Skip to content

Commit afe6328

Browse files
authored
Merge pull request #22 from tiborvass/fix_walk_delete
Allow calling Delete() inside Walk() and WalkPrefix()
2 parents 6ca3752 + f30034d commit afe6328

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

‎radix.go‎

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ func (t *Tree) WalkPrefix(prefix string, fn WalkFn) {
458458
n := t.root
459459
search := prefix
460460
for {
461-
// Check for key exhaution
461+
// Check for key exhaustion
462462
if len(search) == 0 {
463463
recursiveWalk(n, fn)
464464
return
@@ -467,22 +467,20 @@ func (t *Tree) WalkPrefix(prefix string, fn WalkFn) {
467467
// Look for an edge
468468
n = n.getEdge(search[0])
469469
if n == nil {
470-
break
470+
return
471471
}
472472

473473
// Consume the search prefix
474474
if strings.HasPrefix(search, n.prefix) {
475475
search = search[len(n.prefix):]
476-
477-
} else if strings.HasPrefix(n.prefix, search) {
476+
continue
477+
}
478+
if strings.HasPrefix(n.prefix, search) {
478479
// Child may be under our search prefix
479480
recursiveWalk(n, fn)
480-
return
481-
} else {
482-
break
483481
}
482+
return
484483
}
485-
486484
}
487485

488486
// WalkPath is used to walk the tree, but only visiting nodes
@@ -527,10 +525,27 @@ func recursiveWalk(n *node, fn WalkFn) bool {
527525
}
528526

529527
// Recurse on the children
530-
for _, e := range n.edges {
528+
i := 0
529+
k := len(n.edges) // keeps track of number of edges in previous iteration
530+
for i < k {
531+
e := n.edges[i]
531532
if recursiveWalk(e.node, fn) {
532533
return true
533534
}
535+
// It is a possibility that the WalkFn modified the node we are
536+
// iterating on. If there are no more edges, mergeChild happened,
537+
// so the last edge became the current node n, on which we'll
538+
// iterate one last time.
539+
if len(n.edges) == 0 {
540+
return recursiveWalk(n, fn)
541+
}
542+
// If there are now less edges than in the previous iteration,
543+
// then do not increment the loop index, since the current index
544+
// points to a new edge. Otherwise, get to the next index.
545+
if len(n.edges) >= k {
546+
i++
547+
}
548+
k = len(n.edges)
534549
}
535550
return false
536551
}

‎radix_test.go‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,40 @@ func TestWalkPath(t *testing.T) {
344344
}
345345
}
346346

347+
func TestWalkDelete(t *testing.T) {
348+
r := New()
349+
r.Insert("init0/0", nil)
350+
r.Insert("init0/1", nil)
351+
r.Insert("init0/2", nil)
352+
r.Insert("init0/3", nil)
353+
r.Insert("init1/0", nil)
354+
r.Insert("init1/1", nil)
355+
r.Insert("init1/2", nil)
356+
r.Insert("init1/3", nil)
357+
r.Insert("init2", nil)
358+
359+
deleteFn := func(s string, v interface{}) bool {
360+
r.Delete(s)
361+
return false
362+
}
363+
364+
r.WalkPrefix("init1", deleteFn)
365+
366+
for _, s := range []string{"init0/0", "init0/1", "init0/2", "init0/3", "init2"} {
367+
if _, ok := r.Get(s); !ok {
368+
t.Fatalf("expecting to still find %q", s)
369+
}
370+
}
371+
if n := r.Len(); n != 5 {
372+
t.Fatalf("expected to find exactly 5 nodes, instead found %d: %v", n, r.ToMap())
373+
}
374+
375+
r.Walk(deleteFn)
376+
if n := r.Len(); n != 0 {
377+
t.Fatalf("expected to find exactly 0 nodes, instead found %d: %v", n, r.ToMap())
378+
}
379+
}
380+
347381
// generateUUID is used to generate a random UUID
348382
func generateUUID() string {
349383
buf := make([]byte, 16)

0 commit comments

Comments
 (0)