Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Minor tidies

Including making compiled constructor function toString()able, and
making matchers use unification. Which is a fancy way of saying values
given in the env must match exactly (I don't think this behaviour was
even defined before).
  • Loading branch information...
commit d45fccb36b8f0bffda9a9115a4caefc19a8abae7 1 parent 26cf806
@squaremo authored
Showing with 37 additions and 33 deletions.
  1. +14 −7 README.md
  2. +23 −26 lib/compile.js
View
21 README.md
@@ -56,8 +56,8 @@ var p = bitsyntax.matcher('size:8, payload:size/binary',
Compiles a pattern as a string (or strings), to a function that will
return either a map of bindings, or `false`, given a buffer and
-optionally an environment. The environment contains values for the
-bound variables in the pattern (if there are any).
+optionally an environment. The environment contains values for bound
+variables in the pattern (if there are any).
```js
var p = bitsyntax.matcher('header:headerSize/binary, rest/binary');
@@ -71,8 +71,8 @@ the pattern; for example, if it has too few bytes, or a literal is not
present.
```js
-var p = bitsyntax.matcher('"foo:", str/binary');
-p(new Buffer("bar:humbug"));
+var p = bitsyntax.matcher('"foo=", str/binary');
+p(new Buffer("bar=humbug"));
// => false
```
@@ -161,7 +161,9 @@ series of segments.
The first part of a segment gives a variable name or a literal
value. If a variable name is given, the value matched by the segment
will be bound to that variable name for the rest of the pattern. If a
-literal value is given, the matched value must equal that value.
+literal value is given, the matched value must equal that value. If a
+variable's value is given in the environment, the matched value must
+equal the provided value.
When used in a builder, the literal value will be copied into the
buffer according to the type it is given. A variable name indicates a
@@ -255,8 +257,8 @@ its UTF8 encoding. For example,
matches any buffer that starts with the bytes `0x66, 0x6f, 0x6f, 0x62,
0x61, 0x72`.
-When used in a builder, a quoted string is copied verbatim into the
-result.
+When used in a builder, a quoted string is copied into the result as
+the bytes of its UTF8 encoding.
## Examples
@@ -297,3 +299,8 @@ integer as `len` and a buffer of length `len` as `str`.
Matches a binary of at least `2 + len` bytes, binds an unsigned 16-bit
integer as `len`, ignores the next `len` bytes, and binds the
remaining (possibly zero-length) binary as `rest`.
+
+ s:8, key:s/binary, value/binary
+
+When given the environment `{s:6, key: "foobar"}`, will match a binary
+starting with [6, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, ...].
View
49 lib/compile.js
@@ -1,4 +1,4 @@
-// Compile patterns to recognisers
+// Compile patterns to recognisers and constructors
require('buffer-more-ints');
var $ = require('util').format;
@@ -104,13 +104,20 @@ function match_seg(segment) {
get_string(segment);
break;
}
- $line("if (result === false) { return false; }");
+ $line("if (result === false) return false;");
if (segment.name) {
- $line("else { %s = result; }", var_name(segment.name));
+ // variable is given a value in the environment
+ $line("else if (%s !== undefined) {", var_name(segment.name));
+ // .. and it is not the same as that matched
+ $line("if (%s != result) return false;",
+ var_name(segment.name));
+ $line("}");
+ // variable is free
+ $line('else %s = result;', var_name(segment.name));
}
else {
var repr = JSON.stringify(segment.value);
- $line("else if (result != %s) { return false; }", repr);
+ $line("else if (result != %s) return false;", repr);
}
}
}
@@ -136,15 +143,14 @@ function variables(segments) {
function compile_pattern(segments) {
$start();
- $line("return function(binary, vars) {");
- $line("var bin = binary, scope = vars || {};");
+ $line("return function(binary, env) {");
+ $line("var bin = binary, env = env || {};");
$line("var offset = 0, binsize = bin.length * 8;");
$line("var bits, result, byteoffset;");
var varnames = variables(segments);
- var bindings = "";
for (var v = 0; v < varnames.length; v++) {
var name = varnames[v];
- $line("var %s = scope['%s'];", var_name(name), name);
+ $line("var %s = env['%s'];", var_name(name), name);
}
var len = segments.length;
@@ -155,14 +161,14 @@ function compile_pattern(segments) {
}
$line("if (offset == binsize) {");
- $line("var bindings = {");
+ $line("return {");
for (var v = 0; v < varnames.length; v++) {
var name = varnames[v];
$line("%s: %s,", name, var_name(name));
}
- $line('}');
- $line("return bindings; }");
- $line("else { return false; }");
+ $line('};');
+ $line('}'); // if offset == binsize
+ $line("else return false;");
$line("}"); // end function
var fn = new Function('parse_int', 'parse_float', $result());
@@ -212,7 +218,6 @@ function write_number(segment) {
segment.size, segment.unit);
}
else {
- // could do this statically of course
$line('size = %d;', (segment.size * segment.unit) / 8);
}
$line('%s(buf, val, offset, size, %s);',
@@ -254,10 +259,7 @@ function size_of(segments) {
}
}
-function compile_write(segments) {
- $start();
-
- $line('return function(buf, offset, bindings) {');
+function emit_write(segments) {
$line('var val, size;');
var len = segments.length;
@@ -266,24 +268,20 @@ function compile_write(segments) {
$line('// %s', JSON.stringify(segment));
write_seg(segment);
}
-
- $line('return offset;');
- $line('}'); // end function
- var fn = new Function('write_int', 'write_float', $result());
- return fn(write_int, write_float);
}
function compile_ctor(segments) {
- var writer = compile_write(segments);
$start();
$line('return function(bindings) {');
size_of(segments);
$line('var buf = new Buffer(buffersize);');
- $line('write(buf, 0, bindings);');
+ $line('var offset = 0;');
+ emit_write(segments);
$line('return buf;');
$line('}'); // end function
- return new Function('write', $result())(writer);
+ return new Function('write_int', 'write_float',
+ $result())(write_int, write_float);
}
module.exports.compile_pattern = compile_pattern;
@@ -292,7 +290,6 @@ module.exports.compile = function() {
var p = parse(str);
return compile_pattern(p);
};
-module.exports.compile_write = compile_write;
module.exports.compile_builder = function() {
var str = [].join.call(arguments, ',');
var p = parse(str);
Please sign in to comment.
Something went wrong with that request. Please try again.