Skip to content

Commit

Permalink
Compiled incremental signed integer parsers.
Browse files Browse the repository at this point in the history
Closes #223.
See #184.
  • Loading branch information
flatheadmill committed Aug 14, 2013
1 parent d597c32 commit ebb9463
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 25 deletions.
63 changes: 51 additions & 12 deletions composers.js
Expand Up @@ -17,6 +17,14 @@ function hoister () {
}
}

function fixupSignage (field, operation) {
operation('\
_$field = (_$field & $sign) ? ($mask - _$field + 1) * -1 : _$field \n\
')
operation.$sign('0x80' + new Array(field.bytes).join('00'))
operation.$mask('0xff' + new Array(field.bytes).join('ff'))
}

function composeIncrementalParser (ranges) {

var cases = source();
Expand Down Expand Up @@ -76,8 +84,13 @@ function composeIncrementalParser (ranges) {
if (start == end) return start \n\
_$field += Math.pow(256, bite) * buffer[start++] \n\
$direction \n\
} \n\
object[$name] = _$field')
}')
if (field.signed) {
fixupSignage(field, operation)
}
operation('\
object[$name] = _$field \n\
')
operation.$stop(stop)
operation.$name(JSON.stringify(field.name))
operation.$field(field.name)
Expand All @@ -91,7 +104,7 @@ function composeIncrementalParser (ranges) {

var parser = source()
parser('\
switch (index) { \
switch (index) { \n\
$cases \n\
} \n\
\n\
Expand All @@ -117,7 +130,8 @@ function composeIncrementalParser (ranges) {
}

exports.composeParser = function (ranges) {
var parser = source()
var sections = source()
var hoist = hoister()

ranges.forEach(function (range) {
var section = source()
Expand All @@ -137,12 +151,13 @@ exports.composeParser = function (ranges) {
offset += field.bytes * field.repeat
} else {
var assignment = source()
if (field.bytes == 1) {
if (field.bytes == 1 && ! field.signed) {
assignment('\n\
$variable = buffer[$inc] \n\
')
assignment.$inc(offset ? 'start + $offset' : 'start')
assignment.$offset && assignment.$offset(offset)
assignment.$variable('object[$name]')
offset++
} else {
var little = field.endianness == 'l'
Expand Down Expand Up @@ -172,25 +187,49 @@ exports.composeParser = function (ranges) {
$variable = \n\
$read \n\
')
if (field.signed) {
assignment.$variable('_$field')
assignment.$field(field.name)
hoist('_' + field.name)
fixupSignage(field, assignment)
assignment('\
object[$name] = _$field \n\
')
} else {
assignment.$variable('object[$name]')
assignment.$name(JSON.stringify(field.name))
}
read = String(read).replace(/ \+$/, '')
assignment.$read(read)
}
assignment.$variable('object[$name]')
assignment.$name(JSON.stringify(field.name))
section(String(assignment))
assignment.$name(JSON.stringify(field.name))
section(String(assignment))
}
})

if (range.fixed) section('\n\
start += $size \n\
')

parser(String(section))
sections(section)
})

parser('\n\
return callback(object) \n\
')
var parser = source()
if (hoist()) {
parser('\n\
$variables \n\
$sections \n\
return callback(object) \n\
')
parser.$variables(hoist())
} else {
parser('\n\
$sections \n\
\n\
return callback(object) \n\
')
}
parser.$sections(sections)

var constructor = source('\
var inc \n\
Expand Down
1 change: 0 additions & 1 deletion index.js
Expand Up @@ -15,7 +15,6 @@ function canCompileParserUsingSource (pattern) {
return pattern.every(function (part) {
return !/^[f]$/.test(part.type)
&& !part.arrayed
&& !part.signed
&& !part.packing
&& !part.alternation
&& !part.pipeline
Expand Down
39 changes: 33 additions & 6 deletions t/parser/byte-signed.t.js 100755 → 100644
@@ -1,7 +1,34 @@
#!/usr/bin/env node
require('./proof')(0, function (parseEqual) {
parseEqual('foo:-b8', [ 0xff ], 1, {foo:-1}, 'negative')
parseEqual('foo:-b8', [ 0x80 ], 1, {foo:-128}, 'minimum')
parseEqual('foo:-b8', [ 0x7f ], 1, {foo:127}, 'maximum')
parseEqual('foo:-b8', [ 0x02 ], 1, {foo:2}, 'positive')
require('./proof')(0, function (parse) {
parse({
message: 'negative',
pattern: 'foo: -b8',
bytes: [ 0xff ],
length: 1,
expected: { foo: -1 },
require: true
})
parse({
message: 'minimum',
pattern: 'foo: -b8',
bytes: [ 0x80 ],
length: 1,
expected: { foo: -128 },
require: true
})
parse({
message: 'maximum',
pattern: 'foo: -b8',
bytes: [ 0x7f ],
length: 1,
expected: { foo: 127 },
require: true
})
parse({
message: 'positive',
pattern: 'foo: -b8',
bytes: [ 0x02 ],
length: 1,
expected: { foo: 2 },
require: true
})
})
39 changes: 33 additions & 6 deletions t/parser/short-signed.t.js 100755 → 100644
@@ -1,7 +1,34 @@
#!/usr/bin/env node
require('./proof')(0, function (parseEqual) {
parseEqual({ require: true }, 'foo: -b16', [ 0x80, 0x00 ], 2, { foo: -32768 }, 'mininum')
parseEqual('foo: -b16', [ 0xff, 0xff ], 2, { foo: -1 }, 'negative')
parseEqual('foo: -b16', [ 0x7f, 0xff ], 2, { foo: 32767 }, 'maximum')
parseEqual('foo: -b16', [ 0x01, 0x02 ], 2, { foo: 258 }, 'positive')
require('./proof')(0, function (parse) {
parse({
message: 'mininum',
pattern: 'foo: -b16',
bytes: [ 0x80, 0x00 ],
length: 2,
expected: { foo: -32768 },
require: true
})
parse({
message: 'negative',
pattern: 'foo: -b16',
bytes: [ 0xff, 0xff ],
length: 2,
expected: { foo: -1 },
require: true
})
parse({
message: 'maximum',
pattern: 'foo: -b16',
bytes: [ 0x7f, 0xff ],
length: 2,
expected: { foo: 32767 },
require: true
})
parse({
message: 'positive',
pattern: 'foo: -b16',
bytes: [ 0x01, 0x02 ],
length: 2,
expected: { foo: 258 },
require: true
})
})

0 comments on commit ebb9463

Please sign in to comment.