binary-parser
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -28,5 +28,14 @@ //======================================================================================== | ||
'Choice' : null, | ||
'Nest' : null | ||
'Nest' : null, | ||
'Bit' : null | ||
}; | ||
var BIT_RANGE = []; | ||
(function() { | ||
var i; | ||
for (i = 1; i <= 32; i++) { | ||
BIT_RANGE.push(i); | ||
} | ||
})(); | ||
// Converts Parser's method names to internal type names | ||
@@ -73,2 +82,12 @@ var NAME_MAP = {}; | ||
BIT_RANGE.forEach(function(i) { | ||
Parser.prototype['bit' + i.toString()] = function(varName, options) { | ||
if (!options) { | ||
options = {}; | ||
} | ||
options.length = i; | ||
return this.setNextParser('bit', varName, options); | ||
}; | ||
}); | ||
Parser.prototype.skip = function(length, options) { | ||
@@ -171,3 +190,3 @@ if (options && options.assert) { | ||
ctx.pushCode('var vars = {};'); | ||
ctx.pushCode('var iterator = 0;'); | ||
ctx.pushCode('var offset = 0;'); | ||
ctx.pushCode('if (!Buffer.isBuffer(buffer)) {'); | ||
@@ -303,10 +322,50 @@ ctx.generateError('"argument buffer is not a Buffer object"'); | ||
Parser.prototype['generate' + type] = function(ctx) { | ||
ctx.pushCode('{0} = buffer.read{1}(iterator);', ctx.generateVariable(this.varName), type); | ||
ctx.pushCode('iterator += {0};', PRIMITIVE_TYPES[type]); | ||
ctx.pushCode('{0} = buffer.read{1}(offset);', ctx.generateVariable(this.varName), type); | ||
ctx.pushCode('offset += {0};', PRIMITIVE_TYPES[type]); | ||
}; | ||
}); | ||
Parser.prototype.generateBit = function(ctx) { | ||
ctx.bitFields.push(this); | ||
if (!this.next || (this.next && !this.next.type.match('Bit'))) { | ||
var sum = 0; | ||
ctx.bitFields.forEach(function(parser) { | ||
sum += parser.options.length; | ||
}); | ||
var val = ctx.generateTmpVariable(); | ||
if (sum <= 8) { | ||
ctx.pushCode('var {0} = buffer.readUInt8(offset);', val); | ||
sum = 8; | ||
} else if (sum <= 16) { | ||
ctx.pushCode('var {0} = buffer.readUInt16BE(offset);', val); | ||
sum = 16; | ||
} else if (sum <= 32) { | ||
ctx.pushCode('var {0} = buffer.readUInt32BE(offset);', val); | ||
sum = 32; | ||
} else { | ||
throw new Error('Currently, bit field sequence longer than 4-bytes is not supported.'); | ||
} | ||
ctx.pushCode('offset += {0};', sum / 8); | ||
var bitOffset = 0; | ||
ctx.bitFields.forEach(function(parser) { | ||
ctx.pushCode('{0} = {1} >> {2} & {3};', | ||
ctx.generateVariable(parser.varName), | ||
val, | ||
sum - bitOffset - parser.options.length, | ||
(1 << parser.options.length) - 1 | ||
); | ||
bitOffset += parser.options.length; | ||
}); | ||
ctx.bitFields = []; | ||
} | ||
}; | ||
Parser.prototype.generateSkip = function(ctx) { | ||
var length = ctx.generateOption(this.options.length); | ||
ctx.pushCode('iterator += {0};', length); | ||
ctx.pushCode('offset += {0};', length); | ||
}; | ||
@@ -316,10 +375,14 @@ | ||
if (this.options.zeroTerminated) { | ||
ctx.pushCode('{0} = (function() {', ctx.generateVariable(this.varName)); | ||
ctx.pushCode('var start = iterator;'); | ||
ctx.pushCode('while(buffer.readUInt8(iterator++) !== 0);'); | ||
ctx.pushCode('return buffer.toString(\'{0}\', start, iterator - 1);', this.options.encoding); | ||
ctx.pushCode('})();'); | ||
var start = ctx.generateTmpVariable(); | ||
ctx.pushCode('var {0} = offset;', start); | ||
ctx.pushCode('while(buffer.readUInt8(offset++) !== 0);'); | ||
ctx.pushCode('{0} = buffer.toString(\'{1}\', {2}, offset - 1);', | ||
ctx.generateVariable(this.varName), | ||
this.options.encoding, | ||
start | ||
); | ||
} | ||
else { | ||
ctx.pushCode('{0} = buffer.toString(\'{1}\', iterator, iterator + {2});', | ||
ctx.pushCode('{0} = buffer.toString(\'{1}\', offset, offset + {2});', | ||
ctx.generateVariable(this.varName), | ||
@@ -329,3 +392,3 @@ this.options.encoding, | ||
); | ||
ctx.pushCode('iterator += {0};', ctx.generateOption(this.options.length)); | ||
ctx.pushCode('offset += {0};', ctx.generateOption(this.options.length)); | ||
} | ||
@@ -336,17 +399,19 @@ }; | ||
if (this.options.readUntil === 'eof') { | ||
ctx.pushCode('{0} = buffer.slice(iterator, buffer.length - 1);', | ||
ctx.pushCode('{0} = buffer.slice(offset, buffer.length - 1);', | ||
ctx.generateVariable(this.varName) | ||
); | ||
} else { | ||
ctx.pushCode('{0} = buffer.slice(iterator, iterator + {1});', | ||
ctx.pushCode('{0} = buffer.slice(offset, offset + {1});', | ||
ctx.generateVariable(this.varName), | ||
ctx.generateOption(this.options.length) | ||
); | ||
ctx.pushCode('iterator += {0};', ctx.generateOption(this.options.length)); | ||
ctx.pushCode('offset += {0};', ctx.generateOption(this.options.length)); | ||
} | ||
if (this.options.clone) { | ||
ctx.pushCode('{0} = (function() { var buf = new Buffer({0}.length); {0}.copy(buf); return buf; })();', | ||
ctx.generateVariable(this.varName) | ||
); | ||
var buf = ctx.generateTmpVariable(); | ||
ctx.pushCode('var {0} = new Buffer({1}.length);', buf, ctx.generateVariable(this.varName)); | ||
ctx.pushCode('{0}.copy({1});', ctx.generateVariable(this.varName), buf); | ||
ctx.pushCode('{0} = {1}', ctx.generateVariable(this.varName), buf); | ||
} | ||
@@ -358,3 +423,3 @@ }; | ||
var type = this.options.type; | ||
var counter = 'i' + ctx.scopes.length.toString(); | ||
var counter = ctx.generateTmpVariable(); | ||
var lhs = ctx.generateVariable(this.varName); | ||
@@ -364,3 +429,3 @@ | ||
if (this.options.readUntil === 'eof') { | ||
ctx.pushCode('for (var {0} = 0; iterator < buffer.length; {0}++) {', counter); | ||
ctx.pushCode('for (var {0} = 0; offset < buffer.length; {0}++) {', counter); | ||
} else { | ||
@@ -371,4 +436,4 @@ ctx.pushCode('for (var {0} = 0; {0} < {1}; {0}++) {', counter, length); | ||
if (typeof type === 'string') { | ||
ctx.pushCode('{0}.push(buffer.read{1}(iterator));', lhs, NAME_MAP[type]); | ||
ctx.pushCode('iterator += {0};', PRIMITIVE_TYPES[NAME_MAP[type]]); | ||
ctx.pushCode('{0}.push(buffer.read{1}(offset));', lhs, NAME_MAP[type]); | ||
ctx.pushCode('offset += {0};', PRIMITIVE_TYPES[NAME_MAP[type]]); | ||
} else if (type instanceof Parser) { | ||
@@ -386,4 +451,4 @@ ctx.pushCode('{0}.push({});', lhs); | ||
if (typeof type === 'string') { | ||
ctx.pushCode('{0} = buffer.read{1}(iterator);', ctx.generateVariable(this.varName), NAME_MAP[type]); | ||
ctx.pushCode('iterator += {0};', PRIMITIVE_TYPES[NAME_MAP[type]]); | ||
ctx.pushCode('{0} = buffer.read{1}(offset);', ctx.generateVariable(this.varName), NAME_MAP[type]); | ||
ctx.pushCode('offset += {0};', PRIMITIVE_TYPES[NAME_MAP[type]]); | ||
} else if (type instanceof Parser) { | ||
@@ -436,2 +501,4 @@ ctx.scopes.push(varName); | ||
this.isAsync = false; | ||
this.bitFields = []; | ||
this.tmpVariableCount = 0; | ||
}; | ||
@@ -474,2 +541,6 @@ | ||
Context.prototype.generateTmpVariable = function() { | ||
return 'tmp' + (this.tmpVariableCount++); | ||
}; | ||
Context.prototype.pushCode = function() { | ||
@@ -476,0 +547,0 @@ var args = Array.prototype.slice.call(arguments); |
{ | ||
"name": "binary-parser", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Blazing-fast binary parser builder", | ||
@@ -18,3 +19,4 @@ "main": "lib/binary_parser.js", | ||
"struct", | ||
"buffer" | ||
"buffer", | ||
"bit" | ||
], | ||
@@ -21,0 +23,0 @@ "author": { |
@@ -8,3 +8,4 @@ # Binary-parser | ||
It supports all common data types required to parse a structured binary data, | ||
such as integers, floating point numbers, strings, arrays (both fixed length and variable length), etc. | ||
such as integers, bit fields, floating point numbers, strings, arrays | ||
(both fixed length and variable length), etc. | ||
Binary-parser dynamically generates and compiles the parser code on-the-fly. | ||
@@ -76,2 +77,6 @@ | ||
### bit\[1-32\](name [,options]) | ||
Parse bytes as a bit field and store it in variable `name`. There are 32 methods from | ||
`bit1` to `bit32` each corresponding to 1-bit-length to 32-bits-length bit field. | ||
### {float, double}{le, be}(name [,options]) | ||
@@ -235,3 +240,3 @@ Parse bytes as an floating-point value and store it in a variable | ||
Copyright (c) 2013 Keichi Takahashi | ||
Copyright (c) 2013 Keichi Takahashi <keichi.t@me.com> | ||
@@ -238,0 +243,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
@@ -45,2 +45,49 @@ var assert = require('assert'); | ||
describe('Bit field parsers', function() { | ||
it('should parse 1-byte-length bit field sequence', function() { | ||
var parser = new Parser() | ||
.bit1('a') | ||
.bit2('b') | ||
.bit4('c') | ||
.bit1('d'); | ||
var buf = new Buffer([parseInt('11010100', 2)]); | ||
assert.deepEqual(parser.parse(buf), { | ||
a: 1, | ||
b: 2, | ||
c: 10, | ||
d: 0 | ||
}); | ||
}); | ||
it('should parse 2-byte-length bit field sequence', function() { | ||
var parser = new Parser() | ||
.bit3('a') | ||
.bit9('b') | ||
.bit4('c'); | ||
var buf = new Buffer([parseInt('10111100', 2), parseInt('01110101', 2)]); | ||
assert.deepEqual(parser.parse(buf), { | ||
a: 5, | ||
b: 455, | ||
c: 5 | ||
}); | ||
}); | ||
it('should parse 4-byte-length bit field sequence', function() { | ||
var parser = new Parser() | ||
.bit1('a') | ||
.bit24('b') | ||
.bit4('c') | ||
.bit2('d') | ||
.bit1('e'); | ||
var buf = new Buffer([parseInt('11010101', 2), parseInt('01010101', 2), parseInt('01010101', 2), parseInt('01111011', 2)]); | ||
assert.deepEqual(parser.parse(buf), { | ||
a: 1, | ||
b: 11184810, | ||
c: 15, | ||
d: 1, | ||
e: 1 | ||
}); | ||
}); | ||
}); | ||
describe('String parser', function() { | ||
@@ -47,0 +94,0 @@ it('should parse ASCII encoded string', function(){ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
104291
14
1246
257