Author: j16sdiz
Date: 2009-02-20 14:28:58 +0000 (Fri, 20 Feb 2009)
New Revision: 25747

Modified:
   trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java
   trunk/freenet/test/freenet/support/DoublyLinkedListImplTest.java
Log:
Clean up DoublyLinkedListImpl internals, prepare for generic (bug 2512)

Instead of keeping a extra "tail" and "head" objects, point to the
actual item. This is essential for generic, as we cannot construct
a generic-ified object for the "tail" and "head".

This pass the JUnit and some insert/request test.

Modified: trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java
===================================================================
--- trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java 2009-02-20 
09:30:07 UTC (rev 25746)
+++ trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java 2009-02-20 
14:28:58 UTC (rev 25747)
@@ -14,7 +14,7 @@
 public class DoublyLinkedListImpl<T> implements DoublyLinkedList<T>{
 
     protected int size;
-    protected DoublyLinkedListImpl.Item<T> _headptr, _tailptr;
+       protected DoublyLinkedList.Item<T> _firstItem, _lastItem;
 
        @Override
     public final DoublyLinkedListImpl<T> clone() {
@@ -25,20 +25,14 @@
      * A new list with no items.
      */
     public DoublyLinkedListImpl() {
-        _headptr = new Item<T>();
-        _tailptr = new Item<T>();
-        _headptr.setParent(this);
-        _tailptr.setParent(this);
         clear();
     }
 
-    protected DoublyLinkedListImpl(DoublyLinkedListImpl.Item<T> _h, 
DoublyLinkedListImpl.Item<T> _t, int size) {
-        _headptr  = _h;
-        _tailptr  = _t;
-        _headptr.setParent(this);
-        _tailptr.setParent(this);
+       protected DoublyLinkedListImpl(DoublyLinkedList.Item<T> _h, 
DoublyLinkedList.Item<T> _t, int size) {
+               _firstItem = _h;
+               _lastItem = _t;
         
-        DoublyLinkedList.Item i = _headptr;
+        DoublyLinkedList.Item i = _firstItem;
         while (i != null ) {
                i.setParent(this);
                i = i.getNext();
@@ -78,10 +72,13 @@
        // Help to detect removal after clear().
        // The check in remove() is enough, strictly,
        // as long as people don't add elements afterwards.
-       DoublyLinkedList.Item<T> pos = _headptr.next;
-       DoublyLinkedList.Item<T> opos = _headptr;
+               if (_firstItem == null)
+                       return;
+
+               DoublyLinkedList.Item<T> pos = _firstItem;
+               DoublyLinkedList.Item<T> opos;
+
        while(true) {
-               if(pos == _tailptr) break;
                if(pos == null) break;
                pos.setParent(null);
                pos.setPrev(null);
@@ -89,8 +86,8 @@
                pos = pos.getNext();
                opos.setNext(null);
        }
-        _headptr.next = _tailptr;
-        _tailptr.prev = _headptr;
+
+               _firstItem = _lastItem = null;
         size = 0;
     }
 
@@ -98,6 +95,7 @@
      * {...@inheritdoc}
      */
     public final int size() {
+               assert size != 0 || (_firstItem == null && _lastItem == null);
         return size;
     }
 
@@ -105,6 +103,7 @@
      * {...@inheritdoc}
      */
     public final boolean isEmpty() {
+               assert size != 0 || (_firstItem == null && _lastItem == null);
         return size == 0;
     }
 
@@ -128,14 +127,14 @@
      * {...@inheritdoc}
      */
     public final DoublyLinkedList.Item<T> head() {
-        return size == 0 ? null : _headptr.next;
+               return size == 0 ? null : _firstItem;
     }
 
     /**
      * {...@inheritdoc}
      */
     public final DoublyLinkedList.Item<T> tail() {
-        return size == 0 ? null : _tailptr.prev;
+               return size == 0 ? null : _lastItem;
     }
 
 
@@ -144,40 +143,38 @@
      * {...@inheritdoc}
      */
     public final void unshift(DoublyLinkedList.Item<T> i) {
-        insertNext(_headptr, i);
+               insertNext(null, i);
     }
     
     /**
      * {...@inheritdoc}
      */
     public final DoublyLinkedList.Item<T> shift() {
-        return size == 0 ? null : remove(_headptr.next);
+               return size == 0 ? null : remove(_firstItem);
     }
     /**
      * {...@inheritdoc}
      */
     public DoublyLinkedList<T> shift(int n) {
-
         if (n > size) n = size;
         if (n < 1) return new DoublyLinkedListImpl<T>();
 
-        DoublyLinkedList.Item<T> i = _headptr;
-        for (int m=0; m<n; ++m)
+               DoublyLinkedList.Item<T> i = _firstItem;
+               for (int m = 0; m < n - 1; ++m)
             i = i.getNext();
 
-        DoublyLinkedList.Item<T> j = i.getNext();
-        Item<T> newheadptr = new Item<T>();
-        Item<T> newtailptr = new Item<T>();
+               DoublyLinkedList.Item<T> newTailItem = i;
+               DoublyLinkedList.Item<T> newFirstItem = newTailItem.getNext();
+               newTailItem.setNext(null);
 
-        j.setPrev(newheadptr);
-        newheadptr.setNext(j);
+               DoublyLinkedList<T> newlist = new 
DoublyLinkedListImpl<T>(_firstItem, newTailItem, n);
 
-        i.setNext(newtailptr);
-        newtailptr.setPrev(i);
-
-        DoublyLinkedList<T> newlist = new DoublyLinkedListImpl<T>(_headptr, 
newtailptr, n);
-        _headptr = newheadptr;
-        _headptr.setParent(this);
+               if (newFirstItem != null) {
+                       newFirstItem.setPrev(null);
+                       _firstItem = newFirstItem;
+               } else {
+                       _firstItem = _lastItem = null;
+               }
         size -= n;
         
         return newlist;
@@ -189,40 +186,38 @@
      * {...@inheritdoc}
      */
     public final void push(DoublyLinkedList.Item<T> i) {
-        insertPrev(_tailptr, i);
+               insertPrev(null, i);
     }
     
     /**
      * {...@inheritdoc}
      */
     public final DoublyLinkedList.Item<T> pop() {
-        return size == 0 ? null : remove(_tailptr.prev);
+               return size == 0 ? null : remove(_lastItem);
     }
+
     /**
      * {...@inheritdoc}
      */
     public DoublyLinkedList<T> pop(int n) {
-
         if (n > size) n = size;
         if (n < 1) return new DoublyLinkedListImpl<T>();
 
-        DoublyLinkedList.Item<T> i = _tailptr;
-        for (int m=0; m<n; ++m)
+               DoublyLinkedList.Item<T> i = _lastItem;
+               for (int m = 0; m < n - 1; ++m)
             i = i.getPrev();
 
-        DoublyLinkedList.Item<T> j = i.getPrev();
-        DoublyLinkedListImpl.Item<T> newtailptr = new Item<T>();
-        DoublyLinkedListImpl.Item<T> newheadptr = new Item<T>();
+               DoublyLinkedList.Item<T> newFirstItem = i;
+               DoublyLinkedList.Item<T> newLastItem = newFirstItem.getPrev();
+               newFirstItem.setPrev(null);
 
-        j.setNext(newtailptr);
-        newtailptr.setPrev(j);
-        newtailptr.setParent(this);
+               DoublyLinkedList<T> newlist = new 
DoublyLinkedListImpl<T>(newFirstItem, _lastItem, n);
 
-        i.setPrev(newheadptr);
-        newheadptr.setNext(i);
-
-        DoublyLinkedList<T> newlist = new DoublyLinkedListImpl<T>(newheadptr, 
_tailptr, n);
-        _tailptr = newtailptr;
+               if (newLastItem != null) {
+                       newLastItem.setNext(null);
+                       _lastItem = newLastItem;
+               } else
+                       _firstItem = _lastItem = null;
         size -= n;
         
         return newlist;
@@ -235,28 +230,28 @@
      */
     public final boolean hasNext(DoublyLinkedList.Item<T> i) {
         DoublyLinkedList.Item<T> next = i.getNext();
-        return (next != null) && (next != _tailptr);
+               return next != null;
     }
     /**
      * {...@inheritdoc}
      */
     public final boolean hasPrev(DoublyLinkedList.Item<T> i) {
         DoublyLinkedList.Item<T> prev = i.getPrev();
-        return (prev != null) && (prev != _headptr);
+               return prev != null;
     }
     /**
      * {...@inheritdoc}
      */
     public final DoublyLinkedList.Item<T> next(DoublyLinkedList.Item<T> i) {
         DoublyLinkedList.Item<T> next = i.getNext();
-        return next == _tailptr ? null : next;
+               return next;
     }
     /**
      * {...@inheritdoc}
      */
     public final DoublyLinkedList.Item<T> prev(DoublyLinkedList.Item<T> i) {
         DoublyLinkedList.Item<T> prev = i.getPrev();
-        return prev == _headptr ? null : prev;
+               return prev;
     }
 
 
@@ -270,17 +265,29 @@
                        return null; // not in list
        if (i.getParent() != this)
                throw new PromiscuousItemException(i, i.getParent());
-        DoublyLinkedList.Item<T> next = i.getNext(), prev = i.getPrev();
-        if ((next == null) && (prev == null)) return null;  // not in the list
-        if ((next == null) || (prev == null))
-               throw new NullPointerException("next="+next+", prev="+prev); // 
partially in the list?!
-        if((next.getPrev() != i) || (prev.getNext() != i)) {
-               String msg = "Illegal ERROR: i="+i+", next="+next+", 
next.prev="+next.getPrev()+", prev="+prev+", prev.next="+prev.getNext();
-               Logger.error(this, msg);
-               throw new IllegalStateException(msg);
+
+               DoublyLinkedList.Item<T> next = i.getNext();
+               DoublyLinkedList.Item<T> prev = i.getPrev();
+
+               if ((next == null) && (prev == null)) // only item in list
+                       assert size == 1;
+
+               if (next == null) { // last item
+                       assert _lastItem == i;
+                       _lastItem = prev;
+               } else {
+                       assert next.getPrev() == i;
+                       next.setPrev(prev);
+               }
+
+               if (prev == null) { // first item
+                       assert _firstItem == i;
+                       _firstItem = next;
+               } else {
+                       assert prev.getNext() == i;
+                       prev.setNext(next);
         }
-        prev.setNext(next);
-        next.setPrev(prev);
+
         i.setNext(null);
         i.setPrev(null);
         --size;
@@ -292,44 +299,86 @@
      * {...@inheritdoc}
      */
     public void insertPrev(DoublyLinkedList.Item<T> i, 
DoublyLinkedList.Item<T> j) {
-       if (i.getParent() == null)
-               throw new PromiscuousItemException(i, i.getParent()); // 
different trace to make easier debugging
-       if (i.getParent() != this)
-               throw new PromiscuousItemException(i, i.getParent());
        if (j.getParent() != null)
                throw new PromiscuousItemException(j, j.getParent());
         if ((j.getNext() != null) || (j.getPrev() != null))
             throw new PromiscuousItemException(j);
-        DoublyLinkedList.Item<T> prev = i.getPrev();
-        if (prev == null)
-            throw new VirginItemException(i);
-        prev.setNext(j);
-        j.setPrev(prev);
-        i.setPrev(j);
-        j.setNext(i);
-        j.setParent(this);
-        ++size;
+
+               if (i == null) {
+                       // insert as tail
+                       j.setPrev(_lastItem);
+                       j.setNext(null);
+                       j.setParent(this);
+                       if (_lastItem != null) {
+                               _lastItem.setNext(j);
+                               _lastItem = j;
+                       } else {
+                               _firstItem = _lastItem = j;
+                       }
+
+                       ++size;
+               } else {
+                       // insert in middle
+                       if (i.getParent() == null)
+                               throw new PromiscuousItemException(i, 
i.getParent()); // different trace to make easier debugging
+                       if (i.getParent() != this)
+                               throw new PromiscuousItemException(i, 
i.getParent());
+                       DoublyLinkedList.Item<T> prev = i.getPrev();
+                       if (prev == null) {
+                               if (i != _firstItem)
+                                       throw new VirginItemException(i);
+                               _firstItem = j;
+                       } else
+                               prev.setNext(j);
+                       j.setPrev(prev);
+                       i.setPrev(j);
+                       j.setNext(i);
+                       j.setParent(this);
+
+                       ++size;
+               }
     }
 
     /**
      * {...@inheritdoc}
      */
     public void insertNext(DoublyLinkedList.Item<T> i, 
DoublyLinkedList.Item<T> j) {
-       if (i.getParent() != this)
-               throw new PromiscuousItemException(i, i.getParent());
        if (j.getParent() != null)
                throw new PromiscuousItemException(j, i.getParent());
         if ((j.getNext() != null) || (j.getPrev() != null))
             throw new PromiscuousItemException(j);
-        DoublyLinkedList.Item next = i.getNext();
-        if (next == null)
-            throw new VirginItemException(i);
-        next.setPrev(j);
-        j.setNext(next);
-        i.setNext(j);
-        j.setPrev(i);
-        j.setParent(this);
-        ++size;
+
+               if (i == null) {
+                       // insert as head
+                       j.setPrev(null);
+                       j.setNext(_firstItem);
+                       j.setParent(this);
+
+                       if (_firstItem != null) {
+                               _firstItem.setPrev(j);
+                               _firstItem = j;
+                       } else {
+                               _firstItem = _lastItem = j;
+                       }
+
+                       ++size;
+               } else {
+                       if (i.getParent() != this)
+                               throw new PromiscuousItemException(i, 
i.getParent());
+                       DoublyLinkedList.Item next = i.getNext();
+                       if (next == null) {
+                               if (i != _lastItem)
+                                       throw new VirginItemException(i);
+                               _lastItem = j;
+                       } else
+                               next.setPrev(j);
+                       j.setNext(next);
+                       i.setNext(j);
+                       j.setPrev(i);
+                       j.setParent(this);
+
+                       ++size;
+               }
     }
 
     //=== Walkable implementation 
==============================================
@@ -348,46 +397,48 @@
         return new ReverseWalker();
     }
 
-    private class ForwardWalker<T extends DoublyLinkedListImpl.Item<T>> 
implements Enumeration<DoublyLinkedList.Item<T>> {
+       private class ForwardWalker implements Enumeration<T> {
         protected DoublyLinkedList.Item<T> next;
         protected ForwardWalker() {
-            next = _headptr.getNext();
+                       next = _firstItem;
         }
         protected ForwardWalker(DoublyLinkedList.Item<T> startAt,
                                 boolean inclusive) {
             next = (inclusive ? startAt : startAt.getNext());
         }
         public final boolean hasMoreElements() {
-            return next != _tailptr;
+                       return next != null;
         }
-        public DoublyLinkedList.Item<T> nextElement() {
-            if (next == _tailptr)
+
+               public T nextElement() {
+                       if (next == null)
                 throw new NoSuchElementException();
             DoublyLinkedList.Item<T> result = next;
             next = next.getNext();
-            return result;
+                       return (T) result;
         }
     }
 
-    private class ReverseWalker<T extends DoublyLinkedList.Item<T>> implements 
Enumeration<DoublyLinkedList.Item<T>> {
+       private class ReverseWalker implements Enumeration<T> {
         protected DoublyLinkedList.Item<T> next;
         protected ReverseWalker() {
-            next = _tailptr.getPrev();
+                       next = _lastItem;
         }
         protected ReverseWalker(DoublyLinkedList.Item<T> startAt,
                                 boolean inclusive) {
             next = (inclusive ? startAt : startAt.getPrev());
         }
         public final boolean hasMoreElements() {
-            return next != _headptr;
+                       return next != null;
         }
-        public DoublyLinkedList.Item<T> nextElement() {
-            if (next == _headptr)
+
+               public T nextElement() {
+                       if (next == null)
                 throw new NoSuchElementException();
             DoublyLinkedList.Item<T> result = next;
            if(next == null) throw new IllegalStateException("next==null");
             next = next.getPrev();
-            return result;
+                       return (T) result;
         }
     }
 

Modified: trunk/freenet/test/freenet/support/DoublyLinkedListImplTest.java
===================================================================
--- trunk/freenet/test/freenet/support/DoublyLinkedListImplTest.java    
2009-02-20 09:30:07 UTC (rev 25746)
+++ trunk/freenet/test/freenet/support/DoublyLinkedListImplTest.java    
2009-02-20 14:28:58 UTC (rev 25747)
@@ -388,6 +388,7 @@
                        fail("PromiscuousItemException");
                } catch (PromiscuousItemException pie) {
                }
+
                try {
                        // item in other list
                        list2.insertPrev(l2, array[3]);
@@ -400,15 +401,20 @@
                        fail("PromiscuousItemException");
                } catch (PromiscuousItemException pie) {
                }
+
+               T l3 = new T(9999);
+               list2.push(l3);
                try {
                        // VirginItemException
-                       list2.insertPrev(l2.getPrev(), new T(8888));
-                       fail("PromiscuousItemException");
+                       l3.setPrev(null); // corrupt it
+                       list2.insertPrev(l3, new T(8888));
+                       fail("VirginItemException");
                } catch (VirginItemException vie) {
                }
                try {
                        // VirginItemException
-                       list2.insertNext(l2.getNext(), new T(8888));
+                       l2.setNext(null); // corrupt it
+                       list2.insertNext(l2, new T(8888));
                        fail("VirginItemException");
                } catch (VirginItemException vie) {
                }

_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to