‘liusuyi’
2023-10-21 94023628bd9c5e6bf724c37371a19b60d338b291
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
'use strict'
 
var util = require('util')
var isNode = require('detect-node')
 
// Node.js 0.8, 0.10 and 0.12 support
Object.assign = (process.versions.modules >= 46 || !isNode)
  ? Object.assign // eslint-disable-next-line
  : util._extend
 
function QueueItem () {
  this.prev = null
  this.next = null
}
exports.QueueItem = QueueItem
 
function Queue () {
  QueueItem.call(this)
 
  this.prev = this
  this.next = this
}
util.inherits(Queue, QueueItem)
exports.Queue = Queue
 
Queue.prototype.insertTail = function insertTail (item) {
  item.prev = this.prev
  item.next = this
  item.prev.next = item
  item.next.prev = item
}
 
Queue.prototype.remove = function remove (item) {
  var next = item.next
  var prev = item.prev
 
  item.next = item
  item.prev = item
  next.prev = prev
  prev.next = next
}
 
Queue.prototype.head = function head () {
  return this.next
}
 
Queue.prototype.tail = function tail () {
  return this.prev
}
 
Queue.prototype.isEmpty = function isEmpty () {
  return this.next === this
}
 
Queue.prototype.isRoot = function isRoot (item) {
  return this === item
}
 
function LockStream (stream) {
  this.locked = false
  this.queue = []
  this.stream = stream
}
exports.LockStream = LockStream
 
LockStream.prototype.write = function write (chunks, callback) {
  var self = this
 
  // Do not let it interleave
  if (this.locked) {
    this.queue.push(function () {
      return self.write(chunks, callback)
    })
    return
  }
 
  this.locked = true
 
  function done (err, chunks) {
    self.stream.removeListener('error', done)
 
    self.locked = false
    if (self.queue.length > 0) { self.queue.shift()() }
    callback(err, chunks)
  }
 
  this.stream.on('error', done)
 
  // Accumulate all output data
  var output = []
  function onData (chunk) {
    output.push(chunk)
  }
  this.stream.on('data', onData)
 
  function next (err) {
    self.stream.removeListener('data', onData)
    if (err) {
      return done(err)
    }
 
    done(null, output)
  }
 
  for (var i = 0; i < chunks.length - 1; i++) { this.stream.write(chunks[i]) }
 
  if (chunks.length > 0) {
    this.stream.write(chunks[i], next)
  } else { process.nextTick(next) }
 
  if (this.stream.execute) {
    this.stream.execute(function (err) {
      if (err) { return done(err) }
    })
  }
}
 
// Just finds the place in array to insert
function binaryLookup (list, item, compare) {
  var start = 0
  var end = list.length
 
  while (start < end) {
    var pos = (start + end) >> 1
    var cmp = compare(item, list[pos])
 
    if (cmp === 0) {
      start = pos
      end = pos
      break
    } else if (cmp < 0) {
      end = pos
    } else {
      start = pos + 1
    }
  }
 
  return start
}
exports.binaryLookup = binaryLookup
 
function binaryInsert (list, item, compare) {
  var index = binaryLookup(list, item, compare)
 
  list.splice(index, 0, item)
}
exports.binaryInsert = binaryInsert
 
function binarySearch (list, item, compare) {
  var index = binaryLookup(list, item, compare)
 
  if (index >= list.length) {
    return -1
  }
 
  if (compare(item, list[index]) === 0) {
    return index
  }
 
  return -1
}
exports.binarySearch = binarySearch
 
function Timeout (object) {
  this.delay = 0
  this.timer = null
  this.object = object
}
exports.Timeout = Timeout
 
Timeout.prototype.set = function set (delay, callback) {
  this.delay = delay
  this.reset()
  if (!callback) { return }
 
  if (this.delay === 0) {
    this.object.removeListener('timeout', callback)
  } else {
    this.object.once('timeout', callback)
  }
}
 
Timeout.prototype.reset = function reset () {
  if (this.timer !== null) {
    clearTimeout(this.timer)
    this.timer = null
  }
 
  if (this.delay === 0) { return }
 
  var self = this
  this.timer = setTimeout(function () {
    self.timer = null
    self.object.emit('timeout')
  }, this.delay)
}