diff options
| author | David Symonds <dsymonds@golang.org> | 2009-08-18 17:49:44 -0700 |
|---|---|---|
| committer | David Symonds <dsymonds@golang.org> | 2009-08-18 17:49:44 -0700 |
| commit | d8a9f8ac9608bc57e8be5db81e580bfa05796346 (patch) | |
| tree | b7b0a073640ab0f0585dfcdafc1ccd20ba228e25 /src | |
| parent | 4fcb7e3f247d269682608204a6d5f8781c975fb0 (diff) | |
| download | golang-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-x | src/pkg/container/list/list.go | 76 | ||||
| -rwxr-xr-x | src/pkg/container/list/list_test.go | 20 |
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); |
