UNPKG

2.21 kBJavaScriptView Raw
1'use strict'
2
3var sorted = require('sorted-array-functions')
4var match = require('./match')
5
6function 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
22function 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
35Iterator.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
53Iterator.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
75Iterator.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
111module.exports = Iterator