Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81145 views
1
var DuplexStream = require('readable-stream/duplex')
2
, util = require('util')
3
4
function BufferList (callback) {
5
if (!(this instanceof BufferList))
6
return new BufferList(callback)
7
8
this._bufs = []
9
this.length = 0
10
11
if (typeof callback == 'function') {
12
this._callback = callback
13
14
var piper = function (err) {
15
if (this._callback) {
16
this._callback(err)
17
this._callback = null
18
}
19
}.bind(this)
20
21
this.on('pipe', function (src) {
22
src.on('error', piper)
23
})
24
this.on('unpipe', function (src) {
25
src.removeListener('error', piper)
26
})
27
}
28
else if (Buffer.isBuffer(callback))
29
this.append(callback)
30
else if (Array.isArray(callback)) {
31
callback.forEach(function (b) {
32
Buffer.isBuffer(b) && this.append(b)
33
}.bind(this))
34
}
35
36
DuplexStream.call(this)
37
}
38
39
util.inherits(BufferList, DuplexStream)
40
41
BufferList.prototype._offset = function (offset) {
42
var tot = 0, i = 0, _t
43
for (; i < this._bufs.length; i++) {
44
_t = tot + this._bufs[i].length
45
if (offset < _t)
46
return [ i, offset - tot ]
47
tot = _t
48
}
49
}
50
51
BufferList.prototype.append = function (buf) {
52
var isBuffer = Buffer.isBuffer(buf) ||
53
buf instanceof BufferList
54
55
this._bufs.push(isBuffer ? buf : new Buffer(buf))
56
this.length += buf.length
57
return this
58
}
59
60
BufferList.prototype._write = function (buf, encoding, callback) {
61
this.append(buf)
62
if (callback)
63
callback()
64
}
65
66
BufferList.prototype._read = function (size) {
67
if (!this.length)
68
return this.push(null)
69
size = Math.min(size, this.length)
70
this.push(this.slice(0, size))
71
this.consume(size)
72
}
73
74
BufferList.prototype.end = function (chunk) {
75
DuplexStream.prototype.end.call(this, chunk)
76
77
if (this._callback) {
78
this._callback(null, this.slice())
79
this._callback = null
80
}
81
}
82
83
BufferList.prototype.get = function (index) {
84
return this.slice(index, index + 1)[0]
85
}
86
87
BufferList.prototype.slice = function (start, end) {
88
return this.copy(null, 0, start, end)
89
}
90
91
BufferList.prototype.copy = function (dst, dstStart, srcStart, srcEnd) {
92
if (typeof srcStart != 'number' || srcStart < 0)
93
srcStart = 0
94
if (typeof srcEnd != 'number' || srcEnd > this.length)
95
srcEnd = this.length
96
if (srcStart >= this.length)
97
return dst || new Buffer(0)
98
if (srcEnd <= 0)
99
return dst || new Buffer(0)
100
101
var copy = !!dst
102
, off = this._offset(srcStart)
103
, len = srcEnd - srcStart
104
, bytes = len
105
, bufoff = (copy && dstStart) || 0
106
, start = off[1]
107
, l
108
, i
109
110
// copy/slice everything
111
if (srcStart === 0 && srcEnd == this.length) {
112
if (!copy) // slice, just return a full concat
113
return Buffer.concat(this._bufs)
114
115
// copy, need to copy individual buffers
116
for (i = 0; i < this._bufs.length; i++) {
117
this._bufs[i].copy(dst, bufoff)
118
bufoff += this._bufs[i].length
119
}
120
121
return dst
122
}
123
124
// easy, cheap case where it's a subset of one of the buffers
125
if (bytes <= this._bufs[off[0]].length - start) {
126
return copy
127
? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes)
128
: this._bufs[off[0]].slice(start, start + bytes)
129
}
130
131
if (!copy) // a slice, we need something to copy in to
132
dst = new Buffer(len)
133
134
for (i = off[0]; i < this._bufs.length; i++) {
135
l = this._bufs[i].length - start
136
137
if (bytes > l) {
138
this._bufs[i].copy(dst, bufoff, start)
139
} else {
140
this._bufs[i].copy(dst, bufoff, start, start + bytes)
141
break
142
}
143
144
bufoff += l
145
bytes -= l
146
147
if (start)
148
start = 0
149
}
150
151
return dst
152
}
153
154
BufferList.prototype.toString = function (encoding, start, end) {
155
return this.slice(start, end).toString(encoding)
156
}
157
158
BufferList.prototype.consume = function (bytes) {
159
while (this._bufs.length) {
160
if (bytes > this._bufs[0].length) {
161
bytes -= this._bufs[0].length
162
this.length -= this._bufs[0].length
163
this._bufs.shift()
164
} else {
165
this._bufs[0] = this._bufs[0].slice(bytes)
166
this.length -= bytes
167
break
168
}
169
}
170
return this
171
}
172
173
BufferList.prototype.duplicate = function () {
174
var i = 0
175
, copy = new BufferList()
176
177
for (; i < this._bufs.length; i++)
178
copy.append(this._bufs[i])
179
180
return copy
181
}
182
183
BufferList.prototype.destroy = function () {
184
this._bufs.length = 0;
185
this.length = 0;
186
this.push(null);
187
}
188
189
;(function () {
190
var methods = {
191
'readDoubleBE' : 8
192
, 'readDoubleLE' : 8
193
, 'readFloatBE' : 4
194
, 'readFloatLE' : 4
195
, 'readInt32BE' : 4
196
, 'readInt32LE' : 4
197
, 'readUInt32BE' : 4
198
, 'readUInt32LE' : 4
199
, 'readInt16BE' : 2
200
, 'readInt16LE' : 2
201
, 'readUInt16BE' : 2
202
, 'readUInt16LE' : 2
203
, 'readInt8' : 1
204
, 'readUInt8' : 1
205
}
206
207
for (var m in methods) {
208
(function (m) {
209
BufferList.prototype[m] = function (offset) {
210
return this.slice(offset, offset + methods[m])[m](0)
211
}
212
}(m))
213
}
214
}())
215
216
module.exports = BufferList
217
218