switch out the accumulator reader for a faster buffer reader

master
Max Ogden 11 years ago
parent f75a1659aa
commit 8c42c841d6

@ -1,20 +1,12 @@
# varint
decode [protobuf-style varint bytes](https://developers.google.com/protocol-buffers/docs/encoding#varints) and emit whole integers when enough have been accumulated that a number can be constructed; also encode whole numbers to an array of varint style bytes.
encode whole numbers to an array of [protobuf-style varint bytes](https://developers.google.com/protocol-buffers/docs/encoding#varints) and also decode them.
```javascript
var varint = require('varint')
var bytes = varint.encode(300) // === [0xAC, 0x02]
, vi = varint()
vi.once('data', function(num) {
console.log('got', num)
})
vi.write(bytes[0])
vi.write(bytes[1]) // "got 300"
varint.decode(bytes) // 300
```
## api
@ -24,16 +16,11 @@ vi.write(bytes[1]) // "got 300"
### varint.encode(num[, output=[], offset=0]) -> array
encodes `num` into either the array given by `offset` or a new array at `offset`
and returns that array.
### vi = varint() -> EventEmitter
return a new `varint` instance.
and returns that array filled with integers.
### vi.write(byte) -> undefined
### varint.decode(data[, offset=0]) -> number
write a byte to the varint. if the byte is "final" (i.e., does not have the bit at `0x80` set),
it will attempt to compile the number and emit it as a `data` event.
decodes `data`, which can be either a buffer or array of integers, from position `offset` or default 0 and returns the decoded integer
# License

@ -1,33 +1,21 @@
module.exports = Decoder
module.exports = read
var MSB = 0x80
, REST = 0x7F
function Decoder() {
this.accum = []
function read(buf, offset) {
var res = 0
, offset = offset || 0
, shift = 0
, b
do {
b = buf[offset++]
res += shift < 28
? (b & REST) << shift
: (b & REST) * Math.pow(2, shift)
shift += 7
} while (b >= MSB)
return res
}
Decoder.prototype.write = write;
function write(byte) {
var msb = byte & MSB
, accum = this.accum
, len
, out
accum[accum.length] = byte & REST
if(msb) {
return
}
len = accum.length
out = 0
for(var i = 0; i < len; ++i) {
out |= accum[i] << (7 * i)
}
accum.length = 0
this.ondata(out)
return
}

@ -14,4 +14,4 @@ function encode(num, out, offset) {
}
out[offset] = num
return out
}
}

@ -1,22 +1,4 @@
module.exports = varint
varint.encode = require('./encode.js');
var EE = require('events').EventEmitter
, Decoder = require('./decode.js')
function varint() {
var ee = new EE
, dec = new Decoder
dec.ondata = function (item) {
ee.emit("data", item)
}
ee.write = function (item) {
dec.write(item);
}
return ee
module.exports = {
encode: require('./encode.js'),
decode: require('./decode.js')
}

@ -1,7 +1,7 @@
{
"name": "varint",
"version": "0.0.3",
"description": "use msb to create integer values of varying sizes",
"description": "protobuf-style varint bytes - use msb to create integer values of varying sizes",
"main": "index.js",
"scripts": {
"test": "node test.js"

@ -2,39 +2,25 @@ var varint = require('./index')
, test = require('tape')
test('fuzz test', function(assert) {
var vi = varint()
, expect
var expect
, encoded
vi.on('data', function(data) {
assert.equal(expect, data, 'fuzz test: '+expect.toString(16))
})
for(var i = 0, len = 100; i < len; ++i) {
expect = randint(0x7FFFFFFF)
encoded = varint.encode(expect)
for(var x = 0; x < encoded.length; ++x) {
vi.write(encoded[x])
}
var data = varint.decode(encoded)
assert.equal(expect, data, 'fuzz test: '+expect.toString())
}
assert.end()
})
test('test single byte works as expected', function(assert) {
var num = [0xAC, 0x02]
var acc = varint()
acc.on('data', function(data) {
assert.equal(data, 300, 'should equal 300 every time')
})
for(var i = 0, len = 10; i < len; ++i) {
acc.write(0xAC)
acc.write(0x02)
}
var buf = new Uint8Array(2)
buf[0] = 172
buf[1] = 2
var data = varint.decode(buf)
assert.equal(data, 300, 'should equal 300')
assert.end()
})
@ -47,28 +33,22 @@ test('test encode works as expected', function(assert) {
})
test('test decode single bytes', function(assert) {
var vi = varint()
, expected = randint(parseInt('1111111', '2'))
vi.once('data', function(data) {
assert.equal(data, expected)
assert.end()
})
vi.write(expected)
var expected = randint(parseInt('1111111', '2'))
var buf = new Uint8Array(1)
buf[0] = expected
var data = varint.decode(buf)
assert.equal(data, expected)
assert.end()
})
test('test decode multiple bytes with zero', function(assert) {
var vi = varint()
, expected = randint(parseInt('1111111', '2'))
vi.once('data', function(data) {
assert.equal(data, expected << 7)
assert.end()
})
vi.write(0x80)
vi.write(expected)
var expected = randint(parseInt('1111111', '2'))
var buf = new Uint8Array(2)
buf[0] = 128
buf[1] = expected
var data = varint.decode(buf)
assert.equal(data, expected << 7)
assert.end()
})
test('encode single byte', function(assert) {
@ -80,6 +60,7 @@ test('encode single byte', function(assert) {
test('encode multiple byte with zero first byte', function(assert) {
var expected = 0x0F00
assert.deepEqual(varint.encode(expected), [0x80, 0x1E])
assert.end()
})
function randint(range) {

Loading…
Cancel
Save