1 | 'use strict'
|
2 |
|
3 | var sorted = require('sorted-array-functions')
|
4 | var match = require('./match')
|
5 |
|
6 | function Iterator (parent, obj, asMatch) {
|
7 | this.parent = parent
|
8 | this.pattern = obj
|
9 | this._asMatch = asMatch
|
10 | this.buckets = []
|
11 | this.visited = this.bucket = null
|
12 | if (obj) {
|
13 | loop(obj, parent._tree, this.buckets, parent._algo)
|
14 | } else {
|
15 | this.buckets = parent._buckets
|
16 | }
|
17 | var r = parent._regexBucket
|
18 | this.i = this.k = 0
|
19 | this.regexpBucket = r.data.length > 0 && r
|
20 | }
|
21 |
|
22 | function loop (obj, tree, keys, algo) {
|
23 | var magic = 0
|
24 | var branch
|
25 |
|
26 | for (var key in obj) {
|
27 | branch = tree[key]
|
28 | if (branch && branch[obj[key]]) {
|
29 | magic = branch[obj[key]]
|
30 | sorted.add(keys, magic, algo)
|
31 | }
|
32 | }
|
33 | }
|
34 |
|
35 | Iterator.prototype.nextBucket = function () {
|
36 | var bucket = this.bucket
|
37 | var regexpBucket = this.regexpBucket
|
38 |
|
39 | if (!bucket) {
|
40 | bucket = this.buckets[this.i++]
|
41 |
|
42 | if (!bucket && regexpBucket) {
|
43 | bucket = regexpBucket
|
44 | this.regexpBucket = null
|
45 | }
|
46 |
|
47 | this.bucket = bucket
|
48 | }
|
49 |
|
50 | return bucket
|
51 | }
|
52 |
|
53 | Iterator.prototype.one = function () {
|
54 | var result = null
|
55 | var bucket = null
|
56 | var pattern = this.pattern
|
57 | var asMatch = this._asMatch
|
58 |
|
59 | while (result === null && (bucket = this.nextBucket())) {
|
60 | var current = bucket.data[this.k]
|
61 |
|
62 | if (!pattern || match(current.pattern, pattern)) {
|
63 | result = asMatch ? asMatch(current) : current.payload
|
64 | }
|
65 |
|
66 | if (++this.k === bucket.data.length) {
|
67 | this.bucket = null
|
68 | this.k = 0
|
69 | }
|
70 | }
|
71 |
|
72 | return result
|
73 | }
|
74 |
|
75 | Iterator.prototype.next = function () {
|
76 | var result = null
|
77 | var bucket = null
|
78 | var current = null
|
79 | var pattern = this.pattern
|
80 | var asMatch = this._asMatch
|
81 |
|
82 | if (!this.visited) {
|
83 | this.visited = new Set()
|
84 | }
|
85 |
|
86 | var visited = this.visited
|
87 |
|
88 | while (result === null) {
|
89 | bucket = this.nextBucket()
|
90 |
|
91 | if (!bucket) {
|
92 | return null
|
93 | }
|
94 |
|
95 | current = bucket.data[this.k]
|
96 |
|
97 | if (!visited.has(current) && (!pattern || match(current.pattern, pattern))) {
|
98 | visited.add(current)
|
99 | result = asMatch ? asMatch(current) : current.payload
|
100 | }
|
101 |
|
102 | if (++this.k === bucket.data.length) {
|
103 | this.bucket = null
|
104 | this.k = 0
|
105 | }
|
106 | }
|
107 |
|
108 | return result
|
109 | }
|
110 |
|
111 | module.exports = Iterator
|