-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunion.js
90 lines (82 loc) · 2.13 KB
/
union.js
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
var Cursor = require('./cursor')
var CursorStream = require('./stream')
var cmp = require('./cmp')
function Union (blocks, cursors, reverse, limit) {
// if(vectors.length === 1) {
// return new Cursor(blocks, vectors[0], reverse, limit)
// }
// this.cursors = vectors.map(function (vector) {
// return new Cursor(blocks, vector, reverse)
// })
//
this.cursors = cursors
this.value = 0
this.ended = false
this.matched = false
this.reverse = !!reverse
CursorStream.call(this, limit)
this._blocks = blocks
this.min = 0
}
Union.prototype = new CursorStream()
Union.prototype.ready = function () {
var infinite = this.reverse ? -Infinity : Infinity
this.min = infinite
for(var i = 0; i < this.cursors.length; i++) {
var cursor = this.cursors[i]
cursor.ready() //this line makes it work...
if(!cursor.isEnded()) {
if(!cursor.ready()) return false
this.min = cmp.lt(cursor.value, this.min, this.reverse) ? cursor.value : this.min
}
}
if(this.min == infinite) {
this.ended = true
return false
}
this.value = this.min
return true
}
Union.prototype.next = function () {
if(!this.ready()) throw new Error('next called when not ready')
var min = this.min
this.ready()
var loop = true
while(loop) {
loop = false
for(var i = 0; i < this.cursors.length; i++) {
var cursor = this.cursors[i]
if(!cursor.isEnded() && cmp.lte(cursor.value, min, this.reverse)) {
if(!cursor.ready()) {
return 0
}
cursor.next()
}
}
}
return this.value = min
}
Union.prototype.update = function (cb) {
const self = this
const cursors = this.cursors
var c = 1
var ended = true
for(var i = 0; i < cursors.length; i++) {
var cursor = cursors[i]
if(!cursor.isEnded()) ended = false
if(!cursor.ready() && !cursor.isEnded()) {
c++; cursor.update(done)
}
}
this.ended = ended //only ended when all cursors have ended
done()
function done (_, block) {
if(--c) return
self.ready() //XXX stackoverflow without this.
cb()
}
}
Union.prototype.isEnded = function () {
return this.ended
}
module.exports = Union