Commit 6c7e90e7 authored by David Symonds's avatar David Symonds

container/list: Add InsertBefore and InsertAfter methods.

R=rsc
APPROVED=rsc
DELTA=84  (68 added, 4 deleted, 12 changed)
OCL=33493
CL=33499
parent b3062f17
...@@ -70,31 +70,55 @@ func (l *List) Remove(e *Element) { ...@@ -70,31 +70,55 @@ func (l *List) Remove(e *Element) {
l.len--; l.len--;
} }
func (l *List) insertFront(e *Element) { func (l *List) insertBefore(e *Element, mark *Element) {
e.prev = nil; if mark.prev == nil {
e.next = l.front; // new front of the list
l.front = e; l.front = e;
if e.next != nil {
e.next.prev = e;
} else { } else {
l.back = e; mark.prev.next = e;
} }
e.prev = mark.prev;
mark.prev = e;
e.next = mark;
l.len++; l.len++;
} }
func (l *List) insertBack(e *Element) { func (l *List) insertAfter(e *Element, mark *Element) {
e.next = nil; if mark.next == nil {
e.prev = l.back; // new back of the list
l.back = e; l.back = e;
if e.prev != nil {
e.prev.next = e;
} else { } else {
l.front = e; mark.next.prev = e;
} }
e.next = mark.next;
mark.next = e;
e.prev = mark;
l.len++; 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 { func (l *List) PushFront(value interface {}) *Element {
if l.id == nil { if l.id == nil {
l.Init(); l.Init();
...@@ -104,7 +128,7 @@ func (l *List) PushFront(value interface {}) *Element { ...@@ -104,7 +128,7 @@ func (l *List) PushFront(value interface {}) *Element {
return e 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 { func (l *List) PushBack(value interface {}) *Element {
if l.id == nil { if l.id == nil {
l.Init(); l.Init();
...@@ -114,6 +138,26 @@ func (l *List) PushBack(value interface {}) *Element { ...@@ -114,6 +138,26 @@ func (l *List) PushBack(value interface {}) *Element {
return e 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. // MoveToFront moves the element to the front of the list.
func (l *List) MoveToFront(e *Element) { func (l *List) MoveToFront(e *Element) {
if e.id != l.id || l.front == e { if e.id != l.id || l.front == e {
......
...@@ -94,6 +94,26 @@ func TestList(t *testing.T) { ...@@ -94,6 +94,26 @@ func TestList(t *testing.T) {
l.MoveToBack(e3); // should be no-op l.MoveToBack(e3); // should be no-op
checkListPointers(t, l, []*Element{ e1, e4, e3 }); 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 // Clear all elements by iterating
for e := range l.Iter() { for e := range l.Iter() {
l.Remove(e); l.Remove(e);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment