-
Notifications
You must be signed in to change notification settings - Fork 0
/
iterator.go
143 lines (133 loc) · 2.71 KB
/
iterator.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
* Copyright 2023 SteelBridgeLabs, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
package jsonpath
type Iterator func() (any, bool)
func (it Iterator) ToSlice() []any {
// create slice
values := []any{}
// iterate values
for value, ok := it(); ok; value, ok = it() {
// append value to slice
values = append(values, value)
}
// return slice
return values
}
func (it Iterator) RecurseValues() Iterator {
// stack
var stack []any
// return iterator
return func() (any, bool) {
// result
var value any
var ok bool
// check if stack is empty
if len(stack) > 0 {
// pop
value = stack[len(stack)-1]
stack = stack[:len(stack)-1]
// indicate we have a value
ok = true
} else {
// get next value from iterator
value, ok = it()
if !ok {
// exit
return nil, false
}
}
// process value type, add values to stack if value is a container
switch v := value.(type) {
case []any:
// iterate backwards (debugging and unit test consistency)
for i := len(v) - 1; i >= 0; i-- {
// append to stack
stack = append(stack, v[i])
}
case map[string]any:
// iterate map
loopMap(v, func(_ string, mv any) {
// append to stack
stack = append(stack, mv)
})
case Array:
// backwards iterator (debugging and unit test consistency)
it := v.Values(true)
// loop over values
for iv, ok := it(); ok; iv, ok = it() {
// append to stack
stack = append(stack, iv)
}
case Map:
// iterator
it := v.Values()
// loop over values
for iv, ok := it(); ok; iv, ok = it() {
// append to stack
stack = append(stack, iv)
}
}
return value, ok
}
}
func FromValues(reverse bool, values ...any) Iterator {
// check reverse flag
if reverse {
// initial index
index := len(values) - 1
// return iterator
return func() (any, bool) {
// check if index is out of bounds
if index < 0 {
return nil, false
}
// current value
value := values[index]
// decrement index
index--
// return value
return value, true
}
}
// initial index
index := 0
// return iterator
return func() (any, bool) {
// check if index is out of bounds
if index >= len(values) {
return nil, false
}
// current value
value := values[index]
// increment index
index++
// return value
return value, true
}
}
func FromIterators(its ...Iterator) Iterator {
// return iterator
return func() (any, bool) {
// iterate
for {
// check if there are no more iterators
if len(its) == 0 {
// exit
return nil, false
}
// next iterator
next := its[0]
// evaluate it
vale, ok := next()
// check if iterator is done
if ok {
return vale, true
}
// next iterator
its = its[1:]
}
}
}