summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/go-immutable-radix/raw_iter.go
blob: 04814c1323fb9f377fbb84441534ace2e2701b71 (plain)
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
package iradix

// rawIterator visits each of the nodes in the tree, even the ones that are not
// leaves. It keeps track of the effective path (what a leaf at a given node
// would be called), which is useful for comparing trees.
type rawIterator struct {
	// node is the starting node in the tree for the iterator.
	node *Node

	// stack keeps track of edges in the frontier.
	stack []rawStackEntry

	// pos is the current position of the iterator.
	pos *Node

	// path is the effective path of the current iterator position,
	// regardless of whether the current node is a leaf.
	path string
}

// rawStackEntry is used to keep track of the cumulative common path as well as
// its associated edges in the frontier.
type rawStackEntry struct {
	path  string
	edges edges
}

// Front returns the current node that has been iterated to.
func (i *rawIterator) Front() *Node {
	return i.pos
}

// Path returns the effective path of the current node, even if it's not actually
// a leaf.
func (i *rawIterator) Path() string {
	return i.path
}

// Next advances the iterator to the next node.
func (i *rawIterator) Next() {
	// Initialize our stack if needed.
	if i.stack == nil && i.node != nil {
		i.stack = []rawStackEntry{
			rawStackEntry{
				edges: edges{
					edge{node: i.node},
				},
			},
		}
	}

	for len(i.stack) > 0 {
		// Inspect the last element of the stack.
		n := len(i.stack)
		last := i.stack[n-1]
		elem := last.edges[0].node

		// Update the stack.
		if len(last.edges) > 1 {
			i.stack[n-1].edges = last.edges[1:]
		} else {
			i.stack = i.stack[:n-1]
		}

		// Push the edges onto the frontier.
		if len(elem.edges) > 0 {
			path := last.path + string(elem.prefix)
			i.stack = append(i.stack, rawStackEntry{path, elem.edges})
		}

		i.pos = elem
		i.path = last.path + string(elem.prefix)
		return
	}

	i.pos = nil
	i.path = ""
}