github.com/gogf/gf@v1.16.9/container/glist/glist.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with l file, 5 // You can obtain one at https://github.com/gogf/gf. 6 // 7 8 // Package glist provides most commonly used doubly linked list container which also supports concurrent-safe/unsafe switch feature. 9 package glist 10 11 import ( 12 "bytes" 13 "container/list" 14 "github.com/gogf/gf/internal/json" 15 "github.com/gogf/gf/util/gconv" 16 17 "github.com/gogf/gf/internal/rwmutex" 18 ) 19 20 type ( 21 // List is a doubly linked list containing a concurrent-safe/unsafe switch. 22 // The switch should be set when its initialization and cannot be changed then. 23 List struct { 24 mu rwmutex.RWMutex 25 list *list.List 26 } 27 // Element the item type of the list. 28 Element = list.Element 29 ) 30 31 // New creates and returns a new empty doubly linked list. 32 func New(safe ...bool) *List { 33 return &List{ 34 mu: rwmutex.Create(safe...), 35 list: list.New(), 36 } 37 } 38 39 // NewFrom creates and returns a list from a copy of given slice <array>. 40 // The parameter <safe> is used to specify whether using list in concurrent-safety, 41 // which is false in default. 42 func NewFrom(array []interface{}, safe ...bool) *List { 43 l := list.New() 44 for _, v := range array { 45 l.PushBack(v) 46 } 47 return &List{ 48 mu: rwmutex.Create(safe...), 49 list: l, 50 } 51 } 52 53 // PushFront inserts a new element <e> with value <v> at the front of list <l> and returns <e>. 54 func (l *List) PushFront(v interface{}) (e *Element) { 55 l.mu.Lock() 56 if l.list == nil { 57 l.list = list.New() 58 } 59 e = l.list.PushFront(v) 60 l.mu.Unlock() 61 return 62 } 63 64 // PushBack inserts a new element <e> with value <v> at the back of list <l> and returns <e>. 65 func (l *List) PushBack(v interface{}) (e *Element) { 66 l.mu.Lock() 67 if l.list == nil { 68 l.list = list.New() 69 } 70 e = l.list.PushBack(v) 71 l.mu.Unlock() 72 return 73 } 74 75 // PushFronts inserts multiple new elements with values <values> at the front of list <l>. 76 func (l *List) PushFronts(values []interface{}) { 77 l.mu.Lock() 78 if l.list == nil { 79 l.list = list.New() 80 } 81 for _, v := range values { 82 l.list.PushFront(v) 83 } 84 l.mu.Unlock() 85 } 86 87 // PushBacks inserts multiple new elements with values <values> at the back of list <l>. 88 func (l *List) PushBacks(values []interface{}) { 89 l.mu.Lock() 90 if l.list == nil { 91 l.list = list.New() 92 } 93 for _, v := range values { 94 l.list.PushBack(v) 95 } 96 l.mu.Unlock() 97 } 98 99 // PopBack removes the element from back of <l> and returns the value of the element. 100 func (l *List) PopBack() (value interface{}) { 101 l.mu.Lock() 102 defer l.mu.Unlock() 103 if l.list == nil { 104 l.list = list.New() 105 return 106 } 107 if e := l.list.Back(); e != nil { 108 value = l.list.Remove(e) 109 } 110 return 111 } 112 113 // PopFront removes the element from front of <l> and returns the value of the element. 114 func (l *List) PopFront() (value interface{}) { 115 l.mu.Lock() 116 defer l.mu.Unlock() 117 if l.list == nil { 118 l.list = list.New() 119 return 120 } 121 if e := l.list.Front(); e != nil { 122 value = l.list.Remove(e) 123 } 124 return 125 } 126 127 // PopBacks removes <max> elements from back of <l> 128 // and returns values of the removed elements as slice. 129 func (l *List) PopBacks(max int) (values []interface{}) { 130 l.mu.Lock() 131 defer l.mu.Unlock() 132 if l.list == nil { 133 l.list = list.New() 134 return 135 } 136 length := l.list.Len() 137 if length > 0 { 138 if max > 0 && max < length { 139 length = max 140 } 141 values = make([]interface{}, length) 142 for i := 0; i < length; i++ { 143 values[i] = l.list.Remove(l.list.Back()) 144 } 145 } 146 return 147 } 148 149 // PopFronts removes <max> elements from front of <l> 150 // and returns values of the removed elements as slice. 151 func (l *List) PopFronts(max int) (values []interface{}) { 152 l.mu.Lock() 153 defer l.mu.Unlock() 154 if l.list == nil { 155 l.list = list.New() 156 return 157 } 158 length := l.list.Len() 159 if length > 0 { 160 if max > 0 && max < length { 161 length = max 162 } 163 values = make([]interface{}, length) 164 for i := 0; i < length; i++ { 165 values[i] = l.list.Remove(l.list.Front()) 166 } 167 } 168 return 169 } 170 171 // PopBackAll removes all elements from back of <l> 172 // and returns values of the removed elements as slice. 173 func (l *List) PopBackAll() []interface{} { 174 return l.PopBacks(-1) 175 } 176 177 // PopFrontAll removes all elements from front of <l> 178 // and returns values of the removed elements as slice. 179 func (l *List) PopFrontAll() []interface{} { 180 return l.PopFronts(-1) 181 } 182 183 // FrontAll copies and returns values of all elements from front of <l> as slice. 184 func (l *List) FrontAll() (values []interface{}) { 185 l.mu.RLock() 186 defer l.mu.RUnlock() 187 if l.list == nil { 188 return 189 } 190 length := l.list.Len() 191 if length > 0 { 192 values = make([]interface{}, length) 193 for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() { 194 values[i] = e.Value 195 } 196 } 197 return 198 } 199 200 // BackAll copies and returns values of all elements from back of <l> as slice. 201 func (l *List) BackAll() (values []interface{}) { 202 l.mu.RLock() 203 defer l.mu.RUnlock() 204 if l.list == nil { 205 return 206 } 207 length := l.list.Len() 208 if length > 0 { 209 values = make([]interface{}, length) 210 for i, e := 0, l.list.Back(); i < length; i, e = i+1, e.Prev() { 211 values[i] = e.Value 212 } 213 } 214 return 215 } 216 217 // FrontValue returns value of the first element of <l> or nil if the list is empty. 218 func (l *List) FrontValue() (value interface{}) { 219 l.mu.RLock() 220 defer l.mu.RUnlock() 221 if l.list == nil { 222 return 223 } 224 if e := l.list.Front(); e != nil { 225 value = e.Value 226 } 227 return 228 } 229 230 // BackValue returns value of the last element of <l> or nil if the list is empty. 231 func (l *List) BackValue() (value interface{}) { 232 l.mu.RLock() 233 defer l.mu.RUnlock() 234 if l.list == nil { 235 return 236 } 237 if e := l.list.Back(); e != nil { 238 value = e.Value 239 } 240 return 241 } 242 243 // Front returns the first element of list <l> or nil if the list is empty. 244 func (l *List) Front() (e *Element) { 245 l.mu.RLock() 246 defer l.mu.RUnlock() 247 if l.list == nil { 248 return 249 } 250 e = l.list.Front() 251 return 252 } 253 254 // Back returns the last element of list <l> or nil if the list is empty. 255 func (l *List) Back() (e *Element) { 256 l.mu.RLock() 257 defer l.mu.RUnlock() 258 if l.list == nil { 259 return 260 } 261 e = l.list.Back() 262 return 263 } 264 265 // Len returns the number of elements of list <l>. 266 // The complexity is O(1). 267 func (l *List) Len() (length int) { 268 l.mu.RLock() 269 defer l.mu.RUnlock() 270 if l.list == nil { 271 return 272 } 273 length = l.list.Len() 274 return 275 } 276 277 // Size is alias of Len. 278 func (l *List) Size() int { 279 return l.Len() 280 } 281 282 // MoveBefore moves element <e> to its new position before <p>. 283 // If <e> or <p> is not an element of <l>, or <e> == <p>, the list is not modified. 284 // The element and <p> must not be nil. 285 func (l *List) MoveBefore(e, p *Element) { 286 l.mu.Lock() 287 defer l.mu.Unlock() 288 if l.list == nil { 289 l.list = list.New() 290 } 291 l.list.MoveBefore(e, p) 292 } 293 294 // MoveAfter moves element <e> to its new position after <p>. 295 // If <e> or <p> is not an element of <l>, or <e> == <p>, the list is not modified. 296 // The element and <p> must not be nil. 297 func (l *List) MoveAfter(e, p *Element) { 298 l.mu.Lock() 299 defer l.mu.Unlock() 300 if l.list == nil { 301 l.list = list.New() 302 } 303 l.list.MoveAfter(e, p) 304 } 305 306 // MoveToFront moves element <e> to the front of list <l>. 307 // If <e> is not an element of <l>, the list is not modified. 308 // The element must not be nil. 309 func (l *List) MoveToFront(e *Element) { 310 l.mu.Lock() 311 defer l.mu.Unlock() 312 if l.list == nil { 313 l.list = list.New() 314 } 315 l.list.MoveToFront(e) 316 } 317 318 // MoveToBack moves element <e> to the back of list <l>. 319 // If <e> is not an element of <l>, the list is not modified. 320 // The element must not be nil. 321 func (l *List) MoveToBack(e *Element) { 322 l.mu.Lock() 323 defer l.mu.Unlock() 324 if l.list == nil { 325 l.list = list.New() 326 } 327 l.list.MoveToBack(e) 328 } 329 330 // PushBackList inserts a copy of an other list at the back of list <l>. 331 // The lists <l> and <other> may be the same, but they must not be nil. 332 func (l *List) PushBackList(other *List) { 333 if l != other { 334 other.mu.RLock() 335 defer other.mu.RUnlock() 336 } 337 l.mu.Lock() 338 defer l.mu.Unlock() 339 if l.list == nil { 340 l.list = list.New() 341 } 342 l.list.PushBackList(other.list) 343 } 344 345 // PushFrontList inserts a copy of an other list at the front of list <l>. 346 // The lists <l> and <other> may be the same, but they must not be nil. 347 func (l *List) PushFrontList(other *List) { 348 if l != other { 349 other.mu.RLock() 350 defer other.mu.RUnlock() 351 } 352 l.mu.Lock() 353 defer l.mu.Unlock() 354 if l.list == nil { 355 l.list = list.New() 356 } 357 l.list.PushFrontList(other.list) 358 } 359 360 // InsertAfter inserts a new element <e> with value <v> immediately after <p> and returns <e>. 361 // If <p> is not an element of <l>, the list is not modified. 362 // The <p> must not be nil. 363 func (l *List) InsertAfter(p *Element, v interface{}) (e *Element) { 364 l.mu.Lock() 365 defer l.mu.Unlock() 366 if l.list == nil { 367 l.list = list.New() 368 } 369 e = l.list.InsertAfter(v, p) 370 return 371 } 372 373 // InsertBefore inserts a new element <e> with value <v> immediately before <p> and returns <e>. 374 // If <p> is not an element of <l>, the list is not modified. 375 // The <p> must not be nil. 376 func (l *List) InsertBefore(p *Element, v interface{}) (e *Element) { 377 l.mu.Lock() 378 defer l.mu.Unlock() 379 if l.list == nil { 380 l.list = list.New() 381 } 382 e = l.list.InsertBefore(v, p) 383 return 384 } 385 386 // Remove removes <e> from <l> if <e> is an element of list <l>. 387 // It returns the element value e.Value. 388 // The element must not be nil. 389 func (l *List) Remove(e *Element) (value interface{}) { 390 l.mu.Lock() 391 defer l.mu.Unlock() 392 if l.list == nil { 393 l.list = list.New() 394 } 395 value = l.list.Remove(e) 396 return 397 } 398 399 // Removes removes multiple elements <es> from <l> if <es> are elements of list <l>. 400 func (l *List) Removes(es []*Element) { 401 l.mu.Lock() 402 defer l.mu.Unlock() 403 if l.list == nil { 404 l.list = list.New() 405 } 406 for _, e := range es { 407 l.list.Remove(e) 408 } 409 return 410 } 411 412 // RemoveAll removes all elements from list <l>. 413 func (l *List) RemoveAll() { 414 l.mu.Lock() 415 l.list = list.New() 416 l.mu.Unlock() 417 } 418 419 // See RemoveAll(). 420 func (l *List) Clear() { 421 l.RemoveAll() 422 } 423 424 // RLockFunc locks reading with given callback function <f> within RWMutex.RLock. 425 func (l *List) RLockFunc(f func(list *list.List)) { 426 l.mu.RLock() 427 defer l.mu.RUnlock() 428 if l.list != nil { 429 f(l.list) 430 } 431 } 432 433 // LockFunc locks writing with given callback function <f> within RWMutex.Lock. 434 func (l *List) LockFunc(f func(list *list.List)) { 435 l.mu.Lock() 436 defer l.mu.Unlock() 437 if l.list == nil { 438 l.list = list.New() 439 } 440 f(l.list) 441 } 442 443 // Iterator is alias of IteratorAsc. 444 func (l *List) Iterator(f func(e *Element) bool) { 445 l.IteratorAsc(f) 446 } 447 448 // IteratorAsc iterates the list readonly in ascending order with given callback function <f>. 449 // If <f> returns true, then it continues iterating; or false to stop. 450 func (l *List) IteratorAsc(f func(e *Element) bool) { 451 l.mu.RLock() 452 defer l.mu.RUnlock() 453 if l.list == nil { 454 return 455 } 456 length := l.list.Len() 457 if length > 0 { 458 for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() { 459 if !f(e) { 460 break 461 } 462 } 463 } 464 } 465 466 // IteratorDesc iterates the list readonly in descending order with given callback function <f>. 467 // If <f> returns true, then it continues iterating; or false to stop. 468 func (l *List) IteratorDesc(f func(e *Element) bool) { 469 l.mu.RLock() 470 defer l.mu.RUnlock() 471 if l.list == nil { 472 return 473 } 474 length := l.list.Len() 475 if length > 0 { 476 for i, e := 0, l.list.Back(); i < length; i, e = i+1, e.Prev() { 477 if !f(e) { 478 break 479 } 480 } 481 } 482 } 483 484 // Join joins list elements with a string <glue>. 485 func (l *List) Join(glue string) string { 486 l.mu.RLock() 487 defer l.mu.RUnlock() 488 if l.list == nil { 489 return "" 490 } 491 buffer := bytes.NewBuffer(nil) 492 length := l.list.Len() 493 if length > 0 { 494 for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() { 495 buffer.WriteString(gconv.String(e.Value)) 496 if i != length-1 { 497 buffer.WriteString(glue) 498 } 499 } 500 } 501 return buffer.String() 502 } 503 504 // String returns current list as a string. 505 func (l *List) String() string { 506 return "[" + l.Join(",") + "]" 507 } 508 509 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 510 func (l *List) MarshalJSON() ([]byte, error) { 511 return json.Marshal(l.FrontAll()) 512 } 513 514 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 515 func (l *List) UnmarshalJSON(b []byte) error { 516 l.mu.Lock() 517 defer l.mu.Unlock() 518 if l.list == nil { 519 l.list = list.New() 520 } 521 var array []interface{} 522 if err := json.UnmarshalUseNumber(b, &array); err != nil { 523 return err 524 } 525 l.PushBacks(array) 526 return nil 527 } 528 529 // UnmarshalValue is an interface implement which sets any type of value for list. 530 func (l *List) UnmarshalValue(value interface{}) (err error) { 531 l.mu.Lock() 532 defer l.mu.Unlock() 533 if l.list == nil { 534 l.list = list.New() 535 } 536 var array []interface{} 537 switch value.(type) { 538 case string, []byte: 539 err = json.UnmarshalUseNumber(gconv.Bytes(value), &array) 540 default: 541 array = gconv.SliceAny(value) 542 } 543 l.PushBacks(array) 544 return err 545 }