flocore/lib/bufferreader.js
Ryan X. Charles 8e959426e2 support reading varInt nums up to js precision
Javascript only supports 64 bit floating points, which have uint precision up
to Math.pow(2, 53). We now support reading variable sized numbers up to that
size. If the number is bigger than that, then we need to use BN.
2014-09-15 13:58:24 -07:00

124 lines
2.9 KiB
JavaScript

var BN = require('./bn');
var BufferReader = function BufferReader(buf) {
if (!(this instanceof BufferReader))
return new BufferReader(buf);
if (Buffer.isBuffer(buf)) {
this.set({buf: buf});
}
else if (buf) {
var obj = buf;
this.set(obj);
}
};
BufferReader.prototype.set = function(obj) {
this.buf = obj.buf || this.buf || undefined;
this.pos = obj.pos || this.pos || 0;
return this;
};
BufferReader.prototype.eof = function() {
return this.pos >= this.buf.length;
};
BufferReader.prototype.buffer = function(len) {
var buf = this.buf.slice(this.pos, this.pos + len);
this.pos = this.pos + len;
return buf;
};
BufferReader.prototype.read = function() {
var buf = this.buf.slice(this.pos);
this.pos = this.buf.length;
return buf;
};
BufferReader.prototype.readUInt8 = function() {
var val = this.buf.readUInt8(this.pos);
this.pos = this.pos + 1;
return val;
};
BufferReader.prototype.readUInt16BE = function() {
var val = this.buf.readUInt16BE(this.pos);
this.pos = this.pos + 2;
return val;
};
BufferReader.prototype.readUInt16LE = function() {
var val = this.buf.readUInt16LE(this.pos);
this.pos = this.pos + 2;
return val;
};
BufferReader.prototype.readUInt32BE = function() {
var val = this.buf.readUInt32BE(this.pos);
this.pos = this.pos + 4;
return val;
};
BufferReader.prototype.readUInt32LE = function() {
var val = this.buf.readUInt32LE(this.pos);
this.pos = this.pos + 4;
return val;
};
BufferReader.prototype.readUInt64BEBN = function() {
var buf = this.buf.slice(this.pos, this.pos + 8);
var bn = BN().fromBuffer(buf);
this.pos = this.pos + 8;
return bn;
};
BufferReader.prototype.readUInt64LEBN = function() {
var buf = this.buf.slice(this.pos, this.pos + 8);
var reversebuf = BufferReader({buf: buf}).reverse().read();
var bn = BN().fromBuffer(reversebuf);
this.pos = this.pos + 8;
return bn;
};
BufferReader.prototype.readVarInt = function() {
var first = this.readUInt8();
switch (first) {
case 0xFD:
return this.readUInt16LE();
case 0xFE:
return this.readUInt32LE();
case 0xFF:
var bn = this.readUInt64LEBN();
var n = bn.toNumber();
if (n <= Math.pow(2, 53))
return n;
else
throw new Error('number too large to retain precision - use readVarIntBN');
default:
return first;
}
};
BufferReader.prototype.readVarIntBN = function() {
var first = this.readUInt8();
switch (first) {
case 0xFD:
return BN(this.readUInt16LE());
case 0xFE:
return BN(this.readUInt32LE());
case 0xFF:
return this.readUInt64LEBN();
default:
return BN(first);
}
};
BufferReader.prototype.reverse = function() {
var buf = new Buffer(this.buf.length);
for (var i = 0; i < buf.length; i++)
buf[i] = this.buf[this.buf.length - 1 - i]
this.buf = buf;
return this;
};
module.exports = BufferReader;