|
|
- var Buffer = require('buffer').Buffer;
-
- function OffsetBuffer() {
- this.offset = 0;
- this.size = 0;
- this.buffers = [];
- }
- module.exports = OffsetBuffer;
-
- OffsetBuffer.prototype.isEmpty = function isEmpty() {
- return this.size === 0;
- };
-
- OffsetBuffer.prototype.clone = function clone(size) {
- var r = new OffsetBuffer();
- r.offset = this.offset;
- r.size = size;
- r.buffers = this.buffers.slice();
- return r;
- };
-
- OffsetBuffer.prototype.toChunks = function toChunks() {
- if (this.size === 0)
- return [];
-
- // We are going to slice it anyway
- if (this.offset !== 0) {
- this.buffers[0] = this.buffers[0].slice(this.offset);
- this.offset = 0;
- }
-
- var chunks = [ ];
- var off = 0;
- for (var i = 0; off <= this.size && i < this.buffers.length; i++) {
- var buf = this.buffers[i];
- off += buf.length;
-
- // Slice off last buffer
- if (off > this.size) {
- buf = buf.slice(0, buf.length - (off - this.size));
- this.buffers[i] = buf;
- }
-
- chunks.push(buf);
- }
-
- // If some buffers were skipped - trim length
- if (i < this.buffers.length)
- this.buffers.length = i;
-
- return chunks;
- };
-
- OffsetBuffer.prototype.toString = function toString(enc) {
- return this.toChunks().map(function(c) {
- return c.toString(enc);
- }).join('');
- };
-
- OffsetBuffer.prototype.use = function use(buf, off, n) {
- this.buffers = [ buf ];
- this.offset = off;
- this.size = n;
- };
-
- OffsetBuffer.prototype.push = function push(data) {
- // Ignore empty writes
- if (data.length === 0)
- return;
-
- this.size += data.length;
- this.buffers.push(data);
- };
-
- OffsetBuffer.prototype.has = function has(n) {
- return this.size >= n;
- };
-
- OffsetBuffer.prototype.skip = function skip(n) {
- if (this.size === 0)
- return;
-
- this.size -= n;
-
- // Fast case, skip bytes in a first buffer
- if (this.offset + n < this.buffers[0].length) {
- this.offset += n;
- return;
- }
-
- var left = n - (this.buffers[0].length - this.offset);
- this.offset = 0;
-
- for (var shift = 1; left > 0 && shift < this.buffers.length; shift++) {
- var buf = this.buffers[shift];
- if (buf.length > left) {
- this.offset = left;
- break;
- }
- left -= buf.length;
- }
- this.buffers = this.buffers.slice(shift);
- };
-
- OffsetBuffer.prototype.copy = function copy(target, targetOff, off, n) {
- if (this.size === 0)
- return;
- if (off !== 0)
- throw new Error('Unsupported offset in .copy()');
-
- var toff = targetOff;
- var first = this.buffers[0];
- var toCopy = Math.min(n, first.length - this.offset);
- first.copy(target, toff, this.offset, this.offset + toCopy);
-
- toff += toCopy;
- var left = n - toCopy;
- for (var i = 1; left > 0 && i < this.buffers.length; i++) {
- var buf = this.buffers[i];
- var toCopy = Math.min(left, buf.length);
-
- buf.copy(target, toff, 0, toCopy);
-
- toff += toCopy;
- left -= toCopy;
- }
- };
-
- OffsetBuffer.prototype.take = function take(n) {
- if (n === 0)
- return new Buffer(0);
-
- this.size -= n;
-
- // Fast cases
- var first = this.buffers[0].length - this.offset;
- if (first === n) {
- var r = this.buffers.shift();
- if (this.offset !== 0) {
- r = r.slice(this.offset);
- this.offset = 0;
- }
- return r;
- } else if (first > n) {
- var r = this.buffers[0].slice(this.offset, this.offset + n);
- this.offset += n;
- return r;
- }
-
- // Allocate and fill buffer
- var out = new Buffer(n);
- var toOff = 0;
- var startOff = this.offset;
- for (var i = 0; toOff !== n && i < this.buffers.length; i++) {
- var buf = this.buffers[i];
- var toCopy = Math.min(buf.length - startOff, n - toOff);
-
- buf.copy(out, toOff, startOff, startOff + toCopy);
- if (startOff + toCopy < buf.length) {
- this.offset = startOff + toCopy;
- break;
- } else {
- toOff += toCopy;
- startOff = 0;
- }
- }
-
- this.buffers = this.buffers.slice(i);
- if (this.buffers.length === 0)
- this.offset = 0;
-
- return out;
- };
-
- OffsetBuffer.prototype.peekUInt8 = function peekUInt8() {
- return this.buffers[0][this.offset];
- };
-
- OffsetBuffer.prototype.readUInt8 = function readUInt8() {
- this.size -= 1;
- var first = this.buffers[0];
- var r = first[this.offset];
- if (++this.offset === first.length) {
- this.offset = 0;
- this.buffers.shift();
- }
-
- return r;
- };
-
- OffsetBuffer.prototype.readUInt16LE = function readUInt16LE() {
- var first = this.buffers[0];
- this.size -= 2;
-
- var r;
- var shift;
-
- // Fast case - first buffer has all bytes
- if (first.length - this.offset >= 2) {
- r = first.readUInt16LE(this.offset);
- shift = 0;
- this.offset += 2;
-
- // One byte here - one byte there
- } else {
- r = first[this.offset] | (this.buffers[1][0] << 8);
- shift = 1;
- this.offset = 1;
- }
-
- if (this.offset === this.buffers[shift].length) {
- this.offset = 0;
- shift++;
- }
- if (shift !== 0)
- this.buffers = this.buffers.slice(shift);
-
- return r;
- };
-
- OffsetBuffer.prototype.readUInt24LE = function readUInt24LE() {
- var first = this.buffers[0];
-
- var r;
- var shift;
- var firstHas = first.length - this.offset;
-
- // Fast case - first buffer has all bytes
- if (firstHas >= 3) {
- r = first.readUInt16LE(this.offset) | (first[this.offset + 2] << 16);
- shift = 0;
- this.offset += 3;
-
- // First buffer has 2 of 3 bytes
- } else if (firstHas >= 2) {
- r = first.readUInt16LE(this.offset) | (this.buffers[1][0] << 16);
- shift = 1;
- this.offset = 1;
-
- // Slow case: First buffer has 1 of 3 bytes
- } else {
- r = first[this.offset];
- this.offset = 0;
- this.buffers.shift();
- this.size -= 1;
-
- r |= this.readUInt16LE() << 8;
- return r;
- }
-
- this.size -= 3;
- if (this.offset === this.buffers[shift].length) {
- this.offset = 0;
- shift++;
- }
- if (shift !== 0)
- this.buffers = this.buffers.slice(shift);
-
- return r;
- };
-
- OffsetBuffer.prototype.readUInt32LE = function readUInt32LE() {
- var first = this.buffers[0];
-
- var r;
- var shift;
- var firstHas = first.length - this.offset;
-
- // Fast case - first buffer has all bytes
- if (firstHas >= 4) {
- r = first.readUInt32LE(this.offset);
- shift = 0;
- this.offset += 4;
-
- // First buffer has 3 of 4 bytes
- } else if (firstHas >= 3) {
- r = (first.readUInt16LE(this.offset) |
- (first[this.offset + 2] << 16)) +
- (this.buffers[1][0] * 0x1000000);
- shift = 1;
- this.offset = 1;
-
- // Slow case: First buffer has 2 of 4 bytes
- } else if (firstHas >= 2) {
- r = first.readUInt16LE(this.offset);
- this.offset = 0;
- this.buffers.shift();
- this.size -= 2;
-
- r += this.readUInt16LE() * 0x10000;
- return r;
-
- // Slow case: First buffer has 1 of 4 bytes
- } else {
- r = first[this.offset];
- this.offset = 0;
- this.buffers.shift();
- this.size -= 1;
-
- r += this.readUInt24LE() * 0x100;
- return r;
- }
-
- this.size -= 4;
- if (this.offset === this.buffers[shift].length) {
- this.offset = 0;
- shift++;
- }
- if (shift !== 0)
- this.buffers = this.buffers.slice(shift);
-
- return r;
- };
-
- OffsetBuffer.prototype.readUInt16BE = function readUInt16BE() {
- var r = this.readUInt16LE();
-
- return ((r & 0xff) << 8) | (r >> 8);
- };
-
- OffsetBuffer.prototype.readUInt24BE = function readUInt24BE() {
- var r = this.readUInt24LE();
-
- return ((r & 0xff) << 16) | (((r >> 8) & 0xff) << 8) | (r >> 16);
- };
-
- OffsetBuffer.prototype.readUInt32BE = function readUInt32BE() {
- var r = this.readUInt32LE();
-
- return (((r & 0xff) << 24) |
- (((r >>> 8) & 0xff) << 16) |
- (((r >>> 16) & 0xff) << 8) |
- (r >>> 24)) >>> 0;
- };
-
- // Signed number APIs
-
- function signedInt8(num) {
- if (num >= 0x80)
- return -(0xff ^ num) - 1;
- else
- return num;
- }
-
- OffsetBuffer.prototype.peekInt8 = function peekInt8() {
- return signedInt8(this.peekUInt8());
- };
-
- OffsetBuffer.prototype.readInt8 = function readInt8() {
- return signedInt8(this.readUInt8());
- };
-
- function signedInt16(num) {
- if (num >= 0x8000)
- return -(0xffff ^ num) - 1;
- else
- return num;
- }
-
- OffsetBuffer.prototype.readInt16BE = function readInt16BE() {
- return signedInt16(this.readUInt16BE());
- };
-
- OffsetBuffer.prototype.readInt16LE = function readInt16LE() {
- return signedInt16(this.readUInt16LE());
- };
-
- function signedInt24(num) {
- if (num >= 0x800000)
- return -(0xffffff ^ num) - 1;
- else
- return num;
- }
-
- OffsetBuffer.prototype.readInt24BE = function readInt24BE() {
- return signedInt24(this.readUInt24BE());
- };
-
- OffsetBuffer.prototype.readInt24LE = function readInt24LE() {
- return signedInt24(this.readUInt24LE());
- };
-
- function signedInt32(num) {
- if (num >= 0x80000000)
- return -(0xffffffff ^ num) - 1;
- else
- return num;
- }
-
- OffsetBuffer.prototype.readInt32BE = function readInt32BE() {
- return signedInt32(this.readUInt32BE());
- };
-
- OffsetBuffer.prototype.readInt32LE = function readInt32LE() {
- return signedInt32(this.readUInt32LE());
- };
|