@@ -47,6 +47,56 @@ type PathElement struct {
47
47
Index * int
48
48
}
49
49
50
+ // less provides an order for path elements.
51
+ func (e PathElement ) less (rhs PathElement ) bool {
52
+ // For testing the concept, just use the existing string.
53
+ //return e.String() < rhs.String()
54
+ if e .FieldName != nil {
55
+ if rhs .FieldName == nil {
56
+ return true
57
+ }
58
+ return * e .FieldName < * rhs .FieldName
59
+ } else if rhs .FieldName != nil {
60
+ return false
61
+ }
62
+
63
+ if len (e .Key ) != 0 {
64
+ if len (rhs .Key ) == 0 {
65
+ return true
66
+ }
67
+ return value .FieldCollectionLess (e .Key , rhs .Key )
68
+ } else if len (rhs .Key ) != 0 {
69
+ return false
70
+ }
71
+
72
+ if e .Value != nil {
73
+ if rhs .Value == nil {
74
+ return true
75
+ }
76
+ return e .Value .Less (* rhs .Value )
77
+ } else if rhs .Value != nil {
78
+ return false
79
+ }
80
+
81
+ if e .Index != nil {
82
+ if rhs .Index == nil {
83
+ return true
84
+ }
85
+ return * e .Index < * rhs .Index
86
+ } else if rhs .Index != nil {
87
+ // Yes, I know the next statement is the same. But this way
88
+ // the obvious way of extending the function wil be bug-free.
89
+ return false
90
+ }
91
+
92
+ return false
93
+ }
94
+
95
+ // Equal returns true if both path elements are equal.
96
+ func (e PathElement ) Equal (rhs PathElement ) bool {
97
+ return ! e .less (rhs ) && ! rhs .less (e )
98
+ }
99
+
50
100
// String presents the path element as a human-readable string.
51
101
func (e PathElement ) String () string {
52
102
switch {
@@ -94,60 +144,103 @@ func KeyByFields(nameValues ...interface{}) []value.Field {
94
144
type PathElementSet struct {
95
145
// The strange construction is because there's no way to test
96
146
// PathElements for equality (it can't be used as a key for a map).
97
- members map [ string ] PathElement
147
+ members sortedPathElements
98
148
}
99
149
150
+ type sortedPathElements []PathElement
151
+
152
+ func (spe sortedPathElements ) Len () int { return len (spe ) }
153
+ func (spe sortedPathElements ) Less (i , j int ) bool { return spe [i ].less (spe [j ]) }
154
+ func (spe sortedPathElements ) Swap (i , j int ) { spe [i ], spe [j ] = spe [j ], spe [i ] }
155
+
100
156
// Insert adds pe to the set.
101
157
func (s * PathElementSet ) Insert (pe PathElement ) {
102
- serialized := pe .String ()
103
- if s .members == nil {
104
- s .members = map [string ]PathElement {
105
- serialized : pe ,
106
- }
158
+ loc := sort .Search (len (s .members ), func (i int ) bool {
159
+ //return !pe.less(s.members[i])
160
+ return ! s .members [i ].less (pe )
161
+ })
162
+ if loc == len (s .members ) {
163
+ s .members = append (s .members , pe )
107
164
return
108
165
}
109
- if _ , ok := s .members [serialized ]; ! ok {
110
- s .members [serialized ] = pe
166
+ if s .members [loc ].Equal (pe ) {
167
+ return
168
+ }
169
+ n := len (s .members ) - 1
170
+ s .members = append (s .members , s .members [n ])
171
+ for n > loc {
172
+ s .members [n ] = s .members [n - 1 ]
173
+ n --
111
174
}
175
+ s .members [loc ] = pe
112
176
}
113
177
114
178
// Union returns a set containing elements that appear in either s or s2.
115
179
func (s * PathElementSet ) Union (s2 * PathElementSet ) * PathElementSet {
116
- out := & PathElementSet {
117
- members : map [string ]PathElement {},
180
+ out := & PathElementSet {}
181
+
182
+ i , j := 0 , 0
183
+ for i < len (s .members ) && j < len (s2 .members ) {
184
+ if s .members [i ].less (s2 .members [j ]) {
185
+ out .members = append (out .members , s .members [i ])
186
+ i ++
187
+ } else {
188
+ out .members = append (out .members , s2 .members [j ])
189
+ if ! s2 .members [j ].less (s .members [i ]) {
190
+ i ++
191
+ }
192
+ j ++
193
+ }
118
194
}
119
- for k , v := range s .members {
120
- out .members [k ] = v
195
+
196
+ if i < len (s .members ) {
197
+ out .members = append (out .members , s .members [i :]... )
121
198
}
122
- for k , v := range s2 .members {
123
- out .members [ k ] = v
199
+ if j < len ( s2 .members ) {
200
+ out .members = append ( out . members , s2 . members [ j :] ... )
124
201
}
125
202
return out
126
203
}
127
204
128
205
// Intersection returns a set containing elements which appear in both s and s2.
129
206
func (s * PathElementSet ) Intersection (s2 * PathElementSet ) * PathElementSet {
130
- out := & PathElementSet {
131
- members : map [string ]PathElement {},
132
- }
133
- for k , v := range s .members {
134
- if _ , ok := s2 .members [k ]; ok {
135
- out .members [k ] = v
207
+ out := & PathElementSet {}
208
+
209
+ i , j := 0 , 0
210
+ for i < len (s .members ) && j < len (s2 .members ) {
211
+ if s .members [i ].less (s2 .members [j ]) {
212
+ i ++
213
+ } else {
214
+ if ! s2 .members [j ].less (s .members [i ]) {
215
+ out .members = append (out .members , s .members [i ])
216
+ i ++
217
+ }
218
+ j ++
136
219
}
137
220
}
221
+
138
222
return out
139
223
}
140
224
141
225
// Difference returns a set containing elements which appear in s but not in s2.
142
226
func (s * PathElementSet ) Difference (s2 * PathElementSet ) * PathElementSet {
143
- out := & PathElementSet {
144
- members : map [string ]PathElement {},
145
- }
146
- for k , v := range s .members {
147
- if _ , ok := s2 .members [k ]; ! ok {
148
- out .members [k ] = v
227
+ out := & PathElementSet {}
228
+
229
+ i , j := 0 , 0
230
+ for i < len (s .members ) && j < len (s2 .members ) {
231
+ if s .members [i ].less (s2 .members [j ]) {
232
+ out .members = append (out .members , s .members [i ])
233
+ i ++
234
+ } else {
235
+ if ! s2 .members [j ].less (s .members [i ]) {
236
+ i ++
237
+ }
238
+ j ++
149
239
}
150
240
}
241
+ if i < len (s .members ) {
242
+ out .members = append (out .members , s .members [i :]... )
243
+ }
151
244
return out
152
245
}
153
246
@@ -156,11 +249,17 @@ func (s *PathElementSet) Size() int { return len(s.members) }
156
249
157
250
// Has returns true if pe is a member of the set.
158
251
func (s * PathElementSet ) Has (pe PathElement ) bool {
159
- if s .members == nil {
252
+ loc := sort .Search (len (s .members ), func (i int ) bool {
253
+ return ! s .members [i ].less (pe )
254
+ //return !pe.less(s.members[i])
255
+ })
256
+ if loc == len (s .members ) {
160
257
return false
161
258
}
162
- _ , ok := s .members [pe .String ()]
163
- return ok
259
+ if s .members [loc ].Equal (pe ) {
260
+ return true
261
+ }
262
+ return false
164
263
}
165
264
166
265
// Equals returns true if s and s2 have exactly the same members.
@@ -169,14 +268,14 @@ func (s *PathElementSet) Equals(s2 *PathElementSet) bool {
169
268
return false
170
269
}
171
270
for k := range s .members {
172
- if _ , ok := s2 .members [k ]; ! ok {
271
+ if ! s . members [ k ]. Equal ( s2 .members [k ]) {
173
272
return false
174
273
}
175
274
}
176
275
return true
177
276
}
178
277
179
- // Iterate calls f for each PathElement in the set.
278
+ // Iterate calls f for each PathElement in the set. The order is deterministic.
180
279
func (s * PathElementSet ) Iterate (f func (PathElement )) {
181
280
for _ , pe := range s .members {
182
281
f (pe )
0 commit comments