]> Cypherpunks repositories - gostls13.git/commitdiff
container/list: Add InsertBefore and InsertAfter methods.
authorDavid Symonds <dsymonds@golang.org>
Wed, 19 Aug 2009 00:49:44 +0000 (17:49 -0700)
committerDavid Symonds <dsymonds@golang.org>
Wed, 19 Aug 2009 00:49:44 +0000 (17:49 -0700)
R=rsc
APPROVED=rsc
DELTA=84  (68 added, 4 deleted, 12 changed)
OCL=33493
CL=33499

src/pkg/container/list/list.go
src/pkg/container/list/list_test.go

index 8ef5641a66d9e5b31ecf17b0d3b5742e91bbbd22..3b77ced59cc508151df61183b0ea752609ab162e 100755 (executable)
@@ -70,31 +70,55 @@ func (l *List) Remove(e *Element) {
        l.len--;
 }
 
-func (l *List) insertFront(e *Element) {
-       e.prev = nil;
-       e.next = l.front;
-       l.front = e;
-       if e.next != nil {
-               e.next.prev = e;
+func (l *List) insertBefore(e *Element, mark *Element) {
+       if mark.prev == nil {
+               // new front of the list
+               l.front = e;
        } else {
-               l.back = e;
+               mark.prev.next = e;
        }
+       e.prev = mark.prev;
+       mark.prev = e;
+       e.next = mark;
        l.len++;
 }
 
-func (l *List) insertBack(e *Element) {
-       e.next = nil;
-       e.prev = l.back;
-       l.back = e;
-       if e.prev != nil {
-               e.prev.next = e;
+func (l *List) insertAfter(e *Element, mark *Element) {
+       if mark.next == nil {
+               // new back of the list
+               l.back = e;
        } else {
-               l.front = e;
+               mark.next.prev = e;
        }
+       e.next = mark.next;
+       mark.next = e;
+       e.prev = mark;
        l.len++;
 }
 
-// PushFront inserts the value at the front of the list, and returns a new Element containing it.
+func (l *List) insertFront(e *Element) {
+       if l.front == nil {
+               // empty list
+               l.front, l.back = e, e;
+               e.prev, e.next = nil, nil;
+               l.len = 1;
+               return
+       }
+       l.insertBefore(e, l.front);
+}
+
+func (l *List) insertBack(e *Element) {
+       if l.back == nil {
+               // empty list
+               l.front, l.back = e, e;
+               e.prev, e.next = nil, nil;
+               l.len = 1;
+               return
+       }
+       l.insertAfter(e, l.back);
+}
+
+// PushFront inserts the value at the front of the list and returns a new Element containing the value.
 func (l *List) PushFront(value interface {}) *Element {
        if l.id == nil {
                l.Init();
@@ -104,7 +128,7 @@ func (l *List) PushFront(value interface {}) *Element {
        return e
 }
 
-// PushBack inserts the value at the back of the list, and returns a new Element containing it.
+// PushBack inserts the value at the back of the list and returns a new Element containing the value.
 func (l *List) PushBack(value interface {}) *Element {
        if l.id == nil {
                l.Init();
@@ -114,6 +138,26 @@ func (l *List) PushBack(value interface {}) *Element {
        return e
 }
 
+// InsertBefore inserts the value immediately before mark and returns a new Element containing the value.
+func (l *List) InsertBefore(value interface {}, mark *Element) *Element {
+       if mark.id != l.id {
+               return nil
+       }
+       e := &Element{ nil, nil, l.id, value };
+       l.insertBefore(e, mark);
+       return e
+}
+
+// InsertAfter inserts the value immediately after mark and returns a new Element containing the value.
+func (l *List) InsertAfter(value interface {}, mark *Element) *Element {
+       if mark.id != l.id {
+               return nil
+       }
+       e := &Element{ nil, nil, l.id, value };
+       l.insertAfter(e, mark);
+       return e
+}
+
 // MoveToFront moves the element to the front of the list.
 func (l *List) MoveToFront(e *Element) {
        if e.id != l.id || l.front == e {
index 7b2480f9cb229f2320aa12937e76ace15825ed45..4a291e9189a76cd6e2007588ee625146793b9432 100755 (executable)
@@ -94,6 +94,26 @@ func TestList(t *testing.T) {
        l.MoveToBack(e3);  // should be no-op
        checkListPointers(t, l, []*Element{ e1, e4, e3 });
 
+       e2 = l.InsertBefore(2, e1);  // insert before front
+       checkListPointers(t, l, []*Element{ e2, e1, e4, e3 });
+       l.Remove(e2);
+       e2 = l.InsertBefore(2, e4);  // insert before middle
+       checkListPointers(t, l, []*Element{ e1, e2, e4, e3 });
+       l.Remove(e2);
+       e2 = l.InsertBefore(2, e3);  // insert before back
+       checkListPointers(t, l, []*Element{ e1, e4, e2, e3 });
+       l.Remove(e2);
+
+       e2 = l.InsertAfter(2, e1);  // insert after front
+       checkListPointers(t, l, []*Element{ e1, e2, e4, e3 });
+       l.Remove(e2);
+       e2 = l.InsertAfter(2, e4);  // insert after middle
+       checkListPointers(t, l, []*Element{ e1, e4, e2, e3 });
+       l.Remove(e2);
+       e2 = l.InsertAfter(2, e3);  // insert after back
+       checkListPointers(t, l, []*Element{ e1, e4, e3, e2 });
+       l.Remove(e2);
+
        // Clear all elements by iterating
        for e := range l.Iter() {
                l.Remove(e);