summaryrefslogtreecommitdiff
path: root/src/pkg/container/list
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/container/list')
-rw-r--r--src/pkg/container/list/Makefile2
-rw-r--r--src/pkg/container/list/list.go70
-rw-r--r--src/pkg/container/list/list_test.go24
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)
+}