You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.4 KiB
113 lines
3.4 KiB
var Flatted = (function (Primitive, primitive) { |
|
|
|
/*! |
|
* 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. |
|
*/ |
|
|
|
var Flatted = { |
|
|
|
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); |
|
}, |
|
|
|
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(',') + ']'; |
|
} |
|
|
|
}; |
|
|
|
return Flatted; |
|
|
|
function noop(key, value) { |
|
return 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 |
|
); |
|
} |
|
|
|
function set(known, input, value) { |
|
var 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 |
|
|
|
function primitives(value) { |
|
return value instanceof Primitive ? Primitive(value) : value; |
|
} |
|
|
|
function Primitives(key, value) { |
|
return typeof value === primitive ? new Primitive(value) : value; |
|
} |
|
|
|
}(String, 'string'));
|
|
|