summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Symonds <dsymonds@golang.org>2009-08-18 17:49:44 -0700
committerDavid Symonds <dsymonds@golang.org>2009-08-18 17:49:44 -0700
commitd8a9f8ac9608bc57e8be5db81e580bfa05796346 (patch)
treeb7b0a073640ab0f0585dfcdafc1ccd20ba228e25 /src
parent4fcb7e3f247d269682608204a6d5f8781c975fb0 (diff)
downloadgolang-d8a9f8ac9608bc57e8be5db81e580bfa05796346.tar.gz
container/list: Add InsertBefore and InsertAfter methods.
R=rsc APPROVED=rsc DELTA=84 (68 added, 4 deleted, 12 changed) OCL=33493 CL=33499
Diffstat (limited to 'src')
-rwxr-xr-xsrc/pkg/container/list/list.go76
-rwxr-xr-xsrc/pkg/container/list/list_test.go20
2 files changed, 80 insertions, 16 deletions
diff --git a/src/pkg/container/list/list.go b/src/pkg/container/list/list.go
index 8ef5641a6..3b77ced59 100755
--- a/src/pkg/container/list/list.go
+++ b/src/pkg/container/list/list.go
@@ -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 {
diff --git a/src/pkg/container/list/list_test.go b/src/pkg/container/list/list_test.go
index 7b2480f9c..4a291e918 100755
--- a/src/pkg/container/list/list_test.go
+++ b/src/pkg/container/list/list_test.go
@@ -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);