Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

move object assembly logic outside of the json Parser object

  • Loading branch information...
commit fbe85a41f48ae13dfe10168546d291e69f4e8af9 1 parent 97da149
@chjj authored
Showing with 98 additions and 114 deletions.
  1. +98 −114 lib/json.js
View
212 lib/json.js
@@ -56,17 +56,17 @@ Parser.prototype.end = function(data) {
if (this.value) {
switch (this.state) {
case 'number':
- this.assemble('number', +this.value);
+ this.emit('number', +this.value);
break;
case 'value':
- this.assemble('string', this.value);
+ this.emit('string', this.value);
break;
default:
return this._unexpected('EOF');
}
}
- this.emit('end', this.data);
+ this.emit('end');
this._reset();
@@ -88,27 +88,27 @@ Parser.prototype._parse = function(data) {
if (this.value) {
return this._unexpected(ch);
}
- this.assemble('object start');
+ this.emit('object start');
break;
case '}':
if (this.value) {
- this.assemble('string', this.value);
+ this.emit('string', this.value);
this.value = '';
}
- this.assemble('object end');
+ this.emit('object end');
break;
case '[':
if (this.value) {
return this._unexpected(ch);
}
- this.assemble('array start');
+ this.emit('array start');
break;
case ']':
if (this.value) {
- this.assemble('string', this.value);
+ this.emit('string', this.value);
this.value = '';
}
- this.assemble('array end');
+ this.emit('array end');
break;
case '"':
if (this.value) {
@@ -118,7 +118,7 @@ Parser.prototype._parse = function(data) {
break;
case ',':
if (this.value) {
- this.assemble('string', this.value);
+ this.emit('string', this.value);
this.value = '';
}
break;
@@ -126,7 +126,7 @@ Parser.prototype._parse = function(data) {
if (!this.value) {
return this._unexpected(ch);
}
- this.assemble('object key', this.value);
+ this.emit('object key', this.value);
this.value = '';
break;
case '-':
@@ -168,19 +168,19 @@ Parser.prototype._parse = function(data) {
// check last byte of .value
// make sure it is a digit
this.state = 'value';
- this.assemble('number', +this.value);
+ this.emit('number', +this.value);
this.value = '';
- this.assemble('object end');
+ this.emit('object end');
break;
case ']':
this.state = 'value';
- this.assemble('number', +this.value);
+ this.emit('number', +this.value);
this.value = '';
- this.assemble('array end');
+ this.emit('array end');
break;
case ',':
this.state = 'value';
- this.assemble('number', +this.value);
+ this.emit('number', +this.value);
this.value = '';
break;
case 'e':
@@ -224,7 +224,7 @@ Parser.prototype._parse = function(data) {
default:
if (ch <= ' ') {
this.state = 'value';
- this.assemble('number', +this.value);
+ this.emit('number', +this.value);
this.value = '';
} else {
return this._unexpected(ch);
@@ -315,7 +315,7 @@ Parser.prototype._parse = function(data) {
}
case 'nul': {
this._expect(ch, 'l');
- this.assemble('null', null);
+ this.emit('null', null);
this.state = 'value';
break;
}
@@ -336,7 +336,7 @@ Parser.prototype._parse = function(data) {
}
case 'fals': {
this._expect(ch, 'e');
- this.assemble('boolean', false);
+ this.emit('boolean', false);
this.state = 'value';
break;
}
@@ -352,7 +352,7 @@ Parser.prototype._parse = function(data) {
}
case 'tru': {
this._expect(ch, 'e');
- this.assemble('boolean', true);
+ this.emit('boolean', true);
this.state = 'value';
break;
}
@@ -360,99 +360,7 @@ Parser.prototype._parse = function(data) {
}
};
-/**
- * Object Assembler
- */
-
-Parser.prototype.assemble = function(type, val) {
- switch (type) {
- case 'object start': {
- var object = {};
- this.assemble('value', object);
- this.stack.push(object);
- break;
- }
- case 'object key': {
- if (this.key != null) {
- return this._unexpected(':');
- }
- // not terribly necessary
- // but good for error messages
- if (!this.stack.length) {
- return this._unexpected(val);
- }
- this.key = val;
- break;
- }
- case 'object end': {
- var top = this.stack.pop();
- if (!top || Array.isArray(top)
- || this.key != null) {
- return this._unexpected('}');
- }
- this.emit('object', top);
- break;
- }
- case 'array start': {
- var array = [];
- this.assemble('value', array);
- this.stack.push(array);
- break;
- }
- case 'array end': {
- var top = this.stack.pop();
- if (!top || !Array.isArray(top)) {
- return this._unexpected(']');
- }
- this.emit('array', top);
- break;
- }
- case 'number':
- case 'string':
- case 'boolean':
- case 'null': {
- this.emit(type, val);
- this.assemble('value', val);
- break;
- }
- case 'value': {
- if (this.data === undefined) {
- if (this.key != null) {
- return this._unexpected(':');
- }
- this.data = val;
- return;
- }
-
- var top = this.stack[this.stack.length-1];
- if (!top) {
- // another value is being entered
- // we're only allowed one in json
- return this._unexpected(typeof val);
- }
-
- if (this.key == null) {
- if (!Array.isArray(top)) {
- return this._unexpected(typeof val);
- }
- top.push(val);
- } else {
- if (Array.isArray(top)) {
- return this._unexpected(':');
- }
- top[this.key] = val;
- this.key = null;
- }
- break;
- }
- }
-};
-
Parser.prototype._reset = function() {
- this.stack = [];
- this.key = null;
- this.data = undefined;
-
this.state = 'value';
this.value = '';
this.unicode = '';
@@ -517,14 +425,90 @@ exports.middleware = function(options) {
exports.handle = function(req, res, next, options) {
var parser = new Parser(options)
- , limit = options.limit;
+ , limit = options.limit
+ , stack = []
+ , data
+ , key;
+
+ parser.on('object start', function() {
+ var object = {};
+ onval(object);
+ stack.push(object);
+ });
+
+ parser.on('object key', function(val) {
+ if (key != null) {
+ return this._unexpected(':');
+ }
+ // not terribly necessary
+ // but good for error messages
+ if (!stack.length) {
+ return this._unexpected(val);
+ }
+ key = val;
+ });
+
+ parser.on('object end', function() {
+ var top = stack.pop();
+ if (!top || Array.isArray(top) || key != null) {
+ return this._unexpected('}');
+ }
+ });
+
+ parser.on('array start', function() {
+ var array = [];
+ onval(array);
+ stack.push(array);
+ });
+
+ parser.on('array end', function() {
+ var top = stack.pop();
+ if (!top || !Array.isArray(top)) {
+ return this._unexpected(']');
+ }
+ });
+
+ parser.on('number', onval);
+ parser.on('string', onval);
+ parser.on('boolean', onval);
+ parser.on('null', onval);
+
+ function onval(val) {
+ if (data === undefined) {
+ if (key != null) {
+ return parser._unexpected(':');
+ }
+ data = val;
+ return;
+ }
+
+ var top = stack[stack.length-1];
+ if (!top) {
+ // another value is being entered
+ // we're only allowed one in json
+ return parser._unexpected(typeof val);
+ }
+
+ if (key == null) {
+ if (!Array.isArray(top)) {
+ return parser._unexpected(typeof val);
+ }
+ top.push(val);
+ } else {
+ if (Array.isArray(top)) {
+ return parser._unexpected(':');
+ }
+ top[key] = val;
+ key = null;
+ }
+ }
parser.on('error', function(err) {
req.destroy();
next(err);
});
- parser.on('end', function(data) {
+ parser.on('end', function() {
req.body = data;
next();
});
Please sign in to comment.
Something went wrong with that request. Please try again.