Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add test for event emitting

  • Loading branch information...
commit 721fa9119a8547b30bd97cb3492aee618df5a89c 1 parent 1c6c1ea
@Floby authored
View
34 examples/emit.js
@@ -0,0 +1,34 @@
+var ParseStream = require('../lib/ParseStream');
+var assert = require('assert');
+
+var o ;
+var json = JSON.stringify(o = {
+ coucou: "salut",
+ number: 8,
+ bool: true,
+ meh: null,
+ nested_array: [
+ {
+ float: 1000.1,
+ string: "a long string ? \" coucou 'oui oui non non' \n\r",
+ nothingmuch: null
+ },
+ 5,
+ 8,
+ "yet another string"
+ ]
+});
+
+var p = new ParseStream();
+function log_event (value, path) {
+ console.log('at %s: %s', path, value);
+}
+
+//p.on('*', log_event);
+
+p.on('end', function(o) {
+ var res = JSON.stringify(o);
+ //assert.equal(res, json, "the objects are not identical");
+});
+p.end(json);
+
View
51 lib/ParseStream.js
@@ -2,6 +2,7 @@ var Parser = require('parser');
var Tokenizer = require('./JsonTokenizer');
var util = require('util');
var assert = require('assert');
+var expandPath = require('./json_path').expand;
/**
@@ -9,11 +10,12 @@ var assert = require('assert');
* @constructor
* @extends Parser
*/
-function ParseStream () {
+function ParseStream (noRoot) {
// call the parent constructor that needs a tokenizer as parameter
Parser.call(this, new Tokenizer());
this._object;
+ this._noRoot = noRoot;
var self = this;
this.rootObjectPath = '$'
@@ -23,13 +25,18 @@ function ParseStream () {
* @param value the value at top level
* @return JSONPath to the root element
*/
- function initialSet (value) {
- self._object = value;
- self.emitValue(self.rootObjectPath, value);
+ function initialSet (value, dispose) {
+ if(!noRoot) {
+ self._object = value;
+ }
+ var handled = self.emitValue(self.rootObjectPath, value);
+ if(!handled && typeof dispose == 'function') {
+ dispose();
+ }
return self.rootObjectPath;
}
- this.initialHandler(this.value(initialSet, '$'));
+ this.initialHandler(this.value(initialSet));
// TODO set a default handler which is stricter than `ignore`
this.defaultHandler(function(token, type, next) {
if(type !== 'eof') {
@@ -43,13 +50,15 @@ util.inherits(ParseStream, Parser);
* emits values out of the parser according to their JSONPath
* @param path the path of the value to emit
* @param value value to emit
- * @return void
+ * @return boolean weather or not the event was handled
*/
ParseStream.prototype.emitValue = function emitValue(path, value) {
var type = null === value ? null : value.constructor.name;
- console.log('emitting %s at %s = ', type, path, value);
- // here we should emit these for real
- this.emit(path, value);
+ var res = !this._noRoot;
+ expandPath(path).forEach(function(p) {
+ res = res || this.emit(p, value, path);
+ }.bind(this));
+ return res;
};
/**
@@ -122,7 +131,7 @@ ParseStream.prototype.native = function Native(set) {
ParseStream.prototype.array = function array(set) {
var a = [];
var self = this;
- path = set(a);
+ var path = set(a, function() { a = null });
var index = 0;
/**
@@ -130,10 +139,15 @@ ParseStream.prototype.array = function array(set) {
* @param value the value to push to the array
* @return the full JSONPath to this value
*/
- function arraySet (value) {
- a.push(value);
+ function arraySet (value, dispose) {
+ if(a) {
+ a.push(value);
+ }
var newPath = self.makeArrayPath(path, index++);
- self.emitValue(newPath, value);
+ var handled = self.emitValue(newPath, value);
+ if(!handled && typeof dispose == 'function') {
+ dispose();
+ }
return newPath;
}
return function array (token, type, next) {
@@ -157,7 +171,7 @@ ParseStream.prototype.array = function array(set) {
*/
ParseStream.prototype.object = function object(set) {
var o = {};
- path = set(o);
+ var path = set(o, function() { o = null });
var self = this;
/**
@@ -167,9 +181,14 @@ ParseStream.prototype.object = function object(set) {
* @return the full JSONPath of that value
*/
function objectSet (label, value) {
- o[label] = value;
+ if(o) {
+ o[label] = value;
+ }
var newPath = self.makeObjectPath(path, label);
- self.emitValue(newPath, value);
+ var handled = self.emitValue(newPath, value);
+ if(!handled && typeof dispose == 'function') {
+ dispose();
+ }
return newPath;
}
View
8 lib/index.js
@@ -1,8 +1,8 @@
-exports.ParseStream = require('./ParseStream');
-exports.StringifyStream = require('./StringifyStream');
+var ParseStream = exports.ParseStream = require('./ParseStream');
+//exports.StringifyStream = require('./StringifyStream');
-exports.createParseStream = function createParseStream() {
- return new ParseStream;
+exports.createParseStream = function createParseStream(noStore) {
+ return new ParseStream(noStore);
}
exports.createStringifyStream = function createStringifyStream(object) {
return new StringifyStream(object);
View
41 lib/json_path.js
@@ -0,0 +1,41 @@
+// that's the regex we use to split up a
+// canonical json path
+var regex = /^(\[([^\[\]]*)\])(.*)$/;
+
+exports.expand = function expand(JSONPath) {
+ // TODO assert that JSONPath is a canonical URL
+ if('' == JSONPath) return [''];
+ var res = [];
+ if(JSONPath[0] === '$') {
+ var res = ['*'];
+ expand(JSONPath.substring(1)).map(function(p) {
+ res.push('$' + p);
+ });
+ return res.sort();
+ }
+
+ var m = regex.exec(JSONPath);
+ if(!m) return [''];
+
+ var sub = expand(m[3]);
+
+ sub.forEach(function(e) {
+ res.push(m[1] + e);
+ res.push('[*]' + e);
+ });
+
+ try {
+ var key = JSON.parse(m[2]);
+ if(typeof key == 'string') {
+ sub.forEach(function(p) {
+ res.push('.' + key + p);
+ res.push('.' + '*' + p);
+ })
+ }
+ } catch(e) {
+ // not a parsable key
+ }
+
+ return res.sort();
+}
+
View
31 test/test-00-parse-values.js
@@ -0,0 +1,31 @@
+var createParseStream = require('../').createParseStream;
+
+function testParsedEquals(v) {
+ return function(test) {
+ var p = createParseStream();
+ p.on('end', function(value) {
+ test.equal(JSON.stringify(value), JSON.stringify(v), "parsed value should be identical");
+ test.done();
+ });
+ p.end(JSON.stringify(v));
+ }
+}
+
+exports.parseInt = testParsedEquals(8);
+exports.parseFloat = testParsedEquals(12.98);
+exports.parseBoolean = testParsedEquals(true);
+exports.parseString = testParsedEquals("o hai frendz");
+
+exports.parseEmptyArray = testParsedEquals([]);
+exports.parseStringArray = testParsedEquals(["O hai", 'hello', "This is a text\n", "\x65ಠ"]);
+exports.parseMixedArray = testParsedEquals([5, true, null, 'hello', 5e12]);
+exports.parseArrayInArray = testParsedEquals([[4545], [true, false]]);
+
+exports.parseEmptyObject = testParsedEquals({});
+exports.parseMixedObject = testParsedEquals({
+ hello: 'goodbye',
+ one: 1,
+ yes: true,
+ nothing: null,
+ great: 1.8e20,
+})
Please sign in to comment.
Something went wrong with that request. Please try again.