You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							396 lines
						
					
					
						
							8.6 KiB
						
					
					
				
			
		
		
	
	
							396 lines
						
					
					
						
							8.6 KiB
						
					
					
				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()); | 
						|
};
 | 
						|
 |