binary-parser
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -120,8 +120,11 @@ //======================================================================================== | ||
Parser.prototype.string = function(varName, options) { | ||
if (!options.zeroTerminated && !options.length) { | ||
throw new Error('Neiter length nor zeroTerminated is defined for string.'); | ||
if (!options.zeroTerminated && !options.length && !options.greedy) { | ||
throw new Error('Neither length, zeroTerminated, nor greedy is defined for string.'); | ||
} | ||
if (options.stripNull && !options.length) { | ||
throw new Error('Length must be defined if stripNull is defined.'); | ||
if ((options.zeroTerminated || options.length) && options.greedy) { | ||
throw new Error('greedy is mutually exclusive with length and zeroTerminated for string.'); | ||
} | ||
if (options.stripNull && !(options.length || options.greedy)) { | ||
throw new Error('Length or greedy must be defined if stripNull is defined.'); | ||
} | ||
options.encoding = options.encoding || 'utf8'; | ||
@@ -297,2 +300,6 @@ | ||
// if this is a fixed length buffer | ||
} else if (this.type === 'Buffer' && typeof this.options.length === 'number') { | ||
size = this.options.length; | ||
// if this is a fixed length array | ||
@@ -314,3 +321,3 @@ } else if (this.type === 'Array' && typeof this.options.length === 'number') { | ||
} else if (this.type === 'Nest') { | ||
size = this.options.type.sizeOf(); | ||
size = this.options.type.sizeOf(); | ||
} else if (!this.type) { | ||
@@ -500,2 +507,10 @@ size = 0; | ||
); | ||
} else if (this.options.greedy) { | ||
ctx.pushCode('var {0} = offset;', start); | ||
ctx.pushCode('while(buffer.length > offset++);'); | ||
ctx.pushCode('{0} = buffer.toString(\'{1}\', {2}, offset);', | ||
name, | ||
this.options.encoding, | ||
start | ||
); | ||
} | ||
@@ -599,3 +614,3 @@ if(this.options.stripNull) { | ||
type.generate(ctx); | ||
ctx.popPath(); | ||
ctx.popPath(varName); | ||
} | ||
@@ -606,4 +621,6 @@ }; | ||
var tag = ctx.generateOption(this.options.tag); | ||
ctx.pushCode('{0} = {};', ctx.generateVariable(this.varName)); | ||
if (this.varName) | ||
{ | ||
ctx.pushCode('{0} = {};', ctx.generateVariable(this.varName)); | ||
} | ||
ctx.pushCode('switch({0}) {', tag); | ||
@@ -632,3 +649,3 @@ Object.keys(this.options.choices).forEach(function(tag) { | ||
this.options.type.generate(ctx); | ||
ctx.popPath(); | ||
ctx.popPath(this.varName); | ||
} else if (aliasRegistry[this.options.type]) { | ||
@@ -635,0 +652,0 @@ var tempVar = ctx.generateTmpVariable(); |
@@ -40,3 +40,3 @@ //======================================================================================== | ||
case 'function': | ||
return '(' + val + ').call(' + this.generateVariable() + ')'; | ||
return '(' + val + ').call(' + this.generateVariable() + ', vars)'; | ||
} | ||
@@ -67,7 +67,13 @@ }; | ||
Context.prototype.pushPath = function(name) { | ||
this.scopes[this.scopes.length - 1].push(name); | ||
if (name) | ||
{ | ||
this.scopes[this.scopes.length - 1].push(name); | ||
} | ||
}; | ||
Context.prototype.popPath = function() { | ||
this.scopes[this.scopes.length - 1].pop(); | ||
Context.prototype.popPath = function(name) { | ||
if (name) | ||
{ | ||
this.scopes[this.scopes.length - 1].pop(); | ||
} | ||
}; | ||
@@ -74,0 +80,0 @@ |
{ | ||
"name": "binary-parser", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Blazing-fast binary parser builder", | ||
"main": "lib/binary_parser.js", | ||
"devDependencies": { | ||
"istanbul": "^0.3.14", | ||
"mocha": "^2.2.5" | ||
"istanbul": "^0.4.5", | ||
"mocha": "^3.5.0" | ||
}, | ||
@@ -26,3 +26,3 @@ "scripts": { | ||
"email": "keichi.t@me.com", | ||
"url": "http://blog.keichi.net/" | ||
"url": "https://keichi.net/" | ||
}, | ||
@@ -32,6 +32,6 @@ "license": "MIT", | ||
"type": "git", | ||
"url": "http://github.com/Keichi/binary-parser.git" | ||
"url": "http://github.com/keichi/binary-parser.git" | ||
}, | ||
"bugs": "http://github.com/Keichi/binary-parser/issues", | ||
"bugs": "http://github.com/keichi/binary-parser/issues", | ||
"dependencies": {} | ||
} |
143
README.md
@@ -94,3 +94,3 @@ # Binary-parser | ||
var parser = new Parser() | ||
// Signed 32-bit integer (little endian) | ||
// Signed 32-bit integer (little endian) | ||
.int32le('a') | ||
@@ -130,2 +130,3 @@ // Unsigned 8-bit integer | ||
- `zeroTerminated` - (Optional, defaults to `false`) If true, then this parser reads until it reaches zero. | ||
- `greedy` - (Optional, defaults to `false`) If true, then this parser reads until it reaches the end of the buffer. Will consume zero-bytes. | ||
- `stripNull` - (Optional, must be used with `length`) If true, then strip null characters from end of the string | ||
@@ -153,59 +154,59 @@ | ||
- `length` - (either `length`, `lengthInBytes`, or `readUntil` is required) Length of the array. Can be a number, string or a function. | ||
Use number for statically sized arrays. | ||
Use number for statically sized arrays. | ||
- `lengthInBytes` - (either `length`, `lengthInBytes`, or `readUntil` is required) Length of the array expressed in bytes. Can be a number, string or a function. | ||
Use number for statically sized arrays. | ||
Use number for statically sized arrays. | ||
- `readUntil` - (either `length`, `lengthInBytes`, or `readUntil` is required) If `'eof'`, then this parser | ||
reads until the end of `Buffer` object. If function it reads until the function returns true. | ||
reads until the end of `Buffer` object. If function it reads until the function returns true. | ||
```javascript | ||
var parser = new Parser() | ||
// Statically sized array | ||
.array('data', { | ||
type: 'int32', | ||
length: 8 | ||
}) | ||
// Statically sized array | ||
.array('data', { | ||
type: 'int32', | ||
length: 8 | ||
}) | ||
// Dynamically sized array (reference another variable) | ||
.uint8('dataLength') | ||
.array('data2', { | ||
type: 'int32', | ||
length: 'dataLength' | ||
}) | ||
// Dynamically sized array (references another variable) | ||
.uint8('dataLength') | ||
.array('data2', { | ||
type: 'int32', | ||
length: 'dataLength' | ||
}) | ||
// Dynamically sized array (with some calculation) | ||
.array('data3', { | ||
type: 'int32', | ||
length: function() { return this.dataLength - 1; } // other fields are available through this | ||
}); | ||
// Dynamically sized array (with some calculation) | ||
.array('data3', { | ||
type: 'int32', | ||
length: function() { return this.dataLength - 1; } // other fields are available through this | ||
}); | ||
// Statically sized array | ||
.array('data4', { | ||
type: 'int32', | ||
lengthInBytes: 16 | ||
}) | ||
// Statically sized array | ||
.array('data4', { | ||
type: 'int32', | ||
lengthInBytes: 16 | ||
}) | ||
// Dynamically sized array (reference another variable) | ||
.uint8('dataLengthInBytes') | ||
.array('data5', { | ||
type: 'int32', | ||
lengthInBytes: 'dataLengthInBytes' | ||
}) | ||
// Dynamically sized array (references another variable) | ||
.uint8('dataLengthInBytes') | ||
.array('data5', { | ||
type: 'int32', | ||
lengthInBytes: 'dataLengthInBytes' | ||
}) | ||
// Dynamically sized array (with some calculation) | ||
.array('data6', { | ||
type: 'int32', | ||
lengthInBytes: function() { return this.dataLengthInBytes - 4; } // other fields are available through this | ||
}) | ||
// Dynamically sized array (with some calculation) | ||
.array('data6', { | ||
type: 'int32', | ||
lengthInBytes: function() { return this.dataLengthInBytes - 4; } // other fields are available through this | ||
}) | ||
// Dynamically sized array (with stop-check on parsed item) | ||
.array('data7', { | ||
type: 'int32', | ||
readUntil: function(item, buffer) { return item === 42 } // stop when specific item is parsed. buffer can be used to perform a read-ahead. | ||
}); | ||
// Dynamically sized array (with stop-check on parsed item) | ||
.array('data7', { | ||
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('data8', { | ||
type: userDefinedParser, | ||
length: 'dataLength' | ||
}); | ||
// Use user defined parser object | ||
.array('data8', { | ||
type: userDefinedParser, | ||
length: 'dataLength' | ||
}); | ||
``` | ||
@@ -219,5 +220,5 @@ | ||
- `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 | ||
when `tag` equals the key value. | ||
when `tag` equals the key value. | ||
- `defaultChoice` - (Optional) In case of the tag value doesn't match any of `choices` use this parser. | ||
@@ -231,11 +232,11 @@ | ||
var parser = new Parser() | ||
.uint8('tagValue') | ||
.choice('data', { | ||
tag: 'tagValue', | ||
choices: { | ||
1: parser1, // When tagValue == 1, execute parser1 | ||
4: parser2, // When tagValue == 4, execute parser2 | ||
5: parser3 // When tagValue == 5, execute parser3 | ||
} | ||
}); | ||
.uint8('tagValue') | ||
.choice('data', { | ||
tag: 'tagValue', | ||
choices: { | ||
1: parser1, // When tagValue == 1, execute parser1 | ||
4: parser2, // When tagValue == 4, execute parser2 | ||
5: parser3 // When tagValue == 5, execute parser3 | ||
} | ||
}); | ||
``` | ||
@@ -259,8 +260,8 @@ | ||
.endianess('le') | ||
// You can specify endianess explicitly | ||
.uint16be('a') | ||
// You can specify endianess explicitly | ||
.uint16be('a') | ||
.uint32le('a') | ||
// Or you can omit endianess (in this case, little-endian is used) | ||
.uint16('b') | ||
.int32('c') | ||
// Or you can omit endianess (in this case, little-endian is used) | ||
.uint16('b') | ||
.int32('c') | ||
``` | ||
@@ -364,10 +365,10 @@ | ||
- `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('.'); } | ||
}); | ||
``` | ||
```javascript | ||
var parser = new Parser() | ||
.array('ipv4', { | ||
type: uint8, | ||
length: '4', | ||
formatter: function(arr) { return arr.join('.'); } | ||
}); | ||
``` | ||
@@ -383,3 +384,3 @@ - `assert` - Do assertion on the parsed result (useful for checking magic numbers and so on). | ||
var ClassFile = | ||
Parser.start() | ||
Parser.start() | ||
.endianess('big') | ||
@@ -386,0 +387,0 @@ .uint32('magic', {assert: 0xcafebabe}) |
@@ -324,2 +324,29 @@ var assert = require('assert'); | ||
}); | ||
it('should allow parent parser attributes as choice key', function() { | ||
var ChildParser = Parser.start() | ||
.choice('data', { | ||
tag: function(vars) { | ||
return vars.version; | ||
}, | ||
choices: { | ||
1: Parser.start().uint8('v1'), | ||
2: Parser.start().uint16('v2'), | ||
} | ||
}); | ||
var ParentParser = Parser.start() | ||
.uint8('version') | ||
.nest('child', { type: ChildParser }); | ||
var buffer = new Buffer([0x1, 0x2]); | ||
assert.deepEqual(ParentParser.parse(buffer), { | ||
version: 1, child: { data: { v1: 2 } } | ||
}); | ||
buffer = new Buffer([0x2, 0x3, 0x4]); | ||
assert.deepEqual(ParentParser.parse(buffer), { | ||
version: 2, child: { data: { v2: 0x0304 } } | ||
}); | ||
}); | ||
}); | ||
@@ -645,10 +672,10 @@ | ||
describe('Buffer parser', function() { | ||
//this is a test for testing a fix of a bug, that removed the last byte of the | ||
//this is a test for testing a fix of a bug, that removed the last byte of the | ||
//buffer parser | ||
it('should return a buffer with same size', function() { | ||
var bufferParser = new Parser() | ||
.buffer('buf', { | ||
readUntil: 'eof', | ||
formatter: function(buffer) { | ||
formatter: function(buffer) { | ||
return buffer; | ||
@@ -695,5 +722,6 @@ } | ||
type: 'int8' | ||
}); | ||
}) | ||
.buffer('raw', {length:8}); | ||
assert.equal(parser.sizeOf(), 1 + 4 + 10 + 2 + 3); | ||
assert.equal(parser.sizeOf(), 1 + 4 + 10 + 2 + 3 + 8); | ||
}); | ||
@@ -700,0 +728,0 @@ it('should assert parsed values', function() { |
@@ -256,2 +256,11 @@ var assert = require('assert'); | ||
}); | ||
it('should parse string greedily with zero-bytes internally', function() { | ||
var buffer = new Buffer('abc\u0000defghij\u0000'); | ||
var parser = Parser.start() | ||
.string('a', {greedy: true}); | ||
assert.deepEqual(parser.parse(buffer), { | ||
a: 'abc\u0000defghij\u0000' | ||
}); | ||
}); | ||
}); | ||
@@ -258,0 +267,0 @@ |
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
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
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
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
135742
1924
400