func (l *ListHeader) Append(v interface{}) { switch { case l.start == nil: l.start = l.NewListNode(v) l.end = l.start default: tail := chain.Next(l.end) l.end.Link(chain.NEXT_NODE, l.NewListNode(v)) l.end = chain.Next(l.end) l.end.Link(chain.NEXT_NODE, tail) } l.length++ }
func (l *ListHeader) Expand(i, n int) { if i > -1 && i <= l.length { switch { case l == nil: fallthrough case i == l.length: for ; n > 0; n-- { l.Append(l.newListNode()) } case i == 0: l.length = n for ; n > 0; n-- { x := l.newListNode() x.Link(chain.NEXT_NODE, l.start) l.start = x } default: x1 := l.findNode(i - 1) x2 := l.findNode(i) l.length += n for ; n > 0; n-- { x1.Link(chain.NEXT_NODE, l.newListNode()) x1 = chain.Next(x1) } x1.Link(chain.NEXT_NODE, x2) } } }
func (l *ListHeader) Tail() { if n := l.start; n != nil { l.start = chain.Next(n) n.Link(chain.NEXT_NODE, nil) l.length-- } }
// Iterates through the list reducing the nesting of each element which can be flattened. // Elements which are themselves LinearLists will be inlined as part of the containing list and their contained list destroyed. func (l *ListHeader) Flatten() { l.eachNode(func(i int, n chain.Node) { value := n.Content() if h, ok := value.(Flattenable); ok { h.Flatten() } if h, ok := value.(Linkable); ok { switch length := h.Len(); { case length == 0: n.Set(chain.CURRENT_NODE, nil) case length == 1: n.Set(chain.CURRENT_NODE, h.Start().Content()) default: l.length += length - 1 h.End().Link(chain.NEXT_NODE, chain.Next(n)) n.Link(chain.CURRENT_NODE, h.Start()) if n == l.start { l.start = h.Start() } if n == l.end { l.end = h.End() } } } else { n.Set(chain.CURRENT_NODE, value) } }) }
func (l *ListHeader) eachNode(f func(int, chain.Node)) { n := l.start for i := 0; i < l.length; i++ { f(i, n) n = chain.Next(n) } }
func (l ListHeader) equal(o ListHeader) (r bool) { if l.length == o.length { var e Equatable r = true n := l.start x := o.start for i := l.length; r && i > 0; i-- { if e, r = n.(Equatable); r && e.Equal(x) { n = chain.Next(n) x = chain.Next(x) } } } return }
func (l ListHeader) Each(f func(interface{})) { n := l.start for i := l.length; i > 0; i-- { f(n.Content()) n = chain.Next(n) } }
func (l ListHeader) String() (t string) { terms := []string{} l.Each(func(term interface{}) { terms = append(terms, fmt.Sprintf("%v", term)) }) if l.length > 0 && l.start == chain.Next(l.end) { terms = append(terms, "...") } t = strings.Join(terms, " ") t = strings.Replace(t, "()", "nil", -1) t = strings.Replace(t, "<nil>", "nil", -1) return "(" + t + ")" }
// Reverses the order in which elements of a List are traversed func (l *ListHeader) Reverse() { if l != nil { current := l.start l.end = current for i := l.length; i > 0; i-- { next := chain.Next(current) current.Link(chain.NEXT_NODE, l.start) l.start = current current = next } } return }
func TestLinearListString(t *testing.T) { ConfirmFormat := func(l *LinearList, x string) { if s := l.String(); s != x { t.Fatalf("'%v' erroneously serialised as '%v'", x, s) } } ConfirmFormat(&LinearList{}, "()") ConfirmFormat(List(0), "(0)") ConfirmFormat(List(0, nil), "(0 nil)") ConfirmFormat(List(1, List(0, nil)), "(1 (0 nil))") ConfirmFormat(List(1, 0, nil), "(1 0 nil)") c := List(10, List(0, 1, 2, 3)) ConfirmFormat(c, "(10 (0 1 2 3))") ConfirmFormat(chain.Next(c.start).Content().(*LinearList), "(0 1 2 3)") }
// Removes all elements in the range from the list. func (l *LinearList) Delete(from, to int) { if l != nil && l.EnforceBounds(&from, &to) { last_element_index := l.length - 1 switch { case from == 0: switch { case to == 0: l.start = chain.Next(l.start) l.length-- case to == last_element_index: l.start = nil l.end = nil l.length = 0 default: l.start = l.findNode(to + 1) l.length -= to + 1 } case from == last_element_index: l.end = l.findNode(from - 1) l.end.Link(chain.NEXT_NODE, nil) l.length-- case to == last_element_index: l.end = l.findNode(from - 1) l.end.Link(chain.NEXT_NODE, nil) l.length = from case from == to: s := l.findNode(from - 1) s.Link(chain.NEXT_NODE, s.MoveTo(2)) l.length-- default: e := l.findNode(from - 1) e.Link(chain.NEXT_NODE, e.MoveTo(to-from+2)) l.length -= to - from + 1 } } }
func (l *ListHeader) Concatenate(s interface{}) { switch s := s.(type) { case []interface{}: if length := len(s); length > 0 { l.Append(s[0]) if length > 1 { tail := chain.Next(l.end) for _, v := range s[1:] { l.end.Link(chain.NEXT_NODE, l.NewListNode(v)) l.end = chain.Next(l.end) } l.end.Link(chain.NEXT_NODE, tail) l.length += length - 1 } } case Sequence: if length := s.Len(); length > 0 { l.Append(s.At(0)) if length > 1 { tail := chain.Next(l.end) for i := 1; i < length; i++ { l.end.Link(chain.NEXT_NODE, l.NewListNode(s.At(i))) l.end = chain.Next(l.end) } l.end.Link(chain.NEXT_NODE, tail) l.length += length - 1 } } default: switch s := reflect.ValueOf(s); s.Kind() { case reflect.Slice: if length := s.Len(); length > 0 { l.Append(s.Index(0).Interface()) if length > 1 { tail := chain.Next(l.end) for i := 1; i < length; i++ { l.end.Link(chain.NEXT_NODE, l.NewListNode(s.Index(i).Interface())) l.end = chain.Next(l.end) } l.end.Link(chain.NEXT_NODE, tail) l.length += length - 1 } } } } }
// Insert an item into the list at the given location. func (l *LinearList) Insert(i int, o interface{}) { if i > -1 && i <= l.length { switch { case l == nil: fallthrough case i == l.length: l.Append(o) case i == 0: n := l.NewListNode(o) n.Link(chain.NEXT_NODE, l.start) l.start = n l.length++ default: n1 := l.findNode(i - 1) n2 := l.findNode(i) n1.Link(chain.NEXT_NODE, l.NewListNode(o)) chain.Next(n1).Link(chain.NEXT_NODE, n2) l.length++ } } }
func (c *CycList) Rotate(i int) { if c != nil && c.end != nil { c.end = c.end.MoveTo(c.index(i)) c.start = chain.Next(c.end) } }
// Iterate over all elements of the list indefinitely // The only way to terminate iteration is by raising a panic() in the applied function func (c CycList) Cycle(f func(interface{})) { for n := c.start; ; n = chain.Next(n) { f(n.Content()) } }