new varint2.

This commit is contained in:
Christopher Jeffrey 2016-05-22 06:49:27 -07:00
parent 5537eb1995
commit 92e8a9c4bc
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 231 additions and 5 deletions

View File

@ -472,6 +472,18 @@ BufferReader.prototype.readVarint = function readVarint(big) {
return result.value;
};
/**
* Read a varint (type 2).
* @param {Boolean?} big - Whether to read as a big number.
* @returns {Number}
*/
BufferReader.prototype.readVarint2 = function readVarint2(big) {
var result = utils.readVarint2(this.data, this.offset, big);
this.offset += result.size;
return result.value;
};
/**
* Read N bytes (will do a fast slice if zero copy).
* @param {Number} size

View File

@ -1694,7 +1694,7 @@ utils.write64BE = function write64BE(dst, num, off) {
* @param {Buffer} data
* @param {Number} off
* @param {Boolean?} big - Whether to read as a big number.
* @returns {Number}
* @returns {Object}
*/
utils.readVarint = function readVarint(data, off, big) {
@ -1814,6 +1814,147 @@ utils.sizeVarint = function sizeVarint(num) {
return 9;
};
/**
* Read a varint (type 2).
* @param {Buffer} data
* @param {Number} off
* @param {Boolean?} big - Whether to read as a big number.
* @returns {Object}
*/
utils.readVarint2 = function readVarint2(data, off, big) {
var num = 0;
var size = 0;
var bnum, ch;
off = off >>> 0;
for (;;) {
assert(off < data.length);
ch = data[off++];
size++;
if (num >= 0x3fffffffffff) {
assert(big, 'Number exceeds 2^53-1.');
bnum = new bn(num);
}
if (bnum) {
bnum.iushln(7).iaddn(ch & 0x7f);
if ((ch & 0x80) === 0)
break;
bnum.iaddn(1);
continue;
}
num = (num * 0x80) + (ch & 0x7f);
if ((ch & 0x80) === 0)
break;
num++;
}
if (bnum)
return { size: size, value: bnum };
if (big)
num = new bn(num);
return { size: size, value: num };
};
/**
* Write a varint (type 2).
* @param {Buffer} dst
* @param {BN|Number} num
* @param {Number} off
* @returns {Number} Number of bytes written.
*/
utils.writeVarint2 = function writeVarint2(dst, num, off) {
var tmp = [];
var len = 0;
if (bn.isBN(num)) {
if (num.bitLength() > 53) {
for (;;) {
tmp[len] = (num.words[0] & 0x7f) | (len ? 0x80 : 0x00);
if (num.cmpn(0x7f) <= 0)
break;
num.iushrn(7).isubn(1);
len++;
}
assert(off + len <= dst.length);
do {
dst[off++] = tmp[len];
} while (len--);
return off;
}
num = num.toNumber();
}
off = off >>> 0;
num = +num;
for (;;) {
tmp[len] = (num & 0x7f) | (len ? 0x80 : 0x00);
if (num <= 0x7f)
break;
num = ((num - (num % 0x80)) / 0x80) - 1;
len++;
}
assert(off + len <= dst.length);
do {
dst[off++] = tmp[len];
} while (len--);
return off;
};
/**
* Calculate size of varint (type 2).
* @param {BN|Number} num
* @returns {Number} size
*/
utils.sizeVarint2 = function sizeVarint2(num) {
var size = 0;
if (bn.isBN(num)) {
if (num.bitLength() > 53) {
num = num.clone();
for (;;) {
size++;
if (num.cmpn(0x7f) <= 0)
break;
num.iushrn(7).isubn(1);
}
return size;
}
num = num.toNumber();
}
num = +num;
for (;;) {
size++;
if (num <= 0x7f)
break;
num = ((num - (num % 0x80)) / 0x80) - 1;
}
return size;
};
/**
* Buffer comparator (memcmp + length comparison).
* @param {Buffer} a

View File

@ -32,10 +32,11 @@ var FLBE = 16;
var DBL = 17;
var DBLBE = 18;
var VARINT = 19;
var BYTES = 20;
var STR = 21;
var CHECKSUM = 22;
var FILL = 23;
var VARINT2 = 20;
var BYTES = 21;
var STR = 22;
var CHECKSUM = 23;
var FILL = 24;
/**
* An object that allows writing of buffers in a
@ -97,6 +98,7 @@ BufferWriter.prototype.render = function render(keep) {
case DBL: off = data.writeDoubleLE(item[1], off, true); break;
case DBLBE: off = data.writeDoubleBE(item[1], off, true); break;
case VARINT: off = utils.writeVarint(data, item[1], off); break;
case VARINT2: off = utils.writeVarint2(data, item[1], off); break;
case BYTES: off += item[1].copy(data, off); break;
case STR: off += data.write(item[1], off, item[2]); break;
case CHECKSUM:
@ -343,6 +345,21 @@ BufferWriter.prototype.writeVarint = function writeVarint(value) {
this.data.push([VARINT, value]);
};
/**
* Write a varint (type 2).
* @param {BN|Number} value
*/
BufferWriter.prototype.writeVarint2 = function writeVarint2(value) {
if (typeof value === 'number')
assert(value >= 0);
else
assert(!value.isNeg());
this.written += utils.sizeVarint2(value);
this.data.push([VARINT2, value]);
};
/**
* Write bytes.
* @param {Buffer} value

View File

@ -61,6 +61,62 @@ describe('Utils', function() {
});
});
it('should write/read new varints', function() {
/*
* 0: [0x00] 256: [0x81 0x00]
* 1: [0x01] 16383: [0xFE 0x7F]
* 127: [0x7F] 16384: [0xFF 0x00]
* 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F]
* 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F]
* 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
*/
var n = 0;
var b = new Buffer(1);
b.fill(0x00);
utils.writeVarint2(b, 0, 0);
assert.equal(utils.readVarint2(b, 0).value, 0);
assert.deepEqual(b, [0]);
var b = new Buffer(1);
b.fill(0x00);
utils.writeVarint2(b, 1, 0);
assert.equal(utils.readVarint2(b, 0).value, 1);
assert.deepEqual(b, [1]);
var b = new Buffer(1);
b.fill(0x00);
utils.writeVarint2(b, 127, 0);
assert.equal(utils.readVarint2(b, 0).value, 127);
assert.deepEqual(b, [0x7f]);
var b = new Buffer(2);
b.fill(0x00);
utils.writeVarint2(b, 128, 0);
assert.equal(utils.readVarint2(b, 0).value, 128);
assert.deepEqual(b, [0x80, 0x00]);
var b = new Buffer(2);
b.fill(0x00);
utils.writeVarint2(b, 255, 0);
assert.equal(utils.readVarint2(b, 0).value, 255);
assert.deepEqual(b, [0x80, 0x7f]);
var b = new Buffer(3);
b.fill(0x00);
utils.writeVarint2(b, 16511, 0);
assert.equal(utils.readVarint2(b, 0).value, 16511);
//assert.deepEqual(b, [0x80, 0xff, 0x7f]);
assert.deepEqual(b, [0xff, 0x7f, 0x00]);
var b = new Buffer(3);
b.fill(0x00);
utils.writeVarint2(b, 65535, 0);
assert.equal(utils.readVarint2(b, 0).value, 65535);
//assert.deepEqual(b, [0x82, 0xfd, 0x7f]);
assert.deepEqual(b, [0x82, 0xfe, 0x7f]);
});
var unsigned = [
new bn('ffeeffee'),
new bn('001fffeeffeeffee'),