-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmap.go
121 lines (104 loc) · 2.77 KB
/
map.go
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
package immutableMap
import "fmt"
type Object interface{}
type HashCode uint32
type HashFunc func(Object) HashCode
type EqualsFunc func(Object, Object) bool
type MapVisitor func(Object, Object)
type reporter func(message string)
type Map interface {
Assign(key Object, value Object) Map
Get(key Object) Object
Delete(key Object) Map
Keys() Set
Size() int
Iterate() MapIterator
ForEach(v MapVisitor)
checkInvariants(report reporter)
}
type MapIterator interface {
Next() bool
Get() (Object, Object)
}
type mapImpl struct {
hash HashFunc
equals EqualsFunc
root *node
size int
}
type mapIteratorImpl struct {
state *iteratorState
key Object
value Object
}
func (this *mapImpl) withRoot(newRoot *node, delta int) *mapImpl {
newMap := *this
newMap.root = newRoot
newMap.size += delta
return &newMap
}
func CreateMap(hash HashFunc, equals EqualsFunc) Map {
return &mapImpl{hash: hash, equals: equals, root: emptyNode()}
}
func (this *mapImpl) Assign(key Object, value Object) Map {
newRoot, delta := this.root.assign(this.hash(key), key, value, this.equals)
return this.withRoot(newRoot, delta)
}
func (this *mapImpl) Get(key Object) Object {
return this.root.get(this.hash(key), key, this.equals)
}
func (this *mapImpl) Delete(key Object) Map {
newRoot, delta := this.root.delete(this.hash(key), key, this.equals)
if newRoot == nil {
newRoot = emptyNode()
}
return this.withRoot(newRoot, delta)
}
func (this *mapImpl) Keys() Set {
return keysSet(this)
}
func (this *mapImpl) Size() int {
return this.size
}
func (this *mapImpl) Iterate() MapIterator {
return &mapIteratorImpl{state: this.root.createIteratorState(nil)}
}
func (this *mapImpl) ForEach(v MapVisitor) {
this.root.forEach(v)
}
func (this *mapImpl) checkInvariants(report reporter) {
this.root.checkInvariants(this.hash, this.equals, 0, report)
size := 0
for i := this.Iterate(); i.Next(); {
key, expected := i.Get()
actual := this.Get(key)
if expected != actual {
report(fmt.Sprintf("Get returned incorrect result: key=%v expected=%v actual=%v", key, expected, actual))
}
size++
}
if this.size != size {
report(fmt.Sprintf("Size() does not match number of keys in iterator: expected=%d actual=%d", this.size, size))
}
i2 := this.Iterate()
this.ForEach(func(key Object, value Object) {
if !i2.Next() {
report(fmt.Sprintf("Next() returned false in ForEach"))
}
k2, _ := i2.Get()
if !this.equals(k2, key) {
report(fmt.Sprintf("Key mismatch between ForEach and Iterate: expected=%v actual=%v", k2, key))
}
})
}
func (this *mapIteratorImpl) Next() bool {
if this.state == nil {
return false
} else {
this.state, this.key, this.value = this.state.currentNode.next(this.state)
return true
}
}
func (this *mapIteratorImpl) Get() (Object, Object) {
return this.key, this.value
}