-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsection_iterator.go
285 lines (249 loc) · 7.72 KB
/
section_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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
package goip
type singleSegmentsIterator struct {
original []*AddressDivision
}
func (it *singleSegmentsIterator) HasNext() bool {
return it.original != nil
}
func (it *singleSegmentsIterator) Next() (res []*AddressDivision) {
if it.HasNext() {
res = it.original
it.original = nil
}
return
}
type multiSegmentsIterator struct {
done bool
hostSegmentIndex int
networkSegmentIndex int
nextSet []*AddressDivision
variations []Iterator[*AddressSegment]
excludeFunc func([]*AddressDivision) bool
segIteratorProducer func(int) Iterator[*AddressSegment]
hostSegIteratorProducer func(int) Iterator[*AddressSegment]
}
func (it *multiSegmentsIterator) HasNext() bool {
return !it.done
}
func (it *multiSegmentsIterator) updateVariations(start int) {
i := start
nextSet := it.nextSet
variations := it.variations
segIteratorProducer := it.segIteratorProducer
for ; i < it.hostSegmentIndex; i++ {
variations[i] = segIteratorProducer(i)
nextSet[i] = variations[i].Next().ToDiv()
}
if i == it.networkSegmentIndex {
variations[i] = it.hostSegIteratorProducer(i)
nextSet[i] = variations[i].Next().ToDiv()
}
}
func (it *multiSegmentsIterator) increment() (res []*AddressDivision) {
var previousSegs []*AddressDivision
// the current set of segments already holds the next iteration,
// this searches for the set of segments to follow.
variations := it.variations
nextSet := it.nextSet
for j := it.networkSegmentIndex; j >= 0; j-- { // for regular iterators (not prefix block), networkSegmentIndex is last segment (count - 1)
for variations[j].HasNext() {
if previousSegs == nil {
previousSegs = cloneDivs(nextSet)
}
nextSet[j] = variations[j].Next().ToDiv()
it.updateVariations(j + 1)
excludeFunc := it.excludeFunc
if excludeFunc != nil && excludeFunc(nextSet) {
// try again, starting over
j = it.networkSegmentIndex
} else {
return previousSegs
}
}
}
it.done = true
if previousSegs == nil {
// never found set of candidate segments
return nextSet
}
// found a candidate to follow, but was rejected.
// nextSet has that rejected candidate,
// so we must return the set that was created prior to that.
return previousSegs
}
func (it *multiSegmentsIterator) init() {
it.updateVariations(0)
nextSet := it.nextSet
variations := it.variations
divCount := len(variations)
hostSegIteratorProducer := it.hostSegIteratorProducer
// for regular iterators (not prefix block), networkSegmentIndex is last segment (count - 1)
for i := it.networkSegmentIndex + 1; i < divCount; i++ {
variations[i] = hostSegIteratorProducer(i)
nextSet[i] = variations[i].Next().ToDiv()
}
excludeFunc := it.excludeFunc
if excludeFunc != nil && excludeFunc(it.nextSet) {
it.increment()
}
}
func (it *multiSegmentsIterator) Next() (res []*AddressDivision) {
if it.HasNext() {
res = it.increment()
}
return
}
type singleSectionIterator struct {
original *AddressSection
}
func (it *singleSectionIterator) HasNext() bool {
return it.original != nil
}
func (it *singleSectionIterator) Next() (res *AddressSection) {
if it.HasNext() {
res = it.original
it.original = nil
}
return
}
type multiSectionIterator struct {
original *AddressSection
iterator Iterator[[]*AddressDivision]
valsAreMultiple bool
prefixLen PrefixLen
}
func (it *multiSectionIterator) HasNext() bool {
return it.iterator.HasNext()
}
func (it *multiSectionIterator) Next() (res *AddressSection) {
if it.HasNext() {
segs := it.iterator.Next()
original := it.original
res = createSection(segs, it.prefixLen, original.addrType)
res.isMult = it.valsAreMultiple
}
return
}
type prefixSectionIterator struct {
original *AddressSection
iterator Iterator[[]*AddressDivision]
isNotFirst bool
prefixLen PrefixLen
}
func (it *prefixSectionIterator) HasNext() bool {
return it.iterator.HasNext()
}
func (it *prefixSectionIterator) Next() (res *AddressSection) {
if it.HasNext() {
segs := it.iterator.Next()
original := it.original
res = createSection(segs, it.prefixLen, original.addrType)
if !it.isNotFirst {
res.initMultiple() // sets isMultiple
it.isNotFirst = true
} else if !it.HasNext() {
res.initMultiple() // sets isMultiple
} else {
res.isMult = true
}
}
return
}
type ipSectionIterator struct {
Iterator[*AddressSection]
}
func (iter ipSectionIterator) Next() *IPAddressSection {
return iter.Iterator.Next().ToIP()
}
type ipv4SectionIterator struct {
Iterator[*AddressSection]
}
func (iter ipv4SectionIterator) Next() *IPv4AddressSection {
return iter.Iterator.Next().ToIPv4()
}
type ipv6SectionIterator struct {
Iterator[*AddressSection]
}
func (iter ipv6SectionIterator) Next() *IPv6AddressSection {
return iter.Iterator.Next().ToIPv6()
}
type macSectionIterator struct {
Iterator[*AddressSection]
}
func (iter macSectionIterator) Next() *MACAddressSection {
return iter.Iterator.Next().ToMAC()
}
// segmentsIterator used to produce regular iterators with or without zero-host values,
// and prefix block iterators
func segmentsIterator(
divCount int,
segSupplier func() []*AddressDivision,
segIteratorProducer func(int) Iterator[*AddressSegment], // unused at this time, since we do not have a public segments iterator
excludeFunc func([]*AddressDivision) bool, // can be nil
networkSegmentIndex,
hostSegmentIndex int,
hostSegIteratorProducer func(int) Iterator[*AddressSegment]) Iterator[[]*AddressDivision] {
if segSupplier != nil {
return &singleSegmentsIterator{segSupplier()}
}
iterator := &multiSegmentsIterator{
variations: make([]Iterator[*AddressSegment], divCount),
nextSet: make([]*AddressDivision, divCount),
segIteratorProducer: segIteratorProducer,
hostSegIteratorProducer: hostSegIteratorProducer,
networkSegmentIndex: networkSegmentIndex,
hostSegmentIndex: hostSegmentIndex,
excludeFunc: excludeFunc,
}
iterator.init()
return iterator
}
// allSegmentsIterator used by addresses and segment arrays, for iterators that are not prefix or prefix block iterators
func allSegmentsIterator(
divCount int,
segSupplier func() []*AddressDivision, // only useful for a segment iterator. Address/section iterators use address/section for single valued iterator.
segIteratorProducer func(int) Iterator[*AddressSegment],
excludeFunc func([]*AddressDivision) bool, // can be nil
) Iterator[[]*AddressDivision] {
return segmentsIterator(divCount, segSupplier, segIteratorProducer, excludeFunc, divCount-1, divCount, nil)
}
// rangeSegmentsIterator used by sequential ranges
func rangeSegmentsIterator(
divCount int,
segIteratorProducer func(int) Iterator[*AddressSegment],
networkSegmentIndex,
hostSegmentIndex int,
prefixedSegIteratorProducer func(int) Iterator[*AddressSegment]) Iterator[[]*AddressDivision] {
return segmentsIterator(
divCount,
nil,
segIteratorProducer,
nil,
networkSegmentIndex,
hostSegmentIndex,
prefixedSegIteratorProducer)
}
func nilSectIterator() Iterator[*AddressSection] {
return &singleSectionIterator{}
}
func sectIterator(useOriginal bool, original *AddressSection, valsAreMultiple bool, iterator Iterator[[]*AddressDivision]) Iterator[*AddressSection] {
if useOriginal {
return &singleSectionIterator{original: original}
}
return &multiSectionIterator{
original: original,
iterator: iterator,
valsAreMultiple: valsAreMultiple,
prefixLen: original.getPrefixLen(),
}
}
func prefixSectIterator(useOriginal bool, original *AddressSection, iterator Iterator[[]*AddressDivision]) Iterator[*AddressSection] {
if useOriginal {
return &singleSectionIterator{original: original}
}
return &prefixSectionIterator{
original: original,
iterator: iterator,
prefixLen: original.getPrefixLen(),
}
}