1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
package collection
import (
"bytes"
"fmt"
"sync"
)
// List is a dynamically sized list akin to List in the .NET world,
// ArrayList in the Java world, or vector in the C++ world.
type List struct {
underlyer []interface{}
key sync.RWMutex
}
// NewList creates a new list which contains the elements provided.
func NewList(entries ...interface{}) *List {
return &List{
underlyer: entries,
}
}
// Add appends an entry to the logical end of the List.
func (l *List) Add(entries ...interface{}) {
l.key.Lock()
defer l.key.Unlock()
l.underlyer = append(l.underlyer, entries...)
}
// AddAt injects values beginning at `pos`. If multiple values
// are provided in `entries` they are placed in the same order
// they are provided.
func (l *List) AddAt(pos uint, entries ...interface{}) {
l.key.Lock()
defer l.key.Unlock()
l.underlyer = append(l.underlyer[:pos], append(entries, l.underlyer[pos:]...)...)
}
// Enumerate lists each element present in the collection
func (l *List) Enumerate(cancel <-chan struct{}) Enumerator {
retval := make(chan interface{})
go func() {
l.key.RLock()
defer l.key.RUnlock()
defer close(retval)
for _, entry := range l.underlyer {
select {
case retval <- entry:
break
case <-cancel:
return
}
}
}()
return retval
}
// Get retreives the value stored in a particular position of the list.
// If no item exists at the given position, the second parameter will be
// returned as false.
func (l *List) Get(pos uint) (interface{}, bool) {
l.key.RLock()
defer l.key.RUnlock()
if pos > uint(len(l.underlyer)) {
return nil, false
}
return l.underlyer[pos], true
}
// IsEmpty tests to see if this List has any elements present.
func (l *List) IsEmpty() bool {
l.key.RLock()
defer l.key.RUnlock()
return 0 == len(l.underlyer)
}
// Length returns the number of elements in the List.
func (l *List) Length() uint {
l.key.RLock()
defer l.key.RUnlock()
return uint(len(l.underlyer))
}
// Remove retreives a value from this List and shifts all other values.
func (l *List) Remove(pos uint) (interface{}, bool) {
l.key.Lock()
defer l.key.Unlock()
if pos > uint(len(l.underlyer)) {
return nil, false
}
retval := l.underlyer[pos]
l.underlyer = append(l.underlyer[:pos], l.underlyer[pos+1:]...)
return retval, true
}
// Set updates the value stored at a given position in the List.
func (l *List) Set(pos uint, val interface{}) bool {
l.key.Lock()
defer l.key.Unlock()
var retval bool
count := uint(len(l.underlyer))
if pos > count {
retval = false
} else {
l.underlyer[pos] = val
retval = true
}
return retval
}
// String generates a textual representation of the List for the sake of debugging.
func (l *List) String() string {
l.key.RLock()
defer l.key.RUnlock()
builder := bytes.NewBufferString("[")
for i, entry := range l.underlyer {
if i >= 15 {
builder.WriteString("... ")
break
}
builder.WriteString(fmt.Sprintf("%v ", entry))
}
builder.Truncate(builder.Len() - 1)
builder.WriteRune(']')
return builder.String()
}
// Swap switches the values that are stored at positions `x` and `y`
func (l *List) Swap(x, y uint) bool {
l.key.Lock()
defer l.key.Unlock()
return l.swap(x, y)
}
func (l *List) swap(x, y uint) bool {
count := uint(len(l.underlyer))
if x < count && y < count {
temp := l.underlyer[x]
l.underlyer[x] = l.underlyer[y]
l.underlyer[y] = temp
return true
}
return false
}
|