// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package list implements a doubly linked list. // // To iterate over a list (where l is a *List[T]): // // for e := l.Front(); e != nil; e = e.Next() { // // do something with e.Value // }
package list import func [ any]() *sync.Pool { return &sync.Pool{New: func() any { return &Element[]{} }} } // Element is an element of a linked list. type Element[ any] struct { // Next and previous pointers in the doubly-linked list of elements. // To simplify the implementation, internally a list l is implemented // as a ring, such that &l.root is both the next element of the last // list element (l.Back()) and the previous element of the first list // element (l.Front()). next, prev *Element[] // The list to which this element belongs. list *List[] // The value stored with this element. Value } // Next returns the next list element or nil. func ( *Element[]) () *Element[] { if := .next; .list != nil && != &.list.root { return } return nil } // Prev returns the previous list element or nil. func ( *Element[]) () *Element[] { if := .prev; .list != nil && != &.list.root { return } return nil } func ( *Element[]) () *List[] { return .list } // List represents a doubly linked list. // The zero value for List is an empty list ready to use. type List[ any] struct { root Element[] // sentinel list element, only &root, root.prev, and root.next are used len int // current list length excluding (this) sentinel element pool *sync.Pool } // Init initializes or clears list l. func ( *List[]) () *List[] { .root.next = &.root .root.prev = &.root .len = 0 return } // New returns an initialized list. func [ any]() *List[] { return new(List[]).Init() } // NewWithPool returns an initialized list, using a sync.Pool for list elements. func [ any]( *sync.Pool) *List[] { := &List[]{pool: } return .Init() } // Len returns the number of elements of list l. // The complexity is O(1). func ( *List[]) () int { return .len } // Front returns the first element of list l or nil if the list is empty. func ( *List[]) () *Element[] { if .len == 0 { return nil } return .root.next } // Back returns the last element of list l or nil if the list is empty. func ( *List[]) () *Element[] { if .len == 0 { return nil } return .root.prev } // lazyInit lazily initializes a zero List value. func ( *List[]) () { if .root.next == nil { .Init() } } // insert inserts e after at, increments l.len, and returns e. func ( *List[]) (, *Element[]) *Element[] { .prev = .next = .next .prev.next = .next.prev = .list = .len++ return } // insertValue is a convenience wrapper for insert(&Element{Value: v}, at). func ( *List[]) ( , *Element[]) *Element[] { var *Element[] if .pool != nil { = .pool.Get().(*Element[]) } else { = &Element[]{} } .Value = return .insert(, ) } // remove removes e from its list, decrements l.len func ( *List[]) ( *Element[]) { .prev.next = .next .next.prev = .prev .next = nil // avoid memory leaks .prev = nil // avoid memory leaks .list = nil if .pool != nil { .pool.Put() } .len-- } // move moves e to next to at. func ( *List[]) (, *Element[]) { if == { return } .prev.next = .next .next.prev = .prev .prev = .next = .next .prev.next = .next.prev = } // Remove removes e from l if e is an element of list l. // It returns the element value e.Value. // The element must not be nil. func ( *List[]) ( *Element[]) { := .Value if .list == { // if e.list == l, l must have been initialized when e was inserted // in l or l == nil (e is a zero Element) and l.remove will crash .remove() } return } // PushFront inserts a new element e with value v at the front of list l and returns e. func ( *List[]) ( ) *Element[] { .lazyInit() return .insertValue(, &.root) } // PushBack inserts a new element e with value v at the back of list l and returns e. func ( *List[]) ( ) *Element[] { .lazyInit() return .insertValue(, .root.prev) } // InsertBefore inserts a new element e with value v immediately before mark and returns e. // If mark is not an element of l, the list is not modified. // The mark must not be nil. func ( *List[]) ( , *Element[]) *Element[] { if .list != { return nil } // see comment in List.Remove about initialization of l return .insertValue(, .prev) } // InsertAfter inserts a new element e with value v immediately after mark and returns e. // If mark is not an element of l, the list is not modified. // The mark must not be nil. func ( *List[]) ( , *Element[]) *Element[] { if .list != { return nil } // see comment in List.Remove about initialization of l return .insertValue(, ) } // MoveToFront moves element e to the front of list l. // If e is not an element of l, the list is not modified. // The element must not be nil. func ( *List[]) ( *Element[]) { if .list != || .root.next == { return } // see comment in List.Remove about initialization of l .move(, &.root) } // MoveToBack moves element e to the back of list l. // If e is not an element of l, the list is not modified. // The element must not be nil. func ( *List[]) ( *Element[]) { if .list != || .root.prev == { return } // see comment in List.Remove about initialization of l .move(, .root.prev) } // MoveBefore moves element e to its new position before mark. // If e or mark is not an element of l, or e == mark, the list is not modified. // The element and mark must not be nil. func ( *List[]) (, *Element[]) { if .list != || == || .list != { return } .move(, .prev) } // MoveAfter moves element e to its new position after mark. // If e or mark is not an element of l, or e == mark, the list is not modified. // The element and mark must not be nil. func ( *List[]) (, *Element[]) { if .list != || == || .list != { return } .move(, ) } // PushBackList inserts a copy of another list at the back of list l. // The lists l and other may be the same. They must not be nil. func ( *List[]) ( *List[]) { .lazyInit() for , := .Len(), .Front(); > 0; , = -1, .Next() { .insertValue(.Value, .root.prev) } } // PushFrontList inserts a copy of another list at the front of list l. // The lists l and other may be the same. They must not be nil. func ( *List[]) ( *List[]) { .lazyInit() for , := .Len(), .Back(); > 0; , = -1, .Prev() { .insertValue(.Value, &.root) } }