Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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.