|
module.exports = Buffers; |
|
|
|
function Buffers (bufs) { |
|
if (!(this instanceof Buffers)) return new Buffers(bufs); |
|
this.buffers = bufs || []; |
|
this.length = this.buffers.reduce(function (size, buf) { |
|
return size + buf.length |
|
}, 0); |
|
} |
|
|
|
Buffers.prototype.push = function () { |
|
for (var i = 0; i < arguments.length; i++) { |
|
if (!Buffer.isBuffer(arguments[i])) { |
|
throw new TypeError('Tried to push a non-buffer'); |
|
} |
|
} |
|
|
|
for (var i = 0; i < arguments.length; i++) { |
|
var buf = arguments[i]; |
|
this.buffers.push(buf); |
|
this.length += buf.length; |
|
} |
|
return this.length; |
|
}; |
|
|
|
Buffers.prototype.unshift = function () { |
|
for (var i = 0; i < arguments.length; i++) { |
|
if (!Buffer.isBuffer(arguments[i])) { |
|
throw new TypeError('Tried to unshift a non-buffer'); |
|
} |
|
} |
|
|
|
for (var i = 0; i < arguments.length; i++) { |
|
var buf = arguments[i]; |
|
this.buffers.unshift(buf); |
|
this.length += buf.length; |
|
} |
|
return this.length; |
|
}; |
|
|
|
Buffers.prototype.copy = function (dst, dStart, start, end) { |
|
return this.slice(start, end).copy(dst, dStart, 0, end - start); |
|
}; |
|
|
|
Buffers.prototype.splice = function (i, howMany) { |
|
var buffers = this.buffers; |
|
var index = i >= 0 ? i : this.length - i; |
|
var reps = [].slice.call(arguments, 2); |
|
|
|
if (howMany === undefined) { |
|
howMany = this.length - index; |
|
} |
|
else if (howMany > this.length - index) { |
|
howMany = this.length - index; |
|
} |
|
|
|
for (var i = 0; i < reps.length; i++) { |
|
this.length += reps[i].length; |
|
} |
|
|
|
var removed = new Buffers(); |
|
var bytes = 0; |
|
|
|
var startBytes = 0; |
|
for ( |
|
var ii = 0; |
|
ii < buffers.length && startBytes + buffers[ii].length < index; |
|
ii ++ |
|
) { startBytes += buffers[ii].length } |
|
|
|
if (index - startBytes > 0) { |
|
var start = index - startBytes; |
|
|
|
if (start + howMany < buffers[ii].length) { |
|
removed.push(buffers[ii].slice(start, start + howMany)); |
|
|
|
var orig = buffers[ii]; |
|
|
|
var buf0 = new Buffer(start); |
|
for (var i = 0; i < start; i++) { |
|
buf0[i] = orig[i]; |
|
} |
|
|
|
var buf1 = new Buffer(orig.length - start - howMany); |
|
for (var i = start + howMany; i < orig.length; i++) { |
|
buf1[ i - howMany - start ] = orig[i] |
|
} |
|
|
|
if (reps.length > 0) { |
|
var reps_ = reps.slice(); |
|
reps_.unshift(buf0); |
|
reps_.push(buf1); |
|
buffers.splice.apply(buffers, [ ii, 1 ].concat(reps_)); |
|
ii += reps_.length; |
|
reps = []; |
|
} |
|
else { |
|
buffers.splice(ii, 1, buf0, buf1); |
|
|
|
ii += 2; |
|
} |
|
} |
|
else { |
|
removed.push(buffers[ii].slice(start)); |
|
buffers[ii] = buffers[ii].slice(0, start); |
|
ii ++; |
|
} |
|
} |
|
|
|
if (reps.length > 0) { |
|
buffers.splice.apply(buffers, [ ii, 0 ].concat(reps)); |
|
ii += reps.length; |
|
} |
|
|
|
while (removed.length < howMany) { |
|
var buf = buffers[ii]; |
|
var len = buf.length; |
|
var take = Math.min(len, howMany - removed.length); |
|
|
|
if (take === len) { |
|
removed.push(buf); |
|
buffers.splice(ii, 1); |
|
} |
|
else { |
|
removed.push(buf.slice(0, take)); |
|
buffers[ii] = buffers[ii].slice(take); |
|
} |
|
} |
|
|
|
this.length -= removed.length; |
|
|
|
return removed; |
|
}; |
|
|
|
Buffers.prototype.slice = function (i, j) { |
|
var buffers = this.buffers; |
|
if (j === undefined) j = this.length; |
|
if (i === undefined) i = 0; |
|
|
|
if (j > this.length) j = this.length; |
|
|
|
var startBytes = 0; |
|
for ( |
|
var si = 0; |
|
si < buffers.length && startBytes + buffers[si].length <= i; |
|
si ++ |
|
) { startBytes += buffers[si].length } |
|
|
|
var target = new Buffer(j - i); |
|
|
|
var ti = 0; |
|
for (var ii = si; ti < j - i && ii < buffers.length; ii++) { |
|
var len = buffers[ii].length; |
|
|
|
var start = ti === 0 ? i - startBytes : 0; |
|
var end = ti + len >= j - i |
|
? Math.min(start + (j - i) - ti, len) |
|
: len |
|
; |
|
|
|
buffers[ii].copy(target, ti, start, end); |
|
ti += end - start; |
|
} |
|
|
|
return target; |
|
}; |
|
|
|
Buffers.prototype.pos = function (i) { |
|
if (i < 0 || i >= this.length) throw new Error('oob'); |
|
var l = i, bi = 0, bu = null; |
|
for (;;) { |
|
bu = this.buffers[bi]; |
|
if (l < bu.length) { |
|
return {buf: bi, offset: l}; |
|
} else { |
|
l -= bu.length; |
|
} |
|
bi++; |
|
} |
|
}; |
|
|
|
Buffers.prototype.get = function get (i) { |
|
var pos = this.pos(i); |
|
|
|
return this.buffers[pos.buf].get(pos.offset); |
|
}; |
|
|
|
Buffers.prototype.set = function set (i, b) { |
|
var pos = this.pos(i); |
|
|
|
return this.buffers[pos.buf].set(pos.offset, b); |
|
}; |
|
|
|
Buffers.prototype.indexOf = function (needle, offset) { |
|
if ("string" === typeof needle) { |
|
needle = new Buffer(needle); |
|
} else if (needle instanceof Buffer) { |
|
|
|
} else { |
|
throw new Error('Invalid type for a search string'); |
|
} |
|
|
|
if (!needle.length) { |
|
return 0; |
|
} |
|
|
|
if (!this.length) { |
|
return -1; |
|
} |
|
|
|
var i = 0, j = 0, match = 0, mstart, pos = 0; |
|
|
|
|
|
if (offset) { |
|
var p = this.pos(offset); |
|
i = p.buf; |
|
j = p.offset; |
|
pos = offset; |
|
} |
|
|
|
|
|
for (;;) { |
|
while (j >= this.buffers[i].length) { |
|
j = 0; |
|
i++; |
|
|
|
if (i >= this.buffers.length) { |
|
|
|
return -1; |
|
} |
|
} |
|
|
|
var char = this.buffers[i][j]; |
|
|
|
if (char == needle[match]) { |
|
|
|
if (match == 0) { |
|
mstart = { |
|
i: i, |
|
j: j, |
|
pos: pos |
|
}; |
|
} |
|
match++; |
|
if (match == needle.length) { |
|
|
|
return mstart.pos; |
|
} |
|
} else if (match != 0) { |
|
|
|
|
|
i = mstart.i; |
|
j = mstart.j; |
|
pos = mstart.pos; |
|
match = 0; |
|
} |
|
|
|
j++; |
|
pos++; |
|
} |
|
}; |
|
|
|
Buffers.prototype.toBuffer = function() { |
|
return this.slice(); |
|
} |
|
|
|
Buffers.prototype.toString = function(encoding, start, end) { |
|
return this.slice(start, end).toString(encoding); |
|
} |
|
|