| 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()); | 
| }; |