Skip to content

Commit dae355f

Browse files
author
Antoine Pelisse
committed
Create map of PathElement to Value and use it instead of Strings
1 parent 55299fe commit dae355f

File tree

2 files changed

+93
-23
lines changed

2 files changed

+93
-23
lines changed

fieldpath/pathelementmap.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package fieldpath
18+
19+
import (
20+
"sort"
21+
22+
"sigs.k8s.io/structured-merge-diff/value"
23+
)
24+
25+
type PathElementValueMap struct {
26+
members sortedPathElementValues
27+
}
28+
29+
type pathElementValue struct {
30+
PathElement PathElement
31+
Value value.Value
32+
}
33+
34+
type sortedPathElementValues []pathElementValue
35+
36+
// Implement the sort interface; this would permit bulk creation, which would
37+
// be faster than doing it one at a time via Insert.
38+
func (spev sortedPathElementValues) Len() int { return len(spev) }
39+
func (spev sortedPathElementValues) Less(i, j int) bool {
40+
return spev[i].PathElement.Less(spev[j].PathElement)
41+
}
42+
func (spev sortedPathElementValues) Swap(i, j int) { spev[i], spev[j] = spev[j], spev[i] }
43+
44+
// Insert adds pe to the set.
45+
func (s *PathElementValueMap) Insert(pe PathElement, v value.Value) {
46+
loc := sort.Search(len(s.members), func(i int) bool {
47+
return !s.members[i].PathElement.Less(pe)
48+
})
49+
if loc == len(s.members) {
50+
s.members = append(s.members, pathElementValue{pe, v})
51+
return
52+
}
53+
if s.members[loc].PathElement.Equals(pe) {
54+
return
55+
}
56+
s.members = append(s.members, pathElementValue{})
57+
copy(s.members[loc+1:], s.members[loc:])
58+
s.members[loc] = pathElementValue{pe, v}
59+
}
60+
61+
func (s *PathElementValueMap) Get(pe PathElement) (value.Value, bool) {
62+
loc := sort.Search(len(s.members), func(i int) bool {
63+
return !s.members[i].PathElement.Less(pe)
64+
})
65+
if loc == len(s.members) {
66+
return value.Value{}, false
67+
}
68+
if s.members[loc].PathElement.Equals(pe) {
69+
return s.members[loc].Value, true
70+
}
71+
return value.Value{}, false
72+
}

typed/merge.go

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
168168
rhsOrder := []fieldpath.PathElement{}
169169

170170
// First, collect all RHS children.
171-
observedRHS := map[string]value.Value{}
171+
observedRHS := fieldpath.PathElementValueMap{}
172172
if rhs != nil {
173173
for i, child := range rhs.Items {
174174
pe, err := listItemToPathElement(t, i, child)
@@ -179,17 +179,16 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
179179
// this element.
180180
continue
181181
}
182-
keyStr := pe.String()
183-
if _, found := observedRHS[keyStr]; found {
184-
errs = append(errs, w.errorf("rhs: duplicate entries for key %v", keyStr)...)
182+
if _, ok := observedRHS.Get(pe); ok {
183+
errs = append(errs, w.errorf("rhs: duplicate entries for key %v", pe.String())...)
185184
}
186-
observedRHS[keyStr] = child
185+
observedRHS.Insert(pe, child)
187186
rhsOrder = append(rhsOrder, pe)
188187
}
189188
}
190189

191190
// Then merge with LHS children.
192-
observedLHS := map[string]struct{}{}
191+
observedLHS := fieldpath.PathElementSet{}
193192
if lhs != nil {
194193
for i, child := range lhs.Items {
195194
pe, err := listItemToPathElement(t, i, child)
@@ -200,15 +199,14 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
200199
// this element.
201200
continue
202201
}
203-
keyStr := pe.String()
204-
if _, found := observedLHS[keyStr]; found {
205-
errs = append(errs, w.errorf("lhs: duplicate entries for key %v", keyStr)...)
202+
if observedLHS.Has(pe) {
203+
errs = append(errs, w.errorf("lhs: duplicate entries for key %v", pe.String())...)
206204
continue
207205
}
208-
observedLHS[keyStr] = struct{}{}
206+
observedLHS.Insert(pe)
209207
w2 := w.prepareDescent(pe, t.ElementType)
210208
w2.lhs = &child
211-
if rchild, ok := observedRHS[keyStr]; ok {
209+
if rchild, ok := observedRHS.Get(pe); ok {
212210
w2.rhs = &rchild
213211
}
214212
if newErrs := w2.merge(); len(newErrs) > 0 {
@@ -217,22 +215,22 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
217215
out.Items = append(out.Items, *w2.out)
218216
}
219217
w.finishDescent(w2)
220-
// Keep track of children that have been handled
221-
delete(observedRHS, keyStr)
222218
}
223219
}
224220

225-
for _, rhsToCheck := range rhsOrder {
226-
if unmergedChild, ok := observedRHS[rhsToCheck.String()]; ok {
227-
w2 := w.prepareDescent(rhsToCheck, t.ElementType)
228-
w2.rhs = &unmergedChild
229-
if newErrs := w2.merge(); len(newErrs) > 0 {
230-
errs = append(errs, newErrs...)
231-
} else if w2.out != nil {
232-
out.Items = append(out.Items, *w2.out)
233-
}
234-
w.finishDescent(w2)
221+
for _, pe := range rhsOrder {
222+
if observedLHS.Has(pe) {
223+
continue
224+
}
225+
value, _ := observedRHS.Get(pe)
226+
w2 := w.prepareDescent(pe, t.ElementType)
227+
w2.rhs = &value
228+
if newErrs := w2.merge(); len(newErrs) > 0 {
229+
errs = append(errs, newErrs...)
230+
} else if w2.out != nil {
231+
out.Items = append(out.Items, *w2.out)
235232
}
233+
w.finishDescent(w2)
236234
}
237235

238236
if len(out.Items) > 0 {

0 commit comments

Comments
 (0)