UNPKG

simple-object-stream

Version:

A Transform stream which parses json from plaintext input.

237 lines (225 loc) 9.89 kB
// Generated by CoffeeScript 1.9.2 (function() { var SimpleObjectStream, Transform, util, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; util = require('util'); Transform = require('stream').Transform; module.exports = SimpleObjectStream = (function(superClass) { extend(SimpleObjectStream, superClass); function SimpleObjectStream() { var cbError; if (!this instanceof SimpleObjectStream) { return new SimpleObjectStream; } else { Transform.call(this, { readableObjectMode: true }); this.delimiterStack = []; this.curObjArr = []; this.prevChar = ""; this.inString = false; this.curKey = []; this.curVal = []; this.isKey = false; this.buffer = ""; cbError = (function(_this) { return function(err) { return _this.emit('error', err); }; })(this); this.on('pipe', (function(_this) { return function(src) { return src.on('error', cbError); }; })(this)); this.on('unpipe', (function(_this) { return function(src) { return src.removeListener('error', cbError); }; })(this)); } } SimpleObjectStream.prototype._flush = function(callback) { this.pushObjs(this.buffer); if (this.buffer.match(/[^\s]/g)) { this.emit('error', new Error("Unparsable end of stream.")); } return typeof callback === "function" ? callback() : void 0; }; SimpleObjectStream.prototype._transform = function(chunk, encoding, callback) { var str; str = this.buffer + chunk.toString(); this.pushObjs(str); return typeof callback === "function" ? callback() : void 0; }; SimpleObjectStream.prototype.pushObjs = function(str) { var c, err, finalObj, i, j, prevDelim, ref, results; results = []; for (i = j = 0, ref = str.length - 1; j <= ref; i = j += 1) { c = str.charAt(i); if (this.inString) { if (this.isKey) { this.curKey.push(c); } else { this.curVal.push(c); } if (c === "\"" && this.prevChar !== "\\") { this.inString = false; } results.push(this.prevChar = c); } else { if (c === "{" || c === "[") { if (this.prevChar === "" || this.prevChar === ":") { this.delimiterStack.push(c); this.curObjArr.push(c); this.prevChar = c; if (c === "{") { results.push(this.isKey = true); } else { results.push(void 0); } } else { results.push(this.emit('error', new Error("input stream not valid json: invalid positioning of '" + c + "' at " + (this.curObjArr.join(""))))); } } else if (c === "]" || c === "}") { prevDelim = this.delimiterStack.pop(); if (!this.isKey && this.curVal.join("").match(/(true|false|null|[0-9\.]+|"[^"]*")/)) { if (prevDelim === "[" && c !== "]" || prevDelim === "{" && c !== "}") { results.push(this.emit('error', new Error("input stream not valid json: invalid type of closing '" + c + "' at " + (this.curObjArr.join(""))))); } else { this.curObjArr.push(this.curVal.join("")); this.curObjArr.push(c); this.curVal = []; if (this.delimiterStack.length === 0) { try { finalObj = JSON.parse(this.curObjArr.join("")); this.emit('object', finalObj); this.push(JSON.stringify(finalObj)); this.buffer = str.substr(0, i + 1); } catch (_error) { err = _error; this.emit('error', err); } this.curObjArr = []; results.push(this.prevChar = ""); } else { results.push(this.prevChar = c); } } } else { if (prevDelim === "{" && c === "}") { this.curObjArr.push(c); if (this.delimiterStack.length === 0) { try { finalObj = JSON.parse(this.curObjArr.join("")); this.emit('object', finalObj); this.push(JSON.stringify(finalObj)); } catch (_error) { err = _error; this.emit('error', err); } this.curObjArr = []; results.push(this.prevChar = ""); } else { results.push(this.prevChar = c); } } else if (prevDelim === "[" && c === "]") { this.curObjArr.push(this.curKey.join("")); this.curObjArr.push(c); this.curKey = []; if (this.delimiterStack.length === 0) { try { finalObj = JSON.parse(this.curObjArr.join("")); this.emit('object', finalObj); this.push(JSON.stringify(finalObj)); } catch (_error) { err = _error; this.emit('error', err); } this.curObjArr = []; results.push(this.prevChar = ""); } else { results.push(this.prevChar = c); } } else { results.push(this.emit('error', new Error("input stream not valid json: invalid positioning of '" + c + "' at " + (this.curObjArr.join(""))))); } } } else if (c === ":") { if (this.delimiterStack[this.delimiterStack.length - 1] === "[") { results.push(this.emit('error', new Error("input stream not valid json: ':' within array at " + (this.curObjArr.join(""))))); } else if (this.isKey && this.prevChar === "\"") { this.isKey = false; this.curObjArr.push(this.curKey.join("")); this.curKey = []; this.curObjArr.push(c); results.push(this.prevChar = c); } else { results.push(this.emit('error', new Error("input stream not valid json: invalid positioning of ':' at " + (this.curObjArr.join(""))))); } } else if (c === ",") { if (this.delimiterStack[this.delimiterStack.length - 1] === "[" && this.curKey.join("").match(/(true|false|null|[0-9\.]+|"[^"]*")/)) { this.curObjArr.push(this.curKey.join("")); this.curKey = []; this.curObjArr.push(c); results.push(this.prevChar = c); } else if (!this.isKey && this.curVal.join("").match(/(true|false|null|[0-9\.]+|"[^"]*")/)) { this.isKey = true; this.curObjArr.push(this.curVal.join("")); this.curVal = []; this.curObjArr.push(c); results.push(this.prevChar = c); } else if (this.prevChar === "]" || this.prevChar === "}") { this.curObjArr.push(c); this.curVal = []; this.curKey = []; this.isKey = true; results.push(this.prevChar = c); } else { results.push(this.emit('error', new Error("input stream not valid json: invalid positioning of ',' at " + (this.curObjArr.join(""))))); } } else if (c === "\"") { if (this.prevChar === ":") { this.inString = true; this.curVal.push(c); results.push(this.prevChar = c); } else if (this.prevChar === "," || this.prevChar === "{" || this.prevChar === "[") { this.isKey = true; this.inString = true; this.curKey.push(c); results.push(this.prevChar = c); } else { results.push(this.emit('error', new Error("input stream not valid json: invalid positioning of '\"' at " + (this.curObjArr.join(""))))); } } else if (c.match(/[truefasnl]/)) { if (!this.isKey) { this.curVal.push(c); results.push(this.prevChar = c); } else if (this.delimiterStack[this.delimiterStack.length - 1] === "[") { this.curKey.push(c); results.push(this.prevChar = c); } else { results.push(this.emit('error', new Error("input stream not valid json: invalid positioning of 'true/false' at " + (this.curObjArr.join(""))))); } } else if (c.match(/[0-9\.]/)) { if (!this.isKey) { this.curVal.push(c); results.push(this.prevChar = c); } else if (this.delimiterStack[this.delimiterStack.length - 1] === "[") { this.curKey.push(c); results.push(this.prevChar = c); } else { results.push(this.emit('error', new Error("input stream not valid json: invalid positioning of numberic literal at " + (this.curObjArr.join(""))))); } } else if (c.match(/\s/)) { } else { results.push(this.emit('error', new Error("input stream not valid json: invalid char: " + c))); } } } return results; }; return SimpleObjectStream; })(Transform); }).call(this);