pax_global_header00006660000000000000000000000064124133031310014501gustar00rootroot0000000000000052 comment=c0418ae41157517c777fa10e44466caa1351e333 node-clarinet-0.9.1+dfsg/000077500000000000000000000000001241330313100151535ustar00rootroot00000000000000node-clarinet-0.9.1+dfsg/.gitignore000066400000000000000000000000361241330313100171420ustar00rootroot00000000000000.DS_Store node_modules/ *.log node-clarinet-0.9.1+dfsg/.travis.yml000066400000000000000000000001231241330313100172600ustar00rootroot00000000000000language: "node_js" node_js: - 0.6 - 0.8 - 0.9 branches: only: - masternode-clarinet-0.9.1+dfsg/AUTHORS000066400000000000000000000001341241330313100162210ustar00rootroot00000000000000Nuno Job (http://nunojob.com/) Jann Horn node-clarinet-0.9.1+dfsg/LICENSE000066400000000000000000000052741241330313100161700ustar00rootroot00000000000000Copyright (c) Isaac Z. Schlueter ("Author") Copyright (c) 2011 nuno job All rights reserved. The BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The file "examples/strict.dtd" is licensed by the W3C and used according to the terms of the W3C SOFTWARE NOTICE AND LICENSE. See LICENSE-W3C.html for details. "String.fromCodePoint" used under the terms of the MIT license. Its license follows: Copyright Mathias Bynens Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-clarinet-0.9.1+dfsg/README.md000066400000000000000000000161421241330313100164360ustar00rootroot00000000000000# clarinet ![NPM Downloads](http://img.shields.io/npm/dm/clarinet.svg?style=flat) ![NPM Version](http://img.shields.io/npm/v/clarinet.svg?style=flat) `clarinet` is a sax-like streaming parser for JSON. works in the browser and node.js. `clarinet` is inspired (and forked) from [sax-js][saxjs]. just like you shouldn't use `sax` when you need `dom` you shouldn't use `clarinet` when you need `JSON.parse`. for a more detailed introduction and a performance study please refer to this [article][blog]. # design goals `clarinet` is very much like [yajl] but written in javascript: * written in javascript * portable * robust (~110 tests pass before even announcing the project) * data representation independent * fast * generates verbose, useful error messages including context of where the error occurs in the input text. * can parse json data off a stream, incrementally * simple to use * tiny # motivation the reason behind this work was to create better full text support in node. creating indexes out of large (or many) json files doesn't require a full understanding of the json file, but it does require something like `clarinet`. # installation ## node.js 1. install [npm] 2. `npm install clarinet` 3. `var clarinet = require('clarinet');` ## browser 1. minimize clarinet.js 2. load it into your webpage # usage ## basics ``` js var clarinet = require("clarinet") , parser = clarinet.parser() ; parser.onerror = function (e) { // an error happened. e is the error. }; parser.onvalue = function (v) { // got some value. v is the value. can be string, double, bool, or null. }; parser.onopenobject = function (key) { // opened an object. key is the first key. }; parser.onkey = function (key) { // got a key in an object. }; parser.oncloseobject = function () { // closed an object. }; parser.onopenarray = function () { // opened an array. }; parser.onclosearray = function () { // closed an array. }; parser.onend = function () { // parser stream is done, and ready to have more stuff written to it. }; parser.write('{"foo": "bar"}').close(); ``` ``` js // stream usage // takes the same options as the parser var stream = require("clarinet").createStream(options); stream.on("error", function (e) { // unhandled errors will throw, since this is a proper node // event emitter. console.error("error!", e) // clear the error this._parser.error = null this._parser.resume() }) stream.on("openobject", function (node) { // same object as above }) // pipe is supported, and it's readable/writable // same chunks coming in also go out. fs.createReadStream("file.json") .pipe(stream) .pipe(fs.createReadStream("file-altered.json")) ``` ## arguments pass the following arguments to the parser function. all are optional. `opt` - object bag of settings regarding string formatting. all default to `false`. settings supported: * `trim` - boolean. whether or not to trim text and comment nodes. * `normalize` - boolean. if true, then turn any whitespace into a single space. ## methods `write` - write bytes onto the stream. you don't have to do this all at once. you can keep writing as much as you want. `close` - close the stream. once closed, no more data may be written until it is done processing the buffer, which is signaled by the `end` event. `resume` - to gracefully handle errors, assign a listener to the `error` event. then, when the error is taken care of, you can call `resume` to continue parsing. otherwise, the parser will not continue while in an error state. ## members at all times, the parser object will have the following members: `line`, `column`, `position` - indications of the position in the json document where the parser currently is looking. `closed` - boolean indicating whether or not the parser can be written to. if it's `true`, then wait for the `ready` event to write again. `opt` - any options passed into the constructor. and a bunch of other stuff that you probably shouldn't touch. ## events all events emit with a single argument. to listen to an event, assign a function to `on`. functions get executed in the this-context of the parser object. the list of supported events are also in the exported `EVENTS` array. when using the stream interface, assign handlers using the `EventEmitter` `on` function in the normal fashion. `error` - indication that something bad happened. the error will be hanging out on `parser.error`, and must be deleted before parsing can continue. by listening to this event, you can keep an eye on that kind of stuff. note: this happens *much* more in strict mode. argument: instance of `Error`. `value` - a json value. argument: value, can be a bool, null, string on number `openobject` - object was opened. argument: key, a string with the first key of the object (if any) `key` - an object key: argument: key, a string with the current key `closeobject` - indication that an object was closed `openarray` - indication that an array was opened `closearray` - indication that an array was closed `end` - indication that the closed stream has ended. `ready` - indication that the stream has reset, and is ready to be written to. ## samples some [samples] are available to help you get started. one that creates a list of top npm contributors, and another that gets a bunch of data from twitter and generates valid json. # roadmap check [issues] # contribute everyone is welcome to contribute. patches, bug-fixes, new features 1. create an [issue][issues] so the community can comment on your idea 2. fork `clarinet` 3. create a new branch `git checkout -b my_branch` 4. create tests for the changes you made 5. make sure you pass both existing and newly inserted tests 6. commit your changes 7. push to your branch `git push origin my_branch` 8. create an pull request helpful tips: check `index.html`. there's two env vars you can set, `CRECORD` and `CDEBUG`. * `CRECORD` allows you to `record` the event sequence from a new json test so you don't have to write everything. * `CDEBUG` can be set to `info` or `debug`. `info` will `console.log` all emits, `debug` will `console.log` what happens to each char. in `test/clarinet.js` there's two lines you might want to change. `#8` where you define `seps`, if you are isolating a test you probably just want to run one sep, so change this array to `[undefined]`. `#718` which says `for (var key in docs) {` is where you can change the docs you want to run. e.g. to run `foobar` i would do something like `for (var key in {foobar:''}) {`. # meta * code: `git clone git://github.com/dscape/clarinet.git` * home: * bugs: * build: [![build status](https://secure.travis-ci.org/dscape/clarinet.png)](http://travis-ci.org/dscape/clarinet) `(oO)--',-` in [caos] [npm]: http://npmjs.org [issues]: http://github.com/dscape/clarinet/issues [caos]: http://caos.di.uminho.pt/ [saxjs]: http://github.com/isaacs/sax-js [yajl]: https://github.com/lloyd/yajl [samples]: https://github.com/dscape/clarinet/tree/master/samples [blog]: http://writings.nunojob.com/2011/12/clarinet-sax-based-evented-streaming-json-parser-in-javascript-for-the-browser-and-nodejs.html node-clarinet-0.9.1+dfsg/clarinet.js000066400000000000000000000515361241330313100173240ustar00rootroot00000000000000;(function (clarinet) { // non node-js needs to set clarinet debug on root var env , fastlist ; if(typeof process === 'object' && process.env) env = process.env; else env = window; clarinet.parser = function (opt) { return new CParser(opt);}; clarinet.CParser = CParser; clarinet.CStream = CStream; clarinet.createStream = createStream; clarinet.MAX_BUFFER_LENGTH = 64 * 1024; clarinet.DEBUG = (env.CDEBUG==='debug'); clarinet.INFO = (env.CDEBUG==='debug' || env.CDEBUG==='info'); clarinet.EVENTS = [ "value" , "string" , "key" , "openobject" , "closeobject" , "openarray" , "closearray" , "error" , "end" , "ready" ]; var buffers = [ "textNode", "numberNode" ] , streamWraps = clarinet.EVENTS.filter(function (ev) { return ev !== "error" && ev !== "end"; }) , S = 0 , Stream ; clarinet.STATE = { BEGIN : S++ , VALUE : S++ // general stuff , OPEN_OBJECT : S++ // { , CLOSE_OBJECT : S++ // } , OPEN_ARRAY : S++ // [ , CLOSE_ARRAY : S++ // ] , TEXT_ESCAPE : S++ // \ stuff , STRING : S++ // "" , BACKSLASH : S++ , END : S++ // No more stack , OPEN_KEY : S++ // , "a" , CLOSE_KEY : S++ // : , TRUE : S++ // r , TRUE2 : S++ // u , TRUE3 : S++ // e , FALSE : S++ // a , FALSE2 : S++ // l , FALSE3 : S++ // s , FALSE4 : S++ // e , NULL : S++ // u , NULL2 : S++ // l , NULL3 : S++ // l , NUMBER_DECIMAL_POINT : S++ // . , NUMBER_DIGIT : S++ // [0-9] }; for (var s_ in clarinet.STATE) clarinet.STATE[clarinet.STATE[s_]] = s_; // switcharoo S = clarinet.STATE; if (!Object.create) { Object.create = function (o) { function f () { this["__proto__"] = o; } f.prototype = o; return new f; }; } if (!Object.getPrototypeOf) { Object.getPrototypeOf = function (o) { return o["__proto__"]; }; } if (!Object.keys) { Object.keys = function (o) { var a = []; for (var i in o) if (o.hasOwnProperty(i)) a.push(i); return a; }; } function checkBufferLength (parser) { var maxAllowed = Math.max(clarinet.MAX_BUFFER_LENGTH, 10) , maxActual = 0 ; for (var i = 0, l = buffers.length; i < l; i ++) { var len = parser[buffers[i]].length; if (len > maxAllowed) { switch (buffers[i]) { case "text": closeText(parser); break; default: error(parser, "Max buffer length exceeded: "+ buffers[i]); } } maxActual = Math.max(maxActual, len); } parser.bufferCheckPosition = (clarinet.MAX_BUFFER_LENGTH - maxActual) + parser.position; } function clearBuffers (parser) { for (var i = 0, l = buffers.length; i < l; i ++) { parser[buffers[i]] = ""; } } var stringTokenPattern = /[\\"\n]/g; function CParser (opt) { if (!(this instanceof CParser)) return new CParser (opt); var parser = this; clearBuffers(parser); parser.bufferCheckPosition = clarinet.MAX_BUFFER_LENGTH; parser.q = parser.c = parser.p = ""; parser.opt = opt || {}; parser.closed = parser.closedRoot = parser.sawRoot = false; parser.tag = parser.error = null; parser.state = S.BEGIN; parser.stack = new Array(); // mostly just for error reporting parser.position = parser.column = 0; parser.line = 1; parser.slashed = false; parser.unicodeI = 0; parser.unicodeS = null; parser.depth = 0; emit(parser, "onready"); } CParser.prototype = { end : function () { end(this); } , write : write , resume : function () { this.error = null; return this; } , close : function () { return this.write(null); } }; try { Stream = require("stream").Stream; } catch (ex) { Stream = function () {}; } function createStream (opt) { return new CStream(opt); } function CStream (opt) { if (!(this instanceof CStream)) return new CStream(opt); this._parser = new CParser(opt); this.writable = true; this.readable = true; //var Buffer = this.Buffer || function Buffer () {}; // if we don't have Buffers, fake it so we can do `var instanceof Buffer` and not throw an error this.bytes_remaining = 0; // number of bytes remaining in multi byte utf8 char to read after split boundary this.bytes_in_sequence = 0; // bytes in multi byte utf8 char to read this.temp_buffs = { "2": new Buffer(2), "3": new Buffer(3), "4": new Buffer(4) }; // for rebuilding chars split before boundary is reached this.string = ''; var me = this; Stream.apply(me); this._parser.onend = function () { me.emit("end"); }; this._parser.onerror = function (er) { me.emit("error", er); me._parser.error = null; }; streamWraps.forEach(function (ev) { Object.defineProperty(me, "on" + ev, { get : function () { return me._parser["on" + ev]; } , set : function (h) { if (!h) { me.removeAllListeners(ev); me._parser["on"+ev] = h; return h; } me.on(ev, h); } , enumerable : true , configurable : false }); }); } CStream.prototype = Object.create(Stream.prototype, { constructor: { value: CStream } }); CStream.prototype.write = function (data) { var data = new Buffer(data); for (var i = 0; i < data.length; i++) { var n = data[i]; // check for carry over of a multi byte char split between data chunks // & fill temp buffer it with start of this data chunk up to the boundary limit set in the last iteration if (this.bytes_remaining > 0) { for (var j = 0; j < this.bytes_remaining; j++) { this.temp_buffs[this.bytes_in_sequence][this.bytes_in_sequence - this.bytes_remaining + j] = data[j]; } this.string = this.temp_buffs[this.bytes_in_sequence].toString(); this.bytes_in_sequence = this.bytes_remaining = 0; i = i + j - 1; this._parser.write(this.string); this.emit("data", this.string); return true; } else if (this.bytes_remaining === 0 && n >= 128) { // else if no remainder bytes carried over, parse multi byte (>=128) chars one at a time if ((n >= 194) && (n <= 223)) this.bytes_in_sequence = 2; if ((n >= 224) && (n <= 239)) this.bytes_in_sequence = 3; if ((n >= 240) && (n <= 244)) this.bytes_in_sequence = 4; if ((this.bytes_in_sequence + i) > data.length) { // if bytes needed to complete char fall outside data length, we have a boundary split for (var k = 0; k <= (data.length - 1 - i); k++) { this.temp_buffs[this.bytes_in_sequence][k] = data[i + k]; // fill temp data of correct size with bytes available in this chunk } this.bytes_remaining = (i + this.bytes_in_sequence) - data.length; i = data.length - 1; } else { this.string = data.slice(i, (i + this.bytes_in_sequence)).toString(); i = i + this.bytes_in_sequence - 1; this._parser.write(this.string); this.emit("data", this.string); return true; } } else { this._parser.write(data.toString()); this.emit("data", data); return true; } } }; CStream.prototype.end = function (chunk) { if (chunk && chunk.length) this._parser.write(chunk.toString()); this._parser.end(); return true; }; CStream.prototype.on = function (ev, handler) { var me = this; if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) { me._parser["on"+ev] = function () { var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments); args.splice(0, 0, ev); me.emit.apply(me, args); }; } return Stream.prototype.on.call(me, ev, handler); }; CStream.prototype.destroy = function () { clearBuffers(this._parser); this.emit("close"); }; function emit(parser, event, data) { if(clarinet.INFO) console.log('-- emit', event, data); if (parser[event]) parser[event](data); } function emitNode(parser, event, data) { closeValue(parser); emit(parser, event, data); } function closeValue(parser, event) { parser.textNode = textopts(parser.opt, parser.textNode); if (parser.textNode) { emit(parser, (event ? event : "onvalue"), parser.textNode); } parser.textNode = ""; } function closeNumber(parser) { if (parser.numberNode) emit(parser, "onvalue", parseFloat(parser.numberNode)); parser.numberNode = ""; } function textopts (opt, text) { if (opt.trim) text = text.trim(); if (opt.normalize) text = text.replace(/\s+/g, " "); return text; } function error (parser, er) { closeValue(parser); er += "\nLine: "+parser.line+ "\nColumn: "+parser.column+ "\nChar: "+parser.c; er = new Error(er); parser.error = er; emit(parser, "onerror", er); return parser; } function end(parser) { if (parser.state !== S.VALUE || parser.depth !== 0) error(parser, "Unexpected end"); closeValue(parser); parser.c = ""; parser.closed = true; emit(parser, "onend"); CParser.call(parser, parser.opt); return parser; } function write (chunk) { var parser = this; if (this.error) throw this.error; if (parser.closed) return error(parser, "Cannot write after close. Assign an onready handler."); if (chunk === null) return end(parser); var i = 0, c = chunk[0], p = parser.p; if (clarinet.DEBUG) console.log('write -> [' + chunk + ']'); while (c) { p = c; parser.c = c = chunk.charAt(i++); // if chunk doesnt have next, like streaming char by char // this way we need to check if previous is really previous // if not we need to reset to what the parser says is the previous // from buffer if(p !== c ) parser.p = p; else p = parser.p; if(!c) break; if (clarinet.DEBUG) console.log(i,c,clarinet.STATE[parser.state]); parser.position ++; if (c === "\n") { parser.line ++; parser.column = 0; } else parser.column ++; switch (parser.state) { case S.BEGIN: if (c === "{") parser.state = S.OPEN_OBJECT; else if (c === "[") parser.state = S.OPEN_ARRAY; else if (c !== '\r' && c !== '\n' && c !== ' ' && c !== '\t') error(parser, "Non-whitespace before {[."); continue; case S.OPEN_KEY: case S.OPEN_OBJECT: if (c === '\r' || c === '\n' || c === ' ' || c === '\t') continue; if(parser.state === S.OPEN_KEY) parser.stack.push(S.CLOSE_KEY); else { if(c === '}') { emit(parser, 'onopenobject'); this.depth++; emit(parser, 'oncloseobject'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; continue; } else parser.stack.push(S.CLOSE_OBJECT); } if(c === '"') parser.state = S.STRING; else error(parser, "Malformed object key should start with \""); continue; case S.CLOSE_KEY: case S.CLOSE_OBJECT: if (c === '\r' || c === '\n' || c === ' ' || c === '\t') continue; var event = (parser.state === S.CLOSE_KEY) ? 'key' : 'object'; if(c===':') { if(parser.state === S.CLOSE_OBJECT) { parser.stack.push(S.CLOSE_OBJECT); closeValue(parser, 'onopenobject'); this.depth++; } else closeValue(parser, 'onkey'); parser.state = S.VALUE; } else if (c==='}') { emitNode(parser, 'oncloseobject'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; } else if(c===',') { if(parser.state === S.CLOSE_OBJECT) parser.stack.push(S.CLOSE_OBJECT); closeValue(parser); parser.state = S.OPEN_KEY; } else error(parser, 'Bad object'); continue; case S.OPEN_ARRAY: // after an array there always a value case S.VALUE: if (c === '\r' || c === '\n' || c === ' ' || c === '\t') continue; if(parser.state===S.OPEN_ARRAY) { emit(parser, 'onopenarray'); this.depth++; parser.state = S.VALUE; if(c === ']') { emit(parser, 'onclosearray'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; continue; } else { parser.stack.push(S.CLOSE_ARRAY); } } if(c === '"') parser.state = S.STRING; else if(c === '{') parser.state = S.OPEN_OBJECT; else if(c === '[') parser.state = S.OPEN_ARRAY; else if(c === 't') parser.state = S.TRUE; else if(c === 'f') parser.state = S.FALSE; else if(c === 'n') parser.state = S.NULL; else if(c === '-') { // keep and continue parser.numberNode += c; } else if(c==='0') { parser.numberNode += c; parser.state = S.NUMBER_DIGIT; } else if('123456789'.indexOf(c) !== -1) { parser.numberNode += c; parser.state = S.NUMBER_DIGIT; } else error(parser, "Bad value"); continue; case S.CLOSE_ARRAY: if(c===',') { parser.stack.push(S.CLOSE_ARRAY); closeValue(parser, 'onvalue'); parser.state = S.VALUE; } else if (c===']') { emitNode(parser, 'onclosearray'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; } else if (c === '\r' || c === '\n' || c === ' ' || c === '\t') continue; else error(parser, 'Bad array'); continue; case S.STRING: // thanks thejh, this is an about 50% performance improvement. var starti = i-1 , slashed = parser.slashed , unicodeI = parser.unicodeI ; STRING_BIGLOOP: while (true) { if (clarinet.DEBUG) console.log(i,c,clarinet.STATE[parser.state] ,slashed); // zero means "no unicode active". 1-4 mean "parse some more". end after 4. while (unicodeI > 0) { parser.unicodeS += c; c = chunk.charAt(i++); if (unicodeI === 4) { // TODO this might be slow? well, probably not used too often anyway parser.textNode += String.fromCharCode(parseInt(parser.unicodeS, 16)); unicodeI = 0; starti = i-1; } else { unicodeI++; } // we can just break here: no stuff we skipped that still has to be sliced out or so if (!c) break STRING_BIGLOOP; } if (c === '"' && !slashed) { parser.state = parser.stack.pop() || S.VALUE; parser.textNode += chunk.substring(starti, i-1); if(!parser.textNode) { emit(parser, "onvalue", ""); } break; } if (c === '\\' && !slashed) { slashed = true; parser.textNode += chunk.substring(starti, i-1); c = chunk.charAt(i++); if (!c) break; } if (slashed) { slashed = false; if (c === 'n') { parser.textNode += '\n'; } else if (c === 'r') { parser.textNode += '\r'; } else if (c === 't') { parser.textNode += '\t'; } else if (c === 'f') { parser.textNode += '\f'; } else if (c === 'b') { parser.textNode += '\b'; } else if (c === 'u') { // \uxxxx. meh! unicodeI = 1; parser.unicodeS = ''; } else { parser.textNode += c; } c = chunk.charAt(i++); starti = i-1; if (!c) break; else continue; } stringTokenPattern.lastIndex = i; var reResult = stringTokenPattern.exec(chunk); if (reResult === null) { i = chunk.length+1; parser.textNode += chunk.substring(starti, i-1); break; } i = reResult.index+1; c = chunk.charAt(reResult.index); if (!c) { parser.textNode += chunk.substring(starti, i-1); break; } } parser.slashed = slashed; parser.unicodeI = unicodeI; continue; case S.TRUE: if (c==='') continue; // strange buffers if (c==='r') parser.state = S.TRUE2; else error(parser, 'Invalid true started with t'+ c); continue; case S.TRUE2: if (c==='') continue; if (c==='u') parser.state = S.TRUE3; else error(parser, 'Invalid true started with tr'+ c); continue; case S.TRUE3: if (c==='') continue; if(c==='e') { emit(parser, "onvalue", true); parser.state = parser.stack.pop() || S.VALUE; } else error(parser, 'Invalid true started with tru'+ c); continue; case S.FALSE: if (c==='') continue; if (c==='a') parser.state = S.FALSE2; else error(parser, 'Invalid false started with f'+ c); continue; case S.FALSE2: if (c==='') continue; if (c==='l') parser.state = S.FALSE3; else error(parser, 'Invalid false started with fa'+ c); continue; case S.FALSE3: if (c==='') continue; if (c==='s') parser.state = S.FALSE4; else error(parser, 'Invalid false started with fal'+ c); continue; case S.FALSE4: if (c==='') continue; if (c==='e') { emit(parser, "onvalue", false); parser.state = parser.stack.pop() || S.VALUE; } else error(parser, 'Invalid false started with fals'+ c); continue; case S.NULL: if (c==='') continue; if (c==='u') parser.state = S.NULL2; else error(parser, 'Invalid null started with n'+ c); continue; case S.NULL2: if (c==='') continue; if (c==='l') parser.state = S.NULL3; else error(parser, 'Invalid null started with nu'+ c); continue; case S.NULL3: if (c==='') continue; if(c==='l') { emit(parser, "onvalue", null); parser.state = parser.stack.pop() || S.VALUE; } else error(parser, 'Invalid null started with nul'+ c); continue; case S.NUMBER_DECIMAL_POINT: if(c==='.') { parser.numberNode += c; parser.state = S.NUMBER_DIGIT; } else error(parser, 'Leading zero not followed by .'); continue; case S.NUMBER_DIGIT: if('0123456789'.indexOf(c) !== -1) parser.numberNode += c; else if (c==='.') { if(parser.numberNode.indexOf('.')!==-1) error(parser, 'Invalid number has two dots'); parser.numberNode += c; } else if (c==='e' || c==='E') { if(parser.numberNode.indexOf('e')!==-1 || parser.numberNode.indexOf('E')!==-1 ) error(parser, 'Invalid number has two exponential'); parser.numberNode += c; } else if (c==="+" || c==="-") { if(!(p==='e' || p==='E')) error(parser, 'Invalid symbol in number'); parser.numberNode += c; } else { closeNumber(parser); i--; // go back one parser.state = parser.stack.pop() || S.VALUE; } continue; default: error(parser, "Unknown state: " + parser.state); } } if (parser.position >= parser.bufferCheckPosition) checkBufferLength(parser); return parser; } })(typeof exports === "undefined" ? clarinet = {} : exports); node-clarinet-0.9.1+dfsg/package.json000066400000000000000000000023271241330313100174450ustar00rootroot00000000000000{ "name": "clarinet", "description": "SAX based evented streaming JSON parser in JavaScript (browser and node)", "author": "Nuno Job (http://nunojob.com/)", "contributors": [ "Jann Horn (https://github.com/thejh)", "Justin Makeig (http://www.audiblepop.com)", "Roly Fentanes (http://about.me/roly)", "John Lancaster (http://jlank.com)" ], "version": "0.9.1", "main": "./clarinet.js", "homepage": "https://github.com/dscape/clarinet", "repository": { "type": "git", "url": "http://github.com/dscape/clarinet.git" }, "bugs": { "url": "http://github.com/dscape/clarinet/issues" }, "keywords": [ "sax", "json", "parser", "stream", "streaming", "event", "events", "emitter", "async", "streamer", "browser" ], "devDependencies": { "mocha": "1.3.x", "should": "1.0.x", "underscore": "1.2.3" }, "scripts": { "test": "./node_modules/mocha/bin/mocha -r should -t 10000 -s 2000 test/clarinet.js test/npm.js" }, "engines": { "node": ">=0.3.6", "firefox": ">=0.8.0", "chrome": ">=16.0.912" }, "directories": { "test": "test" }, "license": "BSD" }