diff options
Diffstat (limited to 'src/pkg/container/list')
-rw-r--r-- | src/pkg/container/list/Makefile | 2 | ||||
-rw-r--r-- | src/pkg/container/list/list.go | 70 | ||||
-rw-r--r-- | src/pkg/container/list/list_test.go | 24 |
3 files changed, 53 insertions, 43 deletions
diff --git a/src/pkg/container/list/Makefile b/src/pkg/container/list/Makefile index 2d5b35715..7fcd5f99a 100644 --- a/src/pkg/container/list/Makefile +++ b/src/pkg/container/list/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include ../../../Make.$(GOARCH) +include ../../../Make.inc TARG=container/list GOFILES=\ diff --git a/src/pkg/container/list/list.go b/src/pkg/container/list/list.go index 40c968099..c1ebcddaa 100644 --- a/src/pkg/container/list/list.go +++ b/src/pkg/container/list/list.go @@ -3,6 +3,12 @@ // license that can be found in the LICENSE file. // The list package implements a doubly linked list. +// +// To iterate over a list (where l is a *List): +// for e := l.Front(); e != nil; e = e.Next() { +// // do something with e.Value +// } +// package list // Element is an element in the linked list. @@ -11,8 +17,8 @@ type Element struct { // The front of the list has prev = nil, and the back has next = nil. next, prev *Element - // A unique ID for the list to which this element belongs. - id *byte + // The list to which this element belongs. + list *List // The contents of this list element. Value interface{} @@ -25,10 +31,10 @@ func (e *Element) Next() *Element { return e.next } func (e *Element) Prev() *Element { return e.prev } // List represents a doubly linked list. +// The zero value for List is an empty list ready to use. type List struct { front, back *Element len int - id *byte } // Init initializes or clears a List. @@ -36,12 +42,11 @@ func (l *List) Init() *List { l.front = nil l.back = nil l.len = 0 - l.id = new(byte) return l } // New returns an initialized list. -func New() *List { return new(List).Init() } +func New() *List { return new(List) } // Front returns the first element in the list. func (l *List) Front() *Element { return l.front } @@ -49,9 +54,19 @@ func (l *List) Front() *Element { return l.front } // Back returns the last element in the list. func (l *List) Back() *Element { return l.back } -// Remove removes the element from the list. -func (l *List) Remove(e *Element) { - if e.id != l.id { +// Remove removes the element from the list +// and returns its Value. +func (l *List) Remove(e *Element) interface{} { + l.remove(e) + e.list = nil // do what remove does not + return e.Value +} + +// remove the element from the list, but do not clear the Element's list field. +// This is so that other List methods may use remove when relocating Elements +// without needing to restore the list field. +func (l *List) remove(e *Element) { + if e.list != l { return } if e.prev == nil { @@ -120,78 +135,59 @@ func (l *List) insertBack(e *Element) { // 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() - } - e := &Element{nil, nil, l.id, value} + e := &Element{nil, nil, l, value} l.insertFront(e) return e } // 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() - } - e := &Element{nil, nil, l.id, value} + e := &Element{nil, nil, l, value} l.insertBack(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 { + if mark.list != l { return nil } - e := &Element{nil, nil, l.id, value} + e := &Element{nil, nil, l, 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 { + if mark.list != l { return nil } - e := &Element{nil, nil, l.id, value} + e := &Element{nil, nil, l, 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 { + if e.list != l || l.front == e { return } - l.Remove(e) + l.remove(e) l.insertFront(e) } // MoveToBack moves the element to the back of the list. func (l *List) MoveToBack(e *Element) { - if e.id != l.id || l.back == e { + if e.list != l || l.back == e { return } - l.Remove(e) + l.remove(e) l.insertBack(e) } // Len returns the number of elements in the list. func (l *List) Len() int { return l.len } -func (l *List) iterate(c chan<- interface{}) { - for e := l.front; e != nil; e = e.next { - c <- e.Value - } - close(c) -} - -func (l *List) Iter() <-chan interface{} { - c := make(chan interface{}) - go l.iterate(c) - return c -} - // PushBackList inserts each element of ol at the back of the list. func (l *List) PushBackList(ol *List) { last := ol.Back() diff --git a/src/pkg/container/list/list_test.go b/src/pkg/container/list/list_test.go index bf35c9dd9..1d44ff84e 100644 --- a/src/pkg/container/list/list_test.go +++ b/src/pkg/container/list/list_test.go @@ -23,8 +23,7 @@ func checkListPointers(t *testing.T, l *List, es []*Element) { t.Errorf("l.back = %v, want %v", l.back, last) } - for i := 0; i < len(es); i++ { - e := es[i] + for i, e := range es { var e_prev, e_next *Element = nil, nil if i > 0 { e_prev = es[i-1] @@ -116,8 +115,8 @@ func TestList(t *testing.T) { // Check standard iteration. sum := 0 - for e := range l.Iter() { - if i, ok := e.(int); ok { + for e := l.Front(); e != nil; e = e.Next() { + if i, ok := e.Value.(int); ok { sum += i } } @@ -141,7 +140,8 @@ func checkList(t *testing.T, l *List, es []interface{}) { return } i := 0 - for le := range l.Iter() { + for e := l.Front(); e != nil; e = e.Next() { + le := e.Value.(int) if le != es[i] { t.Errorf("elt #%d has value=%v, want %v", i, le, es[i]) } @@ -193,3 +193,17 @@ func TestExtending(t *testing.T) { l1.PushFrontList(l3) checkList(t, l1, []interface{}{1, 2, 3}) } + +func TestRemove(t *testing.T) { + l := New() + e1 := l.PushBack(1) + e2 := l.PushBack(2) + checkListPointers(t, l, []*Element{e1, e2}) + e := l.Front() + l.Remove(e) + checkListPointers(t, l, []*Element{e2}) + checkListLen(t, l, 1) + l.Remove(e) + checkListPointers(t, l, []*Element{e2}) + checkListLen(t, l, 1) +} |