-var Flatted = (function (Primitive, primitive) {
+'use strict';
+/*! (c) 2020 Andrea Giammarchi */
- /*!
- * ISC License
- *
- * Copyright (c) 2018, Andrea Giammarchi, @WebReflection
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
+const {parse: $parse, stringify: $stringify} = JSON;
+const {keys} = Object;
- var Flatted = {
+const Primitive = String; // it could be Number
+const primitive = 'string'; // it could be 'number'
- parse: function parse(text, reviver) {
- var input = JSON.parse(text, Primitives).map(primitives);
- var value = input[0];
- var $ = reviver || noop;
- var tmp = typeof value === 'object' && value ?
- revive(input, new Set, value, $) :
- value;
- return $.call({'': tmp}, '', tmp);
- },
+const ignore = {};
+const object = 'object';
- stringify: function stringify(value, replacer, space) {
- for (var
- firstRun,
- known = new Map,
- input = [],
- output = [],
- $ = replacer && typeof replacer === typeof input ?
- function (k, v) {
- if (k === '' || -1 < replacer.indexOf(k)) return v;
- } :
- (replacer || noop),
- i = +set(known, input, $.call({'': value}, '', value)),
- replace = function (key, value) {
- if (firstRun) {
- firstRun = !firstRun;
- return value;
- }
- var after = $.call(this, key, value);
- switch (typeof after) {
- case 'object':
- if (after === null) return after;
- case primitive:
- return known.get(after) || set(known, input, after);
- }
- return after;
- };
- i < input.length; i++
- ) {
- firstRun = true;
- output[i] = JSON.stringify(input[i], replace, space);
- }
- return '[' + output.join(',') + ']';
- }
+const noop = (_, value) => value;
- };
+const primitives = value => (
+ value instanceof Primitive ? Primitive(value) : value
+);
- return Flatted;
+const Primitives = (_, value) => (
+ typeof value === primitive ? new Primitive(value) : value
+);
- function noop(key, value) {
- return value;
+const revive = (input, parsed, output, $) => {
+ const lazy = [];
+ for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
+ const k = ke[y];
+ const value = output[k];
+ if (value instanceof Primitive) {
+ const tmp = input[value];
+ if (typeof tmp === object && !parsed.has(tmp)) {
+ parsed.add(tmp);
+ output[k] = ignore;
+ lazy.push({k, a: [input, parsed, tmp, $]});
+ }
+ else
+ output[k] = $.call(output, k, tmp);
+ }
+ else if (output[k] !== ignore)
+ output[k] = $.call(output, k, value);
}
-
- function revive(input, parsed, output, $) {
- return Object.keys(output).reduce(
- function (output, key) {
- var value = output[key];
- if (value instanceof Primitive) {
- var tmp = input[value];
- if (typeof tmp === 'object' && !parsed.has(tmp)) {
- parsed.add(tmp);
- output[key] = $.call(output, key, revive(input, parsed, tmp, $));
- } else {
- output[key] = $.call(output, key, tmp);
- }
- } else
- output[key] = $.call(output, key, value);
- return output;
- },
- output
- );
+ for (let {length} = lazy, i = 0; i < length; i++) {
+ const {k, a} = lazy[i];
+ output[k] = $.call(output, k, revive.apply(null, a));
}
+ return output;
+};
- function set(known, input, value) {
- var index = Primitive(input.push(value) - 1);
- known.set(value, index);
- return index;
- }
+const set = (known, input, value) => {
+ const index = Primitive(input.push(value) - 1);
+ known.set(value, index);
+ return index;
+};
- // the two kinds of primitives
- // 1. the real one
- // 2. the wrapped one
+const parse = (text, reviver) => {
+ const input = $parse(text, Primitives).map(primitives);
+ const value = input[0];
+ const $ = reviver || noop;
+ const tmp = typeof value === object && value ?
+ revive(input, new Set, value, $) :
+ value;
+ return $.call({'': tmp}, '', tmp);
+};
+exports.parse = parse;
- function primitives(value) {
- return value instanceof Primitive ? Primitive(value) : value;
+const stringify = (value, replacer, space) => {
+ const $ = replacer && typeof replacer === object ?
+ (k, v) => (k === '' || -1 < replacer.indexOf(k) ? v : void 0) :
+ (replacer || noop);
+ const known = new Map;
+ const input = [];
+ const output = [];
+ let i = +set(known, input, $.call({'': value}, '', value));
+ let firstRun = !i;
+ while (i < input.length) {
+ firstRun = true;
+ output[i] = $stringify(input[i++], replace, space);
}
-
- function Primitives(key, value) {
- return typeof value === primitive ? new Primitive(value) : value;
+ return '[' + output.join(',') + ']';
+ function replace(key, value) {
+ if (firstRun) {
+ firstRun = !firstRun;
+ return value;
+ }
+ const after = $.call(this, key, value);
+ switch (typeof after) {
+ case object:
+ if (after === null) return after;
+ case primitive:
+ return known.get(after) || set(known, input, after);
+ }
+ return after;
}
+};
+exports.stringify = stringify;
-}(String, 'string'));
-module.exports = Flatted;
+const toJSON = any => $parse(stringify(any));
+exports.toJSON = toJSON;
+const fromJSON = any => parse($stringify(any));
+exports.fromJSON = fromJSON;