binary-parser
Advanced tools
Comparing version 1.1.3 to 1.1.4
@@ -65,3 +65,2 @@ //======================================================================================== | ||
this.compiled = null; | ||
this.isAsync = false; | ||
this.endian = 'be'; | ||
@@ -203,5 +202,2 @@ this.constructorFn = null; | ||
var ctx = new Context(); | ||
if (this.isAsync) { | ||
ctx.isAsync = true; | ||
} | ||
@@ -220,5 +216,3 @@ if (this.constructorFn) { | ||
if (!this.isAsync) { | ||
ctx.pushCode('return vars;'); | ||
} | ||
ctx.pushCode('return vars;'); | ||
@@ -237,7 +231,7 @@ return ctx.code; | ||
size = PRIMITIVE_TYPES[this.type]; | ||
// if this is a fixed length string | ||
} else if (this.type === 'String' && typeof this.options.length === 'number') { | ||
size = this.options.length; | ||
// if this is a fixed length array | ||
@@ -252,3 +246,3 @@ } else if (this.type === 'Array' && typeof this.options.length === 'number') { | ||
size = this.options.length * elementSize; | ||
// if this a skip | ||
@@ -284,3 +278,3 @@ } else if (this.type === 'Skip') { | ||
var parser = new Parser(); | ||
parser.type = NAME_MAP[type]; | ||
@@ -290,3 +284,3 @@ parser.varName = varName; | ||
parser.endian = this.endian; | ||
if (this.head) { | ||
@@ -299,6 +293,2 @@ this.head.next = parser; | ||
if (parser.options.async) { | ||
this.isAsync = true; | ||
} | ||
return this; | ||
@@ -310,17 +300,11 @@ }; | ||
if (this.type) { | ||
if (this.options.async) { | ||
ctx.pushCode('process.nextTick(function() {'); | ||
} | ||
this['generate' + this.type](ctx); | ||
this.generateAssert(ctx); | ||
if (this.options.async) { | ||
if (!this.next) { | ||
ctx.pushCode('process.nextTick(function() { callback(null, vars); });'); | ||
} | ||
ctx.pushCode('});'); | ||
} | ||
} | ||
var varName = ctx.generateVariable(this.varName); | ||
if (this.options.formatter) { | ||
this.generateFormatter(ctx, varName, this.options.formatter); | ||
} | ||
return this.generateNext(ctx); | ||
@@ -481,3 +465,5 @@ }; | ||
} | ||
if (this.options.readUntil === 'eof') { | ||
if (typeof this.options.readUntil === 'function') { | ||
ctx.pushCode('do {'); | ||
} else if (this.options.readUntil === 'eof') { | ||
ctx.pushCode('for (var {0} = 0; offset < buffer.length; {0}++) {', counter); | ||
@@ -506,2 +492,6 @@ } else { | ||
ctx.pushCode('}'); | ||
if (typeof this.options.readUntil === 'function') { | ||
ctx.pushCode(' while (!({0}).call(this, {1}, buffer.slice(offset)));', this.options.readUntil, item); | ||
} | ||
}; | ||
@@ -542,3 +532,4 @@ | ||
Parser.prototype.generateNest = function(ctx) { | ||
ctx.pushCode('{0} = {};', ctx.generateVariable(this.varName)); | ||
var nestVar = ctx.generateVariable(this.varName); | ||
ctx.pushCode('{0} = {};', nestVar); | ||
ctx.pushPath(this.varName); | ||
@@ -549,2 +540,8 @@ this.options.type.generate(ctx); | ||
Parser.prototype.generateFormatter = function(ctx, varName, formatter) { | ||
if (typeof formatter === 'function') { | ||
ctx.pushCode('{0} = ({1}).call(this, {0});', varName, formatter); | ||
} | ||
} | ||
Parser.prototype.isInteger = function() { | ||
@@ -551,0 +548,0 @@ return !!this.type.match(/U?Int[8|16|32][BE|LE]?|Bit\d+/); |
@@ -22,3 +22,3 @@ //======================================================================================== | ||
Context.prototype.generateVariable = function(name) { | ||
var arr = []; | ||
var arr = []; | ||
@@ -56,3 +56,3 @@ Array.prototype.push.apply(arr, this.scopes[this.scopes.length - 1]); | ||
Context.prototype.generateTmpVariable = function() { | ||
return 'tmp' + (this.tmpVariableCount++); | ||
return '$tmp' + (this.tmpVariableCount++); | ||
}; | ||
@@ -67,15 +67,15 @@ | ||
Context.prototype.pushPath = function(name) { | ||
this.scopes[this.scopes.length - 1].push(name); | ||
this.scopes[this.scopes.length - 1].push(name); | ||
}; | ||
Context.prototype.popPath = function() { | ||
this.scopes[this.scopes.length - 1].pop(); | ||
this.scopes[this.scopes.length - 1].pop(); | ||
}; | ||
Context.prototype.pushScope = function(name) { | ||
this.scopes.push([name]); | ||
this.scopes.push([name]); | ||
}; | ||
Context.prototype.popScope = function() { | ||
this.scopes.pop(); | ||
this.scopes.pop(); | ||
}; | ||
@@ -82,0 +82,0 @@ |
{ | ||
"name": "binary-parser", | ||
"version": "1.1.3", | ||
"version": "1.1.4", | ||
"description": "Blazing-fast binary parser builder", | ||
@@ -5,0 +5,0 @@ "main": "lib/binary_parser.js", |
@@ -68,3 +68,3 @@ # Binary-parser | ||
// Parse buffer and show result | ||
console.log(ipHeader.parse(buf)); | ||
console.log(ipHeader.parse(buf)); | ||
``` | ||
@@ -82,6 +82,2 @@ | ||
If parser's `async` option is `true`, then a callback function has to be passed as an | ||
argument. This callback should take two arguments like other node.js callbacks: | ||
`function(err, result)`. | ||
### create(constructorFunction) | ||
@@ -96,3 +92,3 @@ Set the constructor function that should be called to create the object returned from | ||
Byte-ordering can be either `l` for little endian or `b` for big endian. | ||
With no prefix, it parses as a signed number, with `u` prefixed as an unsigned number. | ||
With no prefix, it parses as a signed number, with `u` prefixed as an unsigned number. | ||
@@ -115,3 +111,3 @@ ```javascript | ||
Parse bytes as an floating-point value and store it in a variable | ||
named `name`. `name` should consist only of alphanumeric characters and start | ||
named `name`. `name` should consist only of alphanumeric characters and start | ||
with an alphabet. | ||
@@ -129,3 +125,3 @@ | ||
Parse bytes as a string. `name` should consist only of alpha numeric characters and start | ||
with an alphabet. `options` is an object; following options are available: | ||
with an alphabet. `options` is an object; following options are available: | ||
@@ -142,3 +138,3 @@ - `encoding` - (Optional, defaults to `utf8`) Specify which encoding to use. `'utf8'`, `'ascii'`, `'hex'` and else | ||
Parse bytes as a buffer. `name` should consist only of alpha numeric characters and start | ||
with an alphabet. `options` is an object; following options are available: | ||
with an alphabet. `options` is an object; following options are available: | ||
@@ -156,3 +152,3 @@ - `clone` - (Optional, defaults to `false`) By default, `buffer(name [,options])` returns a new buffer which references | ||
### array(name [,options]) | ||
Parse bytes as an array. `options` is an object; following options are available: | ||
Parse bytes as an array. `options` is an object; following options are available: | ||
@@ -164,3 +160,3 @@ - `type` - (Required) Type of the array element. Can be a string or an user defined Parser object. | ||
- `readUntil` - (either `length` or `readUntil` is required) If `'eof'`, then this parser | ||
will read till it reaches end of the `Buffer` object. | ||
reads until the end of `Buffer` object. If function it reads until the function returns true. | ||
@@ -174,3 +170,3 @@ ```javascript | ||
}) | ||
// Dynamically sized array (reference another variable) | ||
@@ -182,3 +178,3 @@ .uint8('dataLength') | ||
}) | ||
// Dynamically sized array (with some calculation) | ||
@@ -189,8 +185,14 @@ .array('data3', { | ||
}); | ||
// Dynamically sized array (with stop-check on parsed item) | ||
.array('data4', { | ||
type: 'int32', | ||
readUntil: function(item, buffer) { return item === 42 } // stop when specific item is parsed. buffer can be used to perform a read-ahead. | ||
}); | ||
// Use user defined parser object | ||
.array('data4', { | ||
.array('data5', { | ||
type: userDefinedParser, | ||
length: 'dataLength' | ||
}) | ||
}); | ||
``` | ||
@@ -204,3 +206,3 @@ | ||
- `tag` - (Required) The value used to determine which parser to use from the `choices` | ||
Can be a string pointing to another field or a function. | ||
Can be a string pointing to another field or a function. | ||
- `choices` - (Required) An object which key is an integer and value is the parser which is executed | ||
@@ -219,7 +221,7 @@ when `tag` equals the key value. | ||
tag: 'tagValue', | ||
choices: [ | ||
choices: { | ||
1: parser1, // When tagValue == 1, execute parser1 | ||
4: parser2, // When tagValue == 4, execute parser2 | ||
5: parser3 // When tagValue == 5, execute parser3 | ||
] | ||
} | ||
}); | ||
@@ -264,2 +266,12 @@ ``` | ||
- `formatter` - Function that transforms the parsed value into a more desired form. | ||
```javascript | ||
var parser = new Parser() | ||
.array('ipv4', { | ||
type: uint8, | ||
length: '4', | ||
formatter: function(arr) { return arr.join('.'); } | ||
}); | ||
``` | ||
- `assert` - Do assertion on the parsed result (useful for checking magic numbers and so on). | ||
@@ -289,5 +301,2 @@ If `assert` is a `string` or `number`, the actual parsed result will be compared with it | ||
- `async` - If `true`, then this parser will be executed asynchronously. You also have | ||
to pass a callback function to `Parser.parse(buffer, callback)`. | ||
## Examples | ||
@@ -294,0 +303,0 @@ See `example` for more complex examples. |
@@ -92,3 +92,3 @@ var assert = require('assert'); | ||
}); | ||
it('should parse until eof when readUnitl is specified', function(){ | ||
it('should parse until eof when readUntil is specified', function(){ | ||
var parser = | ||
@@ -106,4 +106,30 @@ Parser.start() | ||
}); | ||
it('should parse until function returns true when readUntil is function', function(){ | ||
var parser = | ||
Parser.start() | ||
.array('data', { | ||
readUntil: function (item, buf) { return item === 0 }, | ||
type: 'uint8' | ||
}); | ||
var buffer = new Buffer([0xff, 0xff, 0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff]); | ||
assert.deepEqual(parser.parse(buffer), { | ||
data: [0xff, 0xff, 0xff, 0x01, 0x00] | ||
}); | ||
}); | ||
it('should parse until function returns true when readUntil is function (using read-ahead)', function(){ | ||
var parser = | ||
Parser.start() | ||
.array('data', { | ||
readUntil: function (item, buf) { return buf.length > 0 && buf.readUInt8(0) === 0 }, | ||
type: 'uint8' | ||
}); | ||
var buffer = new Buffer([0xff, 0xff, 0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff]); | ||
assert.deepEqual(parser.parse(buffer), { | ||
data: [0xff, 0xff, 0xff, 0x01] | ||
}); | ||
}); | ||
it('should parse associative arrays', function(){ | ||
var parser = | ||
var parser = | ||
Parser.start() | ||
@@ -141,3 +167,17 @@ .int8('numlumps') | ||
}); | ||
}); | ||
}); | ||
it('should use formatter to transform parsed array', function(){ | ||
var parser = | ||
Parser.start() | ||
.array('data', { | ||
type: 'uint8', | ||
length: 4, | ||
formatter: function(arr) { return arr.join('.'); } | ||
}); | ||
var buffer = new Buffer([0x0a, 0x0a, 0x01, 0x6e]); | ||
assert.deepEqual(parser.parse(buffer), { | ||
data: '10.10.1.110' | ||
}); | ||
}); | ||
}); | ||
@@ -258,2 +298,22 @@ | ||
}); | ||
it('should format parsed nested parser', function() { | ||
var nameParser = new Parser() | ||
.string('firstName', { | ||
zeroTerminated: true | ||
}) | ||
.string('lastName', { | ||
zeroTerminated: true | ||
}); | ||
var personParser = new Parser() | ||
.nest('name', { | ||
type: nameParser, | ||
formatter: function(name) { return name.firstName + ' ' + name.lastName } | ||
}) | ||
var buffer = new Buffer('John\0Doe\0'); | ||
assert.deepEqual(personParser.parse(buffer), { | ||
name: 'John Doe' | ||
}); | ||
}); | ||
}); | ||
@@ -333,38 +393,3 @@ | ||
}); | ||
it('should parse asynchronously', function() { | ||
var parser = new Parser() | ||
.uint8('len') | ||
.string('text', {length: 'len', async: true}); | ||
var buf = new Buffer('0c68656c6c6f2c20776f726c64', 'hex'); | ||
parser.parse(buf, function(err, result) { | ||
assert.deepEqual(result, {len: 12, text: 'hello, world'}); | ||
}); | ||
}); | ||
it('should emit error asynchronously', function() { | ||
var parser = new Parser() | ||
.uint8('len') | ||
.string('text', {length: 'len', async: true}); | ||
var buf = null; | ||
parser.parse(buf, function(err, result) { | ||
assert(err); | ||
}); | ||
parser = new Parser().uint32be('val', { | ||
assert: function(x) { | ||
return x === 0xdeadbeef; | ||
}, | ||
async: true | ||
}); | ||
buf = new Buffer('cafebabe', 'hex'); | ||
parser.parse(buf, function(err, result) { | ||
assert(err); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -23,2 +23,15 @@ var assert = require('assert'); | ||
}); | ||
it('should use formatter to transform parsed integer', function(){ | ||
var parser = | ||
Parser.start() | ||
.uint8('a', { | ||
formatter: function(val) { return val * 2; } | ||
}) | ||
.int16le('b', { | ||
formatter: function(val) { return "test" + String(val); } | ||
}); | ||
var buffer = new Buffer([0x01, 0xd2, 0x04]); | ||
assert.deepEqual(parser.parse(buffer), {a: 2, b: "test1234"}); | ||
}); | ||
it('should parse floating point types', function(){ | ||
@@ -121,3 +134,3 @@ var parser = | ||
}); | ||
parser = new Parser() | ||
@@ -124,0 +137,0 @@ .endianess('little') |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
142949
20
1410
318