123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- // Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
- //
- // This Source Code Form is subject to the terms of the MIT License.
- // If a copy of the MIT was not distributed with l file,
- // You can obtain one at https://github.com/gogf/gf.
- //
- // Package glist provides most commonly used doubly linked list container which also supports concurrent-safe/unsafe switch feature.
- package glist
- import (
- "bytes"
- "container/list"
- "github.com/gogf/gf/internal/json"
- "github.com/gogf/gf/util/gconv"
- "github.com/gogf/gf/internal/rwmutex"
- )
- type (
- // List is a doubly linked list containing a concurrent-safe/unsafe switch.
- // The switch should be set when its initialization and cannot be changed then.
- List struct {
- mu rwmutex.RWMutex
- list *list.List
- }
- // Element the item type of the list.
- Element = list.Element
- )
- // New creates and returns a new empty doubly linked list.
- func New(safe ...bool) *List {
- return &List{
- mu: rwmutex.Create(safe...),
- list: list.New(),
- }
- }
- // NewFrom creates and returns a list from a copy of given slice <array>.
- // The parameter <safe> is used to specify whether using list in concurrent-safety,
- // which is false in default.
- func NewFrom(array []interface{}, safe ...bool) *List {
- l := list.New()
- for _, v := range array {
- l.PushBack(v)
- }
- return &List{
- mu: rwmutex.Create(safe...),
- list: l,
- }
- }
- // PushFront inserts a new element <e> with value <v> at the front of list <l> and returns <e>.
- func (l *List) PushFront(v interface{}) (e *Element) {
- l.mu.Lock()
- if l.list == nil {
- l.list = list.New()
- }
- e = l.list.PushFront(v)
- l.mu.Unlock()
- return
- }
- // PushBack inserts a new element <e> with value <v> at the back of list <l> and returns <e>.
- func (l *List) PushBack(v interface{}) (e *Element) {
- l.mu.Lock()
- if l.list == nil {
- l.list = list.New()
- }
- e = l.list.PushBack(v)
- l.mu.Unlock()
- return
- }
- // PushFronts inserts multiple new elements with values <values> at the front of list <l>.
- func (l *List) PushFronts(values []interface{}) {
- l.mu.Lock()
- if l.list == nil {
- l.list = list.New()
- }
- for _, v := range values {
- l.list.PushFront(v)
- }
- l.mu.Unlock()
- }
- // PushBacks inserts multiple new elements with values <values> at the back of list <l>.
- func (l *List) PushBacks(values []interface{}) {
- l.mu.Lock()
- if l.list == nil {
- l.list = list.New()
- }
- for _, v := range values {
- l.list.PushBack(v)
- }
- l.mu.Unlock()
- }
- // PopBack removes the element from back of <l> and returns the value of the element.
- func (l *List) PopBack() (value interface{}) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- return
- }
- if e := l.list.Back(); e != nil {
- value = l.list.Remove(e)
- }
- return
- }
- // PopFront removes the element from front of <l> and returns the value of the element.
- func (l *List) PopFront() (value interface{}) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- return
- }
- if e := l.list.Front(); e != nil {
- value = l.list.Remove(e)
- }
- return
- }
- // PopBacks removes <max> elements from back of <l>
- // and returns values of the removed elements as slice.
- func (l *List) PopBacks(max int) (values []interface{}) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- return
- }
- length := l.list.Len()
- if length > 0 {
- if max > 0 && max < length {
- length = max
- }
- values = make([]interface{}, length)
- for i := 0; i < length; i++ {
- values[i] = l.list.Remove(l.list.Back())
- }
- }
- return
- }
- // PopFronts removes <max> elements from front of <l>
- // and returns values of the removed elements as slice.
- func (l *List) PopFronts(max int) (values []interface{}) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- return
- }
- length := l.list.Len()
- if length > 0 {
- if max > 0 && max < length {
- length = max
- }
- values = make([]interface{}, length)
- for i := 0; i < length; i++ {
- values[i] = l.list.Remove(l.list.Front())
- }
- }
- return
- }
- // PopBackAll removes all elements from back of <l>
- // and returns values of the removed elements as slice.
- func (l *List) PopBackAll() []interface{} {
- return l.PopBacks(-1)
- }
- // PopFrontAll removes all elements from front of <l>
- // and returns values of the removed elements as slice.
- func (l *List) PopFrontAll() []interface{} {
- return l.PopFronts(-1)
- }
- // FrontAll copies and returns values of all elements from front of <l> as slice.
- func (l *List) FrontAll() (values []interface{}) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- length := l.list.Len()
- if length > 0 {
- values = make([]interface{}, length)
- for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() {
- values[i] = e.Value
- }
- }
- return
- }
- // BackAll copies and returns values of all elements from back of <l> as slice.
- func (l *List) BackAll() (values []interface{}) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- length := l.list.Len()
- if length > 0 {
- values = make([]interface{}, length)
- for i, e := 0, l.list.Back(); i < length; i, e = i+1, e.Prev() {
- values[i] = e.Value
- }
- }
- return
- }
- // FrontValue returns value of the first element of <l> or nil if the list is empty.
- func (l *List) FrontValue() (value interface{}) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- if e := l.list.Front(); e != nil {
- value = e.Value
- }
- return
- }
- // BackValue returns value of the last element of <l> or nil if the list is empty.
- func (l *List) BackValue() (value interface{}) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- if e := l.list.Back(); e != nil {
- value = e.Value
- }
- return
- }
- // Front returns the first element of list <l> or nil if the list is empty.
- func (l *List) Front() (e *Element) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- e = l.list.Front()
- return
- }
- // Back returns the last element of list <l> or nil if the list is empty.
- func (l *List) Back() (e *Element) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- e = l.list.Back()
- return
- }
- // Len returns the number of elements of list <l>.
- // The complexity is O(1).
- func (l *List) Len() (length int) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- length = l.list.Len()
- return
- }
- // Size is alias of Len.
- func (l *List) Size() int {
- return l.Len()
- }
- // MoveBefore moves element <e> to its new position before <p>.
- // If <e> or <p> is not an element of <l>, or <e> == <p>, the list is not modified.
- // The element and <p> must not be nil.
- func (l *List) MoveBefore(e, p *Element) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- l.list.MoveBefore(e, p)
- }
- // MoveAfter moves element <e> to its new position after <p>.
- // If <e> or <p> is not an element of <l>, or <e> == <p>, the list is not modified.
- // The element and <p> must not be nil.
- func (l *List) MoveAfter(e, p *Element) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- l.list.MoveAfter(e, p)
- }
- // 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 (l *List) MoveToFront(e *Element) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- l.list.MoveToFront(e)
- }
- // 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 (l *List) MoveToBack(e *Element) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- l.list.MoveToBack(e)
- }
- // PushBackList inserts a copy of an other list at the back of list <l>.
- // The lists <l> and <other> may be the same, but they must not be nil.
- func (l *List) PushBackList(other *List) {
- if l != other {
- other.mu.RLock()
- defer other.mu.RUnlock()
- }
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- l.list.PushBackList(other.list)
- }
- // PushFrontList inserts a copy of an other list at the front of list <l>.
- // The lists <l> and <other> may be the same, but they must not be nil.
- func (l *List) PushFrontList(other *List) {
- if l != other {
- other.mu.RLock()
- defer other.mu.RUnlock()
- }
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- l.list.PushFrontList(other.list)
- }
- // InsertAfter inserts a new element <e> with value <v> immediately after <p> and returns <e>.
- // If <p> is not an element of <l>, the list is not modified.
- // The <p> must not be nil.
- func (l *List) InsertAfter(p *Element, v interface{}) (e *Element) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- e = l.list.InsertAfter(v, p)
- return
- }
- // InsertBefore inserts a new element <e> with value <v> immediately before <p> and returns <e>.
- // If <p> is not an element of <l>, the list is not modified.
- // The <p> must not be nil.
- func (l *List) InsertBefore(p *Element, v interface{}) (e *Element) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- e = l.list.InsertBefore(v, p)
- return
- }
- // 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 (l *List) Remove(e *Element) (value interface{}) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- value = l.list.Remove(e)
- return
- }
- // Removes removes multiple elements <es> from <l> if <es> are elements of list <l>.
- func (l *List) Removes(es []*Element) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- for _, e := range es {
- l.list.Remove(e)
- }
- return
- }
- // RemoveAll removes all elements from list <l>.
- func (l *List) RemoveAll() {
- l.mu.Lock()
- l.list = list.New()
- l.mu.Unlock()
- }
- // See RemoveAll().
- func (l *List) Clear() {
- l.RemoveAll()
- }
- // RLockFunc locks reading with given callback function <f> within RWMutex.RLock.
- func (l *List) RLockFunc(f func(list *list.List)) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list != nil {
- f(l.list)
- }
- }
- // LockFunc locks writing with given callback function <f> within RWMutex.Lock.
- func (l *List) LockFunc(f func(list *list.List)) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- f(l.list)
- }
- // Iterator is alias of IteratorAsc.
- func (l *List) Iterator(f func(e *Element) bool) {
- l.IteratorAsc(f)
- }
- // IteratorAsc iterates the list readonly in ascending order with given callback function <f>.
- // If <f> returns true, then it continues iterating; or false to stop.
- func (l *List) IteratorAsc(f func(e *Element) bool) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- length := l.list.Len()
- if length > 0 {
- for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() {
- if !f(e) {
- break
- }
- }
- }
- }
- // IteratorDesc iterates the list readonly in descending order with given callback function <f>.
- // If <f> returns true, then it continues iterating; or false to stop.
- func (l *List) IteratorDesc(f func(e *Element) bool) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return
- }
- length := l.list.Len()
- if length > 0 {
- for i, e := 0, l.list.Back(); i < length; i, e = i+1, e.Prev() {
- if !f(e) {
- break
- }
- }
- }
- }
- // Join joins list elements with a string <glue>.
- func (l *List) Join(glue string) string {
- l.mu.RLock()
- defer l.mu.RUnlock()
- if l.list == nil {
- return ""
- }
- buffer := bytes.NewBuffer(nil)
- length := l.list.Len()
- if length > 0 {
- for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() {
- buffer.WriteString(gconv.String(e.Value))
- if i != length-1 {
- buffer.WriteString(glue)
- }
- }
- }
- return buffer.String()
- }
- // String returns current list as a string.
- func (l *List) String() string {
- return "[" + l.Join(",") + "]"
- }
- // MarshalJSON implements the interface MarshalJSON for json.Marshal.
- func (l *List) MarshalJSON() ([]byte, error) {
- return json.Marshal(l.FrontAll())
- }
- // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
- func (l *List) UnmarshalJSON(b []byte) error {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- var array []interface{}
- if err := json.Unmarshal(b, &array); err != nil {
- return err
- }
- l.PushBacks(array)
- return nil
- }
- // UnmarshalValue is an interface implement which sets any type of value for list.
- func (l *List) UnmarshalValue(value interface{}) (err error) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if l.list == nil {
- l.list = list.New()
- }
- var array []interface{}
- switch value.(type) {
- case string, []byte:
- err = json.Unmarshal(gconv.Bytes(value), &array)
- default:
- array = gconv.SliceAny(value)
- }
- l.PushBacks(array)
- return err
- }
|