-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalues.go
More file actions
327 lines (288 loc) · 8.54 KB
/
values.go
File metadata and controls
327 lines (288 loc) · 8.54 KB
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
package config
import "sync"
//Values provides storage of arbitrary interface{} values referenced by type Key.
//The zero value for Values is not in a valid state, thus Values should be
//created with NewValues().
//Values is safe for use by multiple goroutines.
type Values struct {
lock *sync.RWMutex
root *node
}
//NewValues creates an empty *Values.
func NewValues() *Values {
return &Values{
lock: &sync.RWMutex{},
root: newNode(),
}
}
func newValues(root *node) *Values {
return &Values{
lock: &sync.RWMutex{},
root: root,
}
}
//Merge merges all associations in other into v starting at key.
//To merge other in v at root, use an empty Key for key.
func (v *Values) Merge(key Key, other *Values) bool {
v.lock.Lock()
defer v.lock.Unlock()
changed := false
other.EachKeyValue(func(otherKey Key, value interface{}) {
actualKey := key.Append(otherKey)
changed = v.put(actualKey, value) || changed
})
return changed
}
//EachKeyValue calls visitor with each set Key value association in v.
func (v *Values) EachKeyValue(visitor func(key Key, value interface{})) {
v.lock.RLock()
defer v.lock.RUnlock()
v.root.eachKeyValue(nil, visitor)
}
//Equal determines whether or not v and other contain the exact same set of
//Keys and associated values.
//Comparison on a value by value basis is done with the == operator.
func (v *Values) Equal(other *Values) bool {
v.lock.RLock()
defer v.lock.RUnlock()
other.lock.RLock()
defer other.lock.RUnlock()
return v.root.equal(other.root)
}
//Put adds the key, value association to v.
//changed indicates whether or not this operation changes the set of associations
//in any way.
func (v *Values) Put(key Key, value interface{}) (changed bool) {
v.lock.Lock()
defer v.lock.Unlock()
return v.put(key, value)
}
func (v *Values) put(key Key, value interface{}) bool {
return v.root.put(key, value)
}
//IsEmpty determines whether or not any associated exist in v.
func (v *Values) IsEmpty() bool {
v.lock.RLock()
defer v.lock.RUnlock()
return v.root.isEmpty()
}
//Get returns the value associated with key or nil if the association does not
//exist.
func (v *Values) Get(key Key) (value interface{}) {
value, _ = v.GetOk(key)
return value
}
//GetOk return the value associated with key.
//The return value ok indicates whether or not any value is actually stored at key.
func (v *Values) GetOk(key Key) (value interface{}, ok bool) {
v.lock.RLock()
defer v.lock.RUnlock()
_, found, _ := v.root.findDescendent(nil, key, false, false)
if found == nil {
return nil, false
}
if found.isSet() {
return found.value, true
}
return newValues(found.clone()), true
}
//Clone creates a new Values with all associations copied into the result.
//The individual values are shallow copied into the result.
func (v *Values) Clone() *Values {
v.lock.RLock()
defer v.lock.RUnlock()
return newValues(v.root)
}
//Remove deletes the association stored at key if one exists.
//v is the removed value or nil if nothing was returned, and ok indicated any value
//was actually removed.
func (v *Values) Remove(key Key) (value interface{}, ok bool) {
v.lock.Lock()
defer v.lock.Unlock()
if key.IsEmpty() {
if v.root.isSet() {
result := v.root.value
v.root = newNode()
return result, true
}
return nil, false
}
parent, found, _ := v.root.findDescendent(nil, key, false, false)
if found == nil {
return nil, false
}
var result interface{}
if found.isSet() {
result = found.value
} else {
result = newValues(found)
}
if parent != nil {
delete(parent.children, key[key.Len()-1])
}
return result, true
}
//node is the internal node type for a Values tree.
//It stores the value stored at its location in the tree and links to children node.
type node struct {
//value is the value stored at this location in the tree.
//It may be nil.
//It is determined to be set by the isSet() method.
value interface{}
//children holds the references to this node's child nodes.
//The keys in children are the parts to the larger Key that references a value.
children map[string]*node
}
//newNodeValues creates a *node to value set to value and children set to nil.
func newNodeValue(value interface{}) *node {
n := newNode()
n.value = value
n.children = nil
return n
}
//newNode creates a *node with nil value and empty children.
func newNode() *node {
return &node{
value: nil,
children: map[string]*node{},
}
}
//isEmpty determines whether or not n is empty.
//true if not n.isSet() and length of n.children is 0, false otherwise.
func (n *node) isEmpty() bool {
return !n.isSet() && len(n.children) == 0
}
//isSet determines whether or not n is set (n.values can assumed to be keyed).
//true if n.children is nil, false otherwise.
func (n *node) isSet() bool {
return n.children == nil
}
//put puts value at key within n's subtree or at n if key is empty.
func (n *node) put(key Key, value interface{}) bool {
if key.IsEmpty() {
return n.setValue(value)
}
child, changed := n.findChild(key[0], true)
remainingKey := key[1:]
return child.put(remainingKey, value) || changed
}
//setValue sets n value to value.
//if value is a *Values, then n.setValues(values.(*Values)) is used.
func (n *node) setValue(value interface{}) bool {
if values, ok := value.(*Values); ok {
return n.setValues(values)
}
changed := false
if n.isSet() {
changed = value != n.value
} else {
changed = true
}
n.value = value
n.children = nil
return changed
}
//setValues calls n.put() for each key, value in values.
func (n *node) setValues(values *Values) bool {
if values.IsEmpty() {
if n.isEmpty() {
return false
}
n.value = nil
n.children = nil
return true
}
changed := false
values.EachKeyValue(func(key Key, value interface{}) {
changed = n.put(key, value) || changed
})
return changed
}
//clone returns a cloned n with a shallow copy of n.value and n.children cloned
//via n.cloneChildren().
func (n *node) clone() *node {
return &node{
value: n.value,
children: n.cloneChildren(),
}
}
//cloneChildren returns a new map matching n.children by calling *node.clone()
//on each child in n.children.
func (n *node) cloneChildren() map[string]*node {
if n.children == nil {
return nil
}
result := map[string]*node{}
for key, child := range n.children {
result[key] = child.clone()
}
return result
}
//eachKeyValues calls visitor for each set value in n's subtree.
//key is a Key onto which to append all descdendent keys.
func (n *node) eachKeyValue(key Key, visitor func(key Key, value interface{})) {
if n.isSet() {
visitor(key, n.value)
return
}
for keyPart, childNode := range n.children {
childNode.eachKeyValue(append(NewKey(key...), keyPart), visitor)
}
}
//equal determines if n and other are equal by n.value == other.value and n.childrenEqual(other)
func (n *node) equal(other *node) bool {
return n.value == other.value && n.childrenEqual(other)
}
//childrenEqual determines if n and other's children have the same set of keys
//and all associated child nodes are equal via *node.equal().
func (n *node) childrenEqual(other *node) bool {
if len(n.children) != len(other.children) {
return false
}
for keyPart, child := range n.children {
otherChild, ok := other.children[keyPart]
if !ok || !child.equal(otherChild) {
return false
}
}
return true
}
//findDescendent finds a desired descendent (node at any lower level) and its possible
//parent.
//The parameter parent should be n's parent. This must be ensured by the caller.
func (n *node) findDescendent(parent *node, key Key, canChange, hasChanged bool) (foundParent *node, found *node, changed bool) {
//if there is no more key to look into, then return parent, n, and hasChanged.
if key.IsEmpty() {
return parent, n, hasChanged
}
//find the child at the next part in key, possibly creating or changing with canChange.
child, changed := n.findChild(key[0], canChange)
if child == nil {
return parent, nil, changed
}
//recurse into children.
return child.findDescendent(n, key[1:], canChange, changed || hasChanged)
}
//findChild find a child node of n at keyPart.
//canChange tells findChild if it can modify n.children to modify n.value and or n.children.
//Essentially, canChange being true performs a put, and false performs a get or lookup.
func (n *node) findChild(keyPart string, canChange bool) (*node, bool) {
changed := false
if n.isSet() {
if !canChange {
return nil, false
}
n.value, changed = nil, true
n.children = map[string]*node{}
}
child, ok := n.children[keyPart]
if !ok {
if !canChange {
return nil, false
}
n.children[keyPart] = newNode()
child = n.children[keyPart]
changed = true
}
return child, changed
}