diff --git a/vtm-tests/test/org/oscim/utils/pool/InlistTest.java b/vtm-tests/test/org/oscim/utils/pool/InlistTest.java new file mode 100644 index 00000000..0e3ac8ef --- /dev/null +++ b/vtm-tests/test/org/oscim/utils/pool/InlistTest.java @@ -0,0 +1,86 @@ +package org.oscim.utils.pool; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Assert; +import org.junit.Test; +import org.oscim.utils.pool.Inlist.List; + +public class InlistTest { + + @Test + public void shouldWork() { + List list = new List(); + + list.reverse(); + assertNull(list.pop()); + + list.push(new Thing(1)); + list.push(new Thing(2)); + list.push(new Thing(3)); + list.push(new Thing(4)); + list.push(new Thing(5)); + + /* iterate items */ + int i = 5; + for (Thing it : list) + assertEquals(it.value, i--); + + assertEquals(i, 0); + + /* iterate with insertion order */ + list.reverse(); + i = 1; + for (Thing it : list) + assertEquals(it.value, i++); + + assertEquals(i, 6); + + list.reverse(); + + List list2 = new List(); + + /* pop list and append to list2 */ + for (int j = 5; j > 0; j--) { + Thing t = list.pop(); + assertEquals(t.value, j); + Assert.assertNull(t.next); + + list2.append(t); + } + + /* check nothing to iterate */ + for (Thing t : list) + assert (t == null && t != null); + + assertNull(list.pop()); + assertNull(list.head()); + + list.push(new Thing(6)); + + /* move items from list2 to list */ + list.appendList(list2.clear()); + + assertNull(list2.head()); + assertNull(list2.pop()); + + list.reverse(); + + list.push(new Thing(0)); + i = 0; + for (Thing t : list) + assertEquals(t.value, i++); + + assertEquals(i, 7); + } + + static class Thing extends Inlist { + final int value; + + public Thing(int val) { + value = val; + } + }; + +} diff --git a/vtm/src/org/oscim/renderer/elements/SymbolLayer.java b/vtm/src/org/oscim/renderer/elements/SymbolLayer.java index 06187488..40d12edb 100644 --- a/vtm/src/org/oscim/renderer/elements/SymbolLayer.java +++ b/vtm/src/org/oscim/renderer/elements/SymbolLayer.java @@ -82,7 +82,7 @@ public final class SymbolLayer extends TextureLayer { textures = null; TextureItem t = null; - for (SymbolItem it = mSymbols.getHead(); it != null;) { + for (SymbolItem it = mSymbols.head(); it != null;) { int width = 0, height = 0; int x = 0; int y = 0; diff --git a/vtm/src/org/oscim/utils/pool/Inlist.java b/vtm/src/org/oscim/utils/pool/Inlist.java index d2bfca4e..03b17ecd 100644 --- a/vtm/src/org/oscim/utils/pool/Inlist.java +++ b/vtm/src/org/oscim/utils/pool/Inlist.java @@ -29,53 +29,85 @@ import javax.annotation.CheckReturnValue; * are *REALLY* sure about it. Better do not use it! :) */ public class Inlist> { - /** UNTESTED */ @SuppressWarnings({ "rawtypes", "unchecked" }) - public static class List> implements Iterable { - Inlist head; - Inlist cur; - Iterator mIterator = new Iterator() { - - @Override - public boolean hasNext() { - return cur != null; - } - - @Override - public T next() { - if (cur == null) - throw new IllegalStateException(); - - Inlist tmp = cur; - cur = cur.next; - return (T) tmp; - } - - @Override - public void remove() { - T tmp = (T) cur.next; - head = Inlist.remove(head, cur); - cur = tmp; - } - }; - - @Override - public Iterator iterator() { - cur = head; - return mIterator; - } + public static class List> implements Iterable, Iterator { + private Inlist head; + private Inlist cur; + /** + * Insert single item at start of list. + * item.next must be null. + */ public void push(T it) { + if (it.next != null) + throw new IllegalArgumentException("item.next must be null"); + ((Inlist) it).next = head; head = it; } + /** + * Insert item at start of list. + */ + public T pop() { + if (head == null) + return null; + + Inlist it = head; + head = it.next; + it.next = null; + return (T) it; + } + + /** + * Reverse list. + */ + public void reverse() { + Inlist tmp; + Inlist itr = head; + head = null; + + while (itr != null) { + /* keep next */ + tmp = itr.next; + + /* push itr onto new list */ + itr.next = head; + head = itr; + + itr = tmp; + } + } + + /** + * Append item, O(n) - use push() and + * reverse() to iterate in insertion order! + */ + public void append(T it) { + head = Inlist.appendItem(head, it); + } + + /** + * Append Inlist. + */ + public void appendList(T list) { + head = Inlist.appendList(head, list); + } + + /** + * Remove item from list. + */ public void remove(T it) { cur = null; head = Inlist.remove(head, it); } + /** + * Clear list. + * + * @return head of list + */ public T clear() { Inlist ret = head; head = null; @@ -83,17 +115,46 @@ public class Inlist> { return (T) ret; } - public T getHead() { + /** @return first node in list */ + public T head() { return (T) head; } + + /** Iterator: Has next item */ + @Override + public boolean hasNext() { + return cur != null; + } + + /** Iterator: Get next item */ + @Override + public T next() { + if (cur == null) + throw new IllegalStateException(); + + Inlist tmp = cur; + cur = cur.next; + return (T) tmp; + } + + /** Iterator: Remove current item */ + @Override + public void remove() { + T tmp = (T) cur.next; + head = Inlist.remove(head, cur); + cur = tmp; + } + + /** NB: Only one iterator at a time possible! */ + @Override + public Iterator iterator() { + cur = head; + return this; + } } public T next; - public T next() { - return next; - } - /** * Push 'item' onto 'list'. * @@ -101,9 +162,10 @@ public class Inlist> { * @param item the item * @return the new head of 'list' (item) */ + @SuppressWarnings({ "unchecked", "rawtypes" }) @CheckReturnValue - public static > T push(T list, T item) { - item.next = list; + public static > T push(T list, T item) { + ((Inlist) (item)).next = list; return item; } @@ -215,7 +277,7 @@ public class Inlist> { it.next = other; break; } else if (it.next == other) { - throw new IllegalArgumentException("'other' alreay in 'list'"); + throw new IllegalArgumentException("'other' already in 'list'"); } } @@ -273,4 +335,8 @@ public class Inlist> { return list; } + + public T next() { + return next; + } }