/* Modifications Copyright (c) 2014 IOnU Security Inc. All rights reserved Created June 2014 by Kendrick Webster based on JSON.parseMore on GitHub (https://github.com/Canop/JSON.parseMore) which is based on JSON-js on GitHub (https://github.com/douglascrockford/JSON-js) which is public domain code written by Douglas Crockford. Comments at the top of JSON.parseMore (where license text should be): // Adapted from Crockford's JSON.parse (see https://github.com/douglascrockford/JSON-js) // This version adds support for NaN, -Infinity and Infinity. */ /* K2Proxy/json.js - json parser that handles comments and provides better error contex than the built-in JSON.parse(). */ "use strict"; function trace(m) { // comment or un-comment as needed for debugging: console.log(m); } function trace_info(m) { // comment or un-comment as needed for debugging: console.log(m); } (function(){ var at, // The index of the current character ch, // The current character line = 1, column = 0, escapee = { '"': '"', '\\': '\\', '/': '/', b: '\b', f: '\f', n: '\n', r: '\r', t: '\t' }, text, error = function (m) { throw { name: 'SyntaxError', message: m, line: line, column: column }; }, next = function (c) { column++; return ch = text.charAt(at++); }, prev = function (n) { ++n; // for the ++ in next(), so prev(0) stays put and prev(1) goes back 1 char column -= n; at -= n; return next(); }, check = function (c) { if (c !== ch) { error("Expected '" + c + "' instead of '" + ch + "'"); } ch = text.charAt(at++); }, number = function () { var string = ''; if (ch === '-') { string = '-'; check('-'); } if (ch === 'I') { check('I'); check('n'); check('f'); check('i'); check('n'); check('i'); check('t'); check('y'); return -Infinity; } while (ch >= '0' && ch <= '9') { string += ch; next(); } if (ch === '.') { string += '.'; while (next() && ch >= '0' && ch <= '9') { string += ch; } } if (ch === 'e' || ch === 'E') { string += ch; next(); if (ch === '-' || ch === '+') { string += ch; next(); } while (ch >= '0' && ch <= '9') { string += ch; next(); } } return +string; }, string = function () { var hex, i, string = '', uffff; if (ch === '"') { while (next()) { if (ch === '"') { next(); return string; } if (ch === '\\') { next(); if (ch === 'u') { uffff = 0; for (i = 0; i < 4; i ++) { hex = parseInt(next(), 16); if (!isFinite(hex)) { break; } uffff = uffff * 16 + hex; } string += String.fromCharCode(uffff); } else if (escapee[ch]) { string += escapee[ch]; } else { break; } } else { string += ch; } } } error("Bad string"); }, white = function () { // Skip whitespace and comments, count lines var s = 0; while (ch) { switch (s) { case 0: // idle if (ch === '/') { s = 1; } else if (ch > ' ') { return; } break; case 1: // '/' if (ch === '/') { s = 2; } else if (ch === '*') { s = 3; } else { prev(1); return; } break; case 2: // '//' if ((ch === '\r') || (ch === '\n')) { s = 0; } break; case 3: // '/*' if (ch === '*') { s = 4; } break; case 4: // '/* ... *' if (ch === '/') { s = 0; } else if (ch !== '*') { s = 3; } break; } if (ch === '\n') { column = 0; line++; } next(); } }, word = function () { switch (ch) { case 't': check('t'); check('r'); check('u'); check('e'); return true; case 'f': check('f'); check('a'); check('l'); check('s'); check('e'); return false; case 'n': check('n'); check('u'); check('l'); check('l'); return null; case 'N': check('N'); check('a'); check('N'); return NaN; case 'I': check('I'); check('n'); check('f'); check('i'); check('n'); check('i'); check('t'); check('y'); return Infinity; } error("Unexpected '" + ch + "'"); }, array = function () { var array = []; if (ch === '[') { check('['); white(); if (ch === ']') { check(']'); return array; // empty array } while (ch) { array.push(value()); white(); if (ch === ']') { check(']'); return array; } check(','); white(); } } error("Bad array"); }, object = function () { var key, object = {}; if (ch === '{') { check('{'); white(); if (ch === '}') { check('}'); return object; // empty object } while (ch) { key = string(); white(); check(':'); if (Object.hasOwnProperty.call(object, key)) { error('Duplicate key "' + key + '"'); } object[key] = value(); white(); if (ch === '}') { check('}'); return object; } check(','); white(); } } error("Bad object"); }; var value = function () { white(); switch (ch) { case '{': return object(); case '[': return array(); case '"': return string(); case '-': return number(); default: return ch >= '0' && ch <= '9' ? number() : word(); } }; JSON.parseMore = function(source, reviver){ var result; text = source; at = 0; ch = ' '; result = value(); white(); if (ch) { error("Syntax error"); } return typeof reviver === 'function' ? (function walk(holder, key) { var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); }({'': result}, '')) : result; } })();