@qubit-ltd/json 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +219 -0
- package/README.zh_CN.md +194 -0
- package/dist/json.cjs +623 -0
- package/dist/json.cjs.map +1 -0
- package/dist/json.min.cjs +1 -0
- package/dist/json.min.cjs.map +1 -0
- package/dist/json.min.mjs +1 -0
- package/dist/json.min.mjs.map +1 -0
- package/dist/json.mjs +610 -0
- package/dist/json.mjs.map +1 -0
- package/doc/api/LosslessNumber.html +610 -0
- package/doc/api/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-Bold-webfont.svg +1838 -0
- package/doc/api/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/doc/api/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-BoldItalic-webfont.svg +1838 -0
- package/doc/api/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/doc/api/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-Italic-webfont.svg +1838 -0
- package/doc/api/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/doc/api/fonts/OpenSans-Light-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-Light-webfont.svg +1839 -0
- package/doc/api/fonts/OpenSans-Light-webfont.woff +0 -0
- package/doc/api/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-LightItalic-webfont.svg +1843 -0
- package/doc/api/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/doc/api/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-Regular-webfont.svg +1839 -0
- package/doc/api/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/doc/api/fonts/OpenSans-Semibold-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-Semibold-webfont.svg +1838 -0
- package/doc/api/fonts/OpenSans-Semibold-webfont.ttf +0 -0
- package/doc/api/fonts/OpenSans-Semibold-webfont.woff +0 -0
- package/doc/api/fonts/OpenSans-SemiboldItalic-webfont.eot +0 -0
- package/doc/api/fonts/OpenSans-SemiboldItalic-webfont.svg +1838 -0
- package/doc/api/fonts/OpenSans-SemiboldItalic-webfont.ttf +0 -0
- package/doc/api/fonts/OpenSans-SemiboldItalic-webfont.woff +0 -0
- package/doc/api/global.html +1274 -0
- package/doc/api/index.html +236 -0
- package/doc/api/scripts/linenumber.js +34 -0
- package/doc/api/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/doc/api/scripts/prettify/lang-css.js +2 -0
- package/doc/api/scripts/prettify/prettify.js +28 -0
- package/doc/api/styles/jsdoc-default.css +699 -0
- package/doc/api/styles/prettify-jsdoc.css +120 -0
- package/doc/api/styles/prettify-tomorrow.css +141 -0
- package/doc/json.min.visualization.html +4949 -0
- package/doc/json.visualization.html +4949 -0
- package/package.json +87 -0
package/dist/json.mjs
ADDED
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
|
|
2
|
+
import _createClass from '@babel/runtime/helpers/createClass';
|
|
3
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
4
|
+
|
|
5
|
+
var T$1=Object.defineProperty;var C$1=(t,a)=>T$1(t,"name",{value:a,configurable:!0});/**
|
|
6
|
+
* https://github.com/jawj/json-custom-numbers
|
|
7
|
+
* @copyright Copyright (c) 2023 George MacKerron
|
|
8
|
+
* @license MIT
|
|
9
|
+
*
|
|
10
|
+
* This file implements a non-recursive JSON parser that's intended to
|
|
11
|
+
* precisely match native `JSON.parse` behaviour but also allow for custom
|
|
12
|
+
* number parsing.
|
|
13
|
+
*/const v=/[^"\\\u0000-\u001f]*/y,D$1=/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][-+]?[0-9]+)?|true|false|null/y,
|
|
14
|
+
J=/[ \n\t\r]*$/y,X=/^.{0,32}\n[ \t]/,h=/[ \n\t\r]*/y,j=`........................\
|
|
15
|
+
.........."............./.............................................\\......\b..\
|
|
16
|
+
..\f........
|
|
17
|
+
....\r.. `.split("."),x$1=C$1(()=>new Uint32Array(103),"hlArr"),k=x$1(),m=x$1(),w=x$1(),$=x$1();
|
|
18
|
+
let i=0;for(;i<48;i++)k[i]=m[i]=w[i]=$[i]=65536;for(;i<58;i++)k[i]=(m[i]=(w[i]=($[i]=
|
|
19
|
+
i-48)<<4)<<4)<<4;for(;i<65;i++)k[i]=m[i]=w[i]=$[i]=65536;for(;i<71;i++)k[i]=(m[i]=
|
|
20
|
+
(w[i]=($[i]=i-55)<<4)<<4)<<4;for(;i<97;i++)k[i]=m[i]=w[i]=$[i]=65536;for(;i<103;i++)
|
|
21
|
+
k[i]=(m[i]=(w[i]=($[i]=i-87)<<4)<<4)<<4;function O(t,a=""){if(!(t>=0))return "end\
|
|
22
|
+
of JSON input";if(t>31&&t<127)return `'${a}${String.fromCharCode(t)}'`;if(t===10)
|
|
23
|
+
return "\\n";if(t===9)return "\\t";const p=t.toString(16),y="0000".slice(p.length)+
|
|
24
|
+
p;return (t>31?`'${a}${String.fromCharCode(t)}' or `:"")+`\\u${y}`}C$1(O,"chDesc");
|
|
25
|
+
function R(t,a){const p=Object.keys(a),y=p.length;for(let d=0;d<y;d++){const n=p[d],
|
|
26
|
+
e=t.call(a,n,a[n]);e!==void 0?a[n]=e:delete a[n];}}C$1(R,"revive");function q$1(t,a,p){
|
|
27
|
+
const y=p===!0?" in array":p===!1?" in object":"",d=t.slice(0,a),n=d.match(/[^\n]{0,69}$/)[0],
|
|
28
|
+
e=n.length<d.length?"..."+n:n,o=a-(d.length-e.length),u=t.slice(a),r=u.match(/[^\n]{0,5}/)[0],
|
|
29
|
+
c=r.length<u.length?r+"...":r,A=e+c,I=" ".repeat(o<1?0:o-1)+"^";return `${y}
|
|
30
|
+
At position ${a} in JSON:
|
|
31
|
+
${A}
|
|
32
|
+
${I}`}C$1(q$1,"errContext");const N={maxDepth:1/0};function K$1(t,a,p,y){var U;typeof t!=
|
|
33
|
+
"string"&&(t=String(t)),typeof a!="function"&&(a=void 0);const d=y===void 0?N.maxDepth:
|
|
34
|
+
typeof y=="number"?y:(U=y.maxDepth)!=null?U:N.maxDepth;let n=0,e,o,u,r,c;function A(l){
|
|
35
|
+
throw new SyntaxError(l+q$1(t,n,u))}C$1(A,"err");function I(){A(`JSON structure too \
|
|
36
|
+
deeply nested (current max depth: ${d})`);}C$1(I,"tooDeep");function b(l){A(`Unexpe\
|
|
37
|
+
cted ${O(e)}, expecting ${l}`);}C$1(b,"expected");function E(){const l=n-1;if(D$1.lastIndex=
|
|
38
|
+
l,D$1.test(t)!==!0&&b("JSON value"),n=D$1.lastIndex,e<102){const g=t.slice(l,n);return p?
|
|
39
|
+
p.call(o,r,g):+g}return e===110?null:e===116}C$1(E,"word");function S(){let l="";e:
|
|
40
|
+
for(;;){v.lastIndex=n,v.test(t);const f=v.lastIndex;for(f>n&&(l+=t.slice(n,f),n=
|
|
41
|
+
f),e=t.charCodeAt(n++);;){switch(e){case 34:return l;case 92:if(e=t.charCodeAt(n++),
|
|
42
|
+
e===117){const s=k[t.charCodeAt(n++)]+m[t.charCodeAt(n++)]+w[t.charCodeAt(n++)]+
|
|
43
|
+
$[t.charCodeAt(n++)];if(s<65536){l+=String.fromCharCode(s);break}A("Invalid \\uXX\
|
|
44
|
+
XX escape in string");}const g=j[e];if(g!==""&&g!==void 0){l+=g;break}A(`Invalid \
|
|
45
|
+
escape sequence: ${O(e,"\\")} in string`);default:e>=0||A("Unterminated string"),
|
|
46
|
+
A(`Invalid unescaped ${O(e)} in string`);}if(e=t.charCodeAt(n),e!==92&&e!==34)continue e;
|
|
47
|
+
n++;}}}C$1(S,"string");e:{do e=t.charCodeAt(n++);while(e<=32&&(e===32||e===10||e===
|
|
48
|
+
13||e===9));switch(e){case 123:d===0&&I(),o={},r=void 0,u=!1;break;case 91:d===0&&
|
|
49
|
+
I(),o=[],r=0,u=!0;break;case 34:c=S();break e;default:c=E();break e}const l=d+d-
|
|
50
|
+
2,f=[],g=X.test(t);let s=0;t:for(;;)if(u===!0)for(;;){g===!0&&s>2&&(h.lastIndex=
|
|
51
|
+
n,h.test(t),n=h.lastIndex);do e=t.charCodeAt(n++);while(e<=32&&(e===32||e===10||
|
|
52
|
+
e===13||e===9));if(e===93){if(a!==void 0&&R(a,o),c=o,s===0)break e;if(o=f[--s],r=
|
|
53
|
+
f[--s],u=typeof r=="number",u===!0){o[r++]=c;continue}else {o[r]=c;continue t}}if(r!==
|
|
54
|
+
0){e!==44&&b("',' or ']' after value"),g===!0&&s>2&&(h.lastIndex=n,h.test(t),n=h.
|
|
55
|
+
lastIndex);do e=t.charCodeAt(n++);while(e<=32&&(e===32||e===10||e===13||e===9))}
|
|
56
|
+
switch(e){case 34:o[r++]=S();continue;case 123:s===l&&I(),f[s++]=r,f[s++]=o,o={},
|
|
57
|
+
r=void 0,u=!1;continue t;case 91:s===l&&I(),f[s++]=r,f[s++]=o,o=[],r=0;continue;default:
|
|
58
|
+
o[r++]=E();}}else for(;;){g===!0&&s>2&&(h.lastIndex=n,h.test(t),n=h.lastIndex);do
|
|
59
|
+
e=t.charCodeAt(n++);while(e<=32&&(e===32||e===10||e===13||e===9));if(e===125){if(a!==
|
|
60
|
+
void 0&&R(a,o),c=o,s===0)break e;if(o=f[--s],r=f[--s],u=typeof r=="number",u===!0){
|
|
61
|
+
o[r++]=c;continue t}else {o[r]=c;continue}}if(r!==void 0){e!==44&&b("',' or '}' a\
|
|
62
|
+
fter value"),g===!0&&s>2&&(h.lastIndex=n,h.test(t),n=h.lastIndex);do e=t.charCodeAt(
|
|
63
|
+
n++);while(e<=32&&(e===32||e===10||e===13||e===9))}e!==34&&b("'}' or double-quot\
|
|
64
|
+
ed key"),r=S();do e=t.charCodeAt(n++);while(e<=32&&(e===32||e===10||e===13||e===
|
|
65
|
+
9));e!==58&&b("':' after key");do e=t.charCodeAt(n++);while(e<=32&&(e===32||e===
|
|
66
|
+
10||e===13||e===9));switch(e){case 34:o[r]=S();continue;case 123:s===l&&I(),f[s++]=
|
|
67
|
+
r,f[s++]=o,o={},r=void 0;continue;case 91:s===l&&I(),f[s++]=r,f[s++]=o,o=[],r=0,
|
|
68
|
+
u=!0;continue t;default:o[r]=E();}}}return J.lastIndex=n,J.test(t)===!1&&A("Unexp\
|
|
69
|
+
ected data after end of JSON input"),a!==void 0&&(c={"":c},R(a,c),c=c[""]),c}C$1(K$1,
|
|
70
|
+
"parse");
|
|
71
|
+
|
|
72
|
+
var E=Object.defineProperty;var T=Object.getOwnPropertySymbols;var F=Object.prototype.hasOwnProperty,V=Object.prototype.propertyIsEnumerable;var D=(t,e,i)=>e in t?E(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):
|
|
73
|
+
t[e]=i,u=(t,e)=>{for(var i in e||(e={}))F.call(e,i)&&D(t,i,e[i]);if(T)for(var i of T(
|
|
74
|
+
e))V.call(e,i)&&D(t,i,e[i]);return t};var K=(t,e)=>E(t,"name",{value:e,configurable:!0});/**
|
|
75
|
+
* https://github.com/jawj/json-custom-numbers
|
|
76
|
+
* @copyright Copyright (c) 2023 George MacKerron
|
|
77
|
+
* @license MIT
|
|
78
|
+
*
|
|
79
|
+
* This file implements a non-recursive JSON stringifier that's intended to
|
|
80
|
+
* precisely match native `JSON.stringify` behaviour but also allow for custom
|
|
81
|
+
* stringifying of numbers.
|
|
82
|
+
*/const x=/["\\\u0000-\u001f]/,q=Object.prototype.hasOwnProperty,z={maxDepth:5e4,
|
|
83
|
+
skipToJSON:!1};function C(t,e,i,j,g={}){typeof g=="number"&&(g={maxDepth:g}),g=u(
|
|
84
|
+
u({},z),g);const{maxDepth:J,skipToJSON:L}=g;let O,S;e!==void 0&&(typeof e=="func\
|
|
85
|
+
tion"?O=e:Array.isArray(e)&&(S=e.map(l=>String(l)))),i!==void 0&&(i=typeof i=="s\
|
|
86
|
+
tring"?i.slice(0,10):typeof i=="number"?" ".slice(0,i):void 0);const P=J*
|
|
87
|
+
(i===void 0?5:6);let r,s={"":t},d=0,c=[""],h=!1,k=1,f=[],n=0,y="",b=`
|
|
88
|
+
`,o,p=new Set([]);do{if(d===k){p.delete(s),i!==void 0&&(b=f[--n],y+=b),y+=c===void 0?
|
|
89
|
+
"]":"}",k=f[--n],h=f[--n],c=f[--n],d=f[--n],s=f[--n];continue}let l,w;c===void 0?
|
|
90
|
+
(r=String(d),t=s[d]):(r=c[d],t=s[r]);let a=typeof t;if(L===!1&&t&&a==="object"&&
|
|
91
|
+
typeof t.toJSON=="function"&&(t=t.toJSON(r),a=typeof t),O!==void 0&&(t=O.call(s,
|
|
92
|
+
r,t),a=typeof t),j===void 0||(o=j(r,t,a))===void 0)switch(a){case"string":o=x.test(
|
|
93
|
+
t)?JSON.stringify(t):'"'+t+'"';break;case"number":o=isFinite(t)?String(t):"null";
|
|
94
|
+
break;case"boolean":o=t===!0?"true":"false";break;case"object":if(t===null){o="n\
|
|
95
|
+
ull";break}if(Array.isArray(t)){const m=t.length;m===0?o="[]":(o="[",l=void 0,w=
|
|
96
|
+
m);break}const N=S===void 0?Object.keys(t):S.filter(m=>q.call(t,m)),A=N.length;A===
|
|
97
|
+
0?o="{}":(o="{",l=N,w=A);break;case"bigint":throw new TypeError("Do not know how\
|
|
98
|
+
to serialize a BigInt: please provide a custom serializer function");default:o=
|
|
99
|
+
void 0;}if(c===void 0?(d>0&&(y+=","),i!==void 0&&(y+=b),y+=o===void 0?"null":o):o!==
|
|
100
|
+
void 0&&(h?y+=",":h=!0,n>0&&(y+=i===void 0?(x.test(r)?JSON.stringify(r):'"'+r+'"')+
|
|
101
|
+
":":b+(x.test(r)?JSON.stringify(r):'"'+r+'"')+": "),y+=o),d++,w!==void 0){if(f[n++]=
|
|
102
|
+
s,f[n++]=d,f[n++]=c,f[n++]=h,f[n++]=k,i!==void 0&&(f[n++]=b,b+=i),s=t,d=0,c=l,h=
|
|
103
|
+
!1,k=w,n>P)throw new RangeError(`Maximum nesting depth exceeded (current maximum\
|
|
104
|
+
is ${J})`);if(p.has(s))throw new TypeError("Cannot stringify circular structure");
|
|
105
|
+
p.add(s);}}while(n!==0);return y||void 0}K(C,"stringify");
|
|
106
|
+
|
|
107
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
108
|
+
//
|
|
109
|
+
// Copyright (c) 2022 - 2024.
|
|
110
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
111
|
+
//
|
|
112
|
+
// All rights reserved.
|
|
113
|
+
//
|
|
114
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* A regular expression for testing whether a string represents an integer.
|
|
118
|
+
*
|
|
119
|
+
* @type {RegExp}
|
|
120
|
+
* @private
|
|
121
|
+
*/
|
|
122
|
+
var INTEGER_REGEX = /^[+-]?\d+$/;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Test whether a string represents an integer.
|
|
126
|
+
*
|
|
127
|
+
* @param value
|
|
128
|
+
* The string to test.
|
|
129
|
+
* @return {boolean}
|
|
130
|
+
* true if the string contains an integer; false otherwise.
|
|
131
|
+
*/
|
|
132
|
+
function isInteger(value) {
|
|
133
|
+
return INTEGER_REGEX.test(value);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
137
|
+
//
|
|
138
|
+
// Copyright (c) 2022 - 2024.
|
|
139
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
140
|
+
//
|
|
141
|
+
// All rights reserved.
|
|
142
|
+
//
|
|
143
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
144
|
+
|
|
145
|
+
var EXPONENTIAL_PART_REGEX = /[eE][+-]?\d+$/;
|
|
146
|
+
var LEADING_MINUS_AND_ZEROS_REGEX = /^-?(0*)?/;
|
|
147
|
+
var DOT_REGEX = /\./;
|
|
148
|
+
var TRAILING_ZEROS_REGEX = /0+$/;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get the significant digits of a number.
|
|
152
|
+
*
|
|
153
|
+
* For example:
|
|
154
|
+
* - '2.34' returns '234'
|
|
155
|
+
* - '-77' returns '77'
|
|
156
|
+
* - '0.003400' returns '34'
|
|
157
|
+
* - '120.5e+30' returns '1205'
|
|
158
|
+
*
|
|
159
|
+
* @param {string} value
|
|
160
|
+
* The string representation of the number.
|
|
161
|
+
* @return {string}
|
|
162
|
+
* The significant digits of the number.
|
|
163
|
+
* @private
|
|
164
|
+
*/
|
|
165
|
+
function extractSignificantDigits(value) {
|
|
166
|
+
return value.replace(EXPONENTIAL_PART_REGEX, '') // from "-0.250e+30" to "-0.250"
|
|
167
|
+
.replace(DOT_REGEX, '') // from "-0.250" to "-0250"
|
|
168
|
+
.replace(TRAILING_ZEROS_REGEX, '') // from "-0250" to "-025"
|
|
169
|
+
.replace(LEADING_MINUS_AND_ZEROS_REGEX, ''); // from "-025" to "25"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
173
|
+
//
|
|
174
|
+
// Copyright (c) 2022 - 2024.
|
|
175
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
176
|
+
//
|
|
177
|
+
// All rights reserved.
|
|
178
|
+
//
|
|
179
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
180
|
+
var DEFAULT_APPROX = false;
|
|
181
|
+
var DEFAULT_REQUIRED_DIGITS = 14;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Test whether a string can be safely represented with a number without
|
|
185
|
+
* information loss.
|
|
186
|
+
*
|
|
187
|
+
* When the argument `approx` is true, floating point numbers that lose a few
|
|
188
|
+
* digits but are still approximately equal in value are considered safe too.
|
|
189
|
+
* Integer numbers must still be exactly equal.
|
|
190
|
+
*
|
|
191
|
+
* @param {string} value
|
|
192
|
+
* The string to test.
|
|
193
|
+
* @param {object} options
|
|
194
|
+
* The options of the test. It may contain the following properties:
|
|
195
|
+
* - `approx: boolean`: indicates whether to consider approximately equal
|
|
196
|
+
* floating point numbers as safe. Default is `false`.
|
|
197
|
+
* - `requiredDigits: number`: the number of significant digits required for
|
|
198
|
+
* a floating point number to be considered approximately equal. Default
|
|
199
|
+
* is `14`.
|
|
200
|
+
* @return {boolean}
|
|
201
|
+
* true if the string can be safely represented with a number; false
|
|
202
|
+
* otherwise.
|
|
203
|
+
*/
|
|
204
|
+
function isSafeNumber(value) {
|
|
205
|
+
var _options$approx;
|
|
206
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
|
|
207
|
+
var num = parseFloat(value);
|
|
208
|
+
var str = String(num);
|
|
209
|
+
if (value === str) {
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
var v = extractSignificantDigits(value);
|
|
213
|
+
var s = extractSignificantDigits(str);
|
|
214
|
+
if (v === s) {
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
var approx = (_options$approx = options === null || options === void 0 ? void 0 : options.approx) !== null && _options$approx !== void 0 ? _options$approx : DEFAULT_APPROX;
|
|
218
|
+
if (approx === true) {
|
|
219
|
+
var _options$requiredDigi;
|
|
220
|
+
// A value is approximately equal when:
|
|
221
|
+
// 1. it is a floating point number, not an integer
|
|
222
|
+
// 2. it has at least requiredDigits digits
|
|
223
|
+
// 3. the first requiredDigits digits are equal
|
|
224
|
+
var requiredDigits = (_options$requiredDigi = options === null || options === void 0 ? void 0 : options.requiredDigits) !== null && _options$requiredDigi !== void 0 ? _options$requiredDigi : DEFAULT_REQUIRED_DIGITS;
|
|
225
|
+
if (!isInteger(value) && s.length >= requiredDigits && v.startsWith(s.substring(0, requiredDigits))) {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
233
|
+
//
|
|
234
|
+
// Copyright (c) 2022 - 2024.
|
|
235
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
236
|
+
//
|
|
237
|
+
// All rights reserved.
|
|
238
|
+
//
|
|
239
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* A regular expression for testing whether a string represents a number.
|
|
243
|
+
*
|
|
244
|
+
* @type {RegExp}
|
|
245
|
+
* @see http://stackoverflow.com/questions/13340717/json-numbers-regular-expression
|
|
246
|
+
* @private
|
|
247
|
+
*/
|
|
248
|
+
var NUMBER_REGEX = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Test whether a string represents a number
|
|
252
|
+
*
|
|
253
|
+
* @param {string} value
|
|
254
|
+
* The string to test.
|
|
255
|
+
* @return {boolean}
|
|
256
|
+
* true if the string contains a number; false otherwise.
|
|
257
|
+
*/
|
|
258
|
+
function isNumber(value) {
|
|
259
|
+
return NUMBER_REGEX.test(value);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
263
|
+
//
|
|
264
|
+
// Copyright (c) 2022 - 2024.
|
|
265
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
266
|
+
//
|
|
267
|
+
// All rights reserved.
|
|
268
|
+
//
|
|
269
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* When the provided value is an unsafe number, describe what the reason is
|
|
273
|
+
* - `'overflow'`
|
|
274
|
+
* - `'underflow'`
|
|
275
|
+
* - `'truncate_integer'`
|
|
276
|
+
* - `'truncate_float'`
|
|
277
|
+
* - `'none'` (when the value is safe)
|
|
278
|
+
*
|
|
279
|
+
* @param {string} value
|
|
280
|
+
* The string represents a number to test.
|
|
281
|
+
* @return {string}
|
|
282
|
+
* The reason why the value is unsafe. Returns `'none'` when the value is safe.
|
|
283
|
+
*/
|
|
284
|
+
function getUnsafeReason(value) {
|
|
285
|
+
var num = parseFloat(value);
|
|
286
|
+
var str = String(num);
|
|
287
|
+
if (value === str) {
|
|
288
|
+
return 'none';
|
|
289
|
+
}
|
|
290
|
+
var v = extractSignificantDigits(value);
|
|
291
|
+
var s = extractSignificantDigits(str);
|
|
292
|
+
if (v === s) {
|
|
293
|
+
return 'none';
|
|
294
|
+
}
|
|
295
|
+
if (isInteger(value)) {
|
|
296
|
+
return 'truncate_integer';
|
|
297
|
+
}
|
|
298
|
+
if (!Number.isFinite(num)) {
|
|
299
|
+
return 'overflow';
|
|
300
|
+
}
|
|
301
|
+
if (num === 0) {
|
|
302
|
+
return 'underflow';
|
|
303
|
+
}
|
|
304
|
+
return 'truncate_float';
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* The class of lossless numbers, which stores its numeric value as string.
|
|
309
|
+
*/
|
|
310
|
+
var LosslessNumber = /*#__PURE__*/function () {
|
|
311
|
+
/**
|
|
312
|
+
* Constructs a new instance of `LosslessNumber`.
|
|
313
|
+
*
|
|
314
|
+
* @param {string} value
|
|
315
|
+
* The string representation of the number.
|
|
316
|
+
*/
|
|
317
|
+
function LosslessNumber(value) {
|
|
318
|
+
_classCallCheck(this, LosslessNumber);
|
|
319
|
+
/**
|
|
320
|
+
* The string representation of the number.
|
|
321
|
+
*
|
|
322
|
+
* @type {string}
|
|
323
|
+
*/
|
|
324
|
+
_defineProperty(this, "value", '');
|
|
325
|
+
/**
|
|
326
|
+
* Whether the value is a lossless number.
|
|
327
|
+
*
|
|
328
|
+
* @type {boolean}
|
|
329
|
+
*/
|
|
330
|
+
_defineProperty(this, "isLosslessNumber", true);
|
|
331
|
+
if (!isNumber(value)) {
|
|
332
|
+
throw new Error("Invalid number (value: \"".concat(value, "\")"));
|
|
333
|
+
}
|
|
334
|
+
this.value = value;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Get the value of the LosslessNumber as number or bigint.
|
|
339
|
+
*
|
|
340
|
+
* - a number is returned for safe numbers and decimal values that only lose
|
|
341
|
+
* some insignificant digits;
|
|
342
|
+
* - a bigint is returned for big integer numbers;
|
|
343
|
+
* - an Error is thrown for values that will overflow or underflow;
|
|
344
|
+
*
|
|
345
|
+
* Note that you can implement your own strategy for conversion by just
|
|
346
|
+
* getting the value as string via `.toString()`, and using util functions
|
|
347
|
+
* like `isInteger`, `isSafeNumber`, `getUnsafeReason`, and `toSafeNumberOrThrow`
|
|
348
|
+
* to convert it to a numeric value.
|
|
349
|
+
*
|
|
350
|
+
* @return {number|bigint}
|
|
351
|
+
* the numeric value of the LosslessNumber, as number or bigint.
|
|
352
|
+
*/
|
|
353
|
+
return _createClass(LosslessNumber, [{
|
|
354
|
+
key: "valueOf",
|
|
355
|
+
value: function valueOf() {
|
|
356
|
+
var unsafeReason = getUnsafeReason(this.value);
|
|
357
|
+
switch (unsafeReason) {
|
|
358
|
+
case 'none':
|
|
359
|
+
return parseFloat(this.value);
|
|
360
|
+
case 'truncate_float':
|
|
361
|
+
return parseFloat(this.value);
|
|
362
|
+
case 'truncate_integer':
|
|
363
|
+
return BigInt(this.value);
|
|
364
|
+
case 'overflow':
|
|
365
|
+
case 'underflow':
|
|
366
|
+
throw new Error('Cannot safely CONVERT TO NUMBER: ' + "the value '".concat(this.value, "' would ").concat(unsafeReason, " ") + "and become ".concat(parseFloat(this.value)));
|
|
367
|
+
default:
|
|
368
|
+
throw new Error('Unknown unsafe reason');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get the value of this `LosslessNumber` as string.
|
|
374
|
+
*
|
|
375
|
+
* @return {string}
|
|
376
|
+
* the string representation of this `LosslessNumber`.
|
|
377
|
+
*/
|
|
378
|
+
}, {
|
|
379
|
+
key: "toString",
|
|
380
|
+
value: function toString() {
|
|
381
|
+
return this.value;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Note: we do NOT implement a .toJSON() method, and you should not implement
|
|
385
|
+
// or use that, it cannot safely turn the numeric value in the string into
|
|
386
|
+
// stringified JSON since it has to be parsed into a number first.
|
|
387
|
+
}]);
|
|
388
|
+
}();
|
|
389
|
+
|
|
390
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
391
|
+
//
|
|
392
|
+
// Copyright (c) 2022 - 2024.
|
|
393
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
394
|
+
//
|
|
395
|
+
// All rights reserved.
|
|
396
|
+
//
|
|
397
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* A custom function to parse a number from a string, which supports lossless
|
|
401
|
+
* number parsing.
|
|
402
|
+
*
|
|
403
|
+
* @param {string} key
|
|
404
|
+
* The key of the property.
|
|
405
|
+
* @param {string} value
|
|
406
|
+
* The value of the property.
|
|
407
|
+
* @return {any}
|
|
408
|
+
* The parsed value.
|
|
409
|
+
* @private
|
|
410
|
+
*/
|
|
411
|
+
function parseNumber(key, value) {
|
|
412
|
+
// if (isBigInt(value)) {
|
|
413
|
+
// return BigInt(value.slice(0, -1));
|
|
414
|
+
// }
|
|
415
|
+
if (isSafeNumber(value, {
|
|
416
|
+
approx: false
|
|
417
|
+
})) {
|
|
418
|
+
return parseFloat(value);
|
|
419
|
+
}
|
|
420
|
+
if (isInteger(value)) {
|
|
421
|
+
return BigInt(value);
|
|
422
|
+
}
|
|
423
|
+
return new LosslessNumber(value);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
427
|
+
//
|
|
428
|
+
// Copyright (c) 2022 - 2024.
|
|
429
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
430
|
+
//
|
|
431
|
+
// All rights reserved.
|
|
432
|
+
//
|
|
433
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Formats a number value.
|
|
437
|
+
*
|
|
438
|
+
* @param {string} key
|
|
439
|
+
* The key of the property.
|
|
440
|
+
* @param {string} value
|
|
441
|
+
* The value of the property.
|
|
442
|
+
* @param {string} type
|
|
443
|
+
* The type of the value.
|
|
444
|
+
* @return {undefined|string}
|
|
445
|
+
* The formatted value. If the value is not a number, then return undefined.
|
|
446
|
+
* @private
|
|
447
|
+
*/
|
|
448
|
+
function formatNumber(key, value, type) {
|
|
449
|
+
switch (type) {
|
|
450
|
+
case 'bigint':
|
|
451
|
+
return value.toString();
|
|
452
|
+
case 'object':
|
|
453
|
+
// if (value instanceof Set) {
|
|
454
|
+
// return Array.from(value);
|
|
455
|
+
// }
|
|
456
|
+
// if (value instanceof Map) {
|
|
457
|
+
// return Array.from(value);
|
|
458
|
+
// }
|
|
459
|
+
if (value instanceof LosslessNumber) {
|
|
460
|
+
return value.toString();
|
|
461
|
+
}
|
|
462
|
+
return undefined;
|
|
463
|
+
default:
|
|
464
|
+
return undefined;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
469
|
+
//
|
|
470
|
+
// Copyright (c) 2022 - 2024.
|
|
471
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
472
|
+
//
|
|
473
|
+
// All rights reserved.
|
|
474
|
+
//
|
|
475
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* A JSON replacer which serialize collections as arrays.
|
|
479
|
+
*
|
|
480
|
+
* @param {string} key
|
|
481
|
+
* The key of the property.
|
|
482
|
+
* @param {any} value
|
|
483
|
+
* The value of the property.
|
|
484
|
+
* @param {undefined|null|function} fallbackReplacer
|
|
485
|
+
* The fallback replacer.
|
|
486
|
+
* @return {any}
|
|
487
|
+
* The serialized value.
|
|
488
|
+
* @private
|
|
489
|
+
*/
|
|
490
|
+
function collectionReplacer(key, value, fallbackReplacer) {
|
|
491
|
+
if (value instanceof Set) {
|
|
492
|
+
return Array.from(value);
|
|
493
|
+
}
|
|
494
|
+
if (value instanceof Map) {
|
|
495
|
+
return Array.from(value);
|
|
496
|
+
}
|
|
497
|
+
if (fallbackReplacer) {
|
|
498
|
+
return fallbackReplacer(key, value);
|
|
499
|
+
}
|
|
500
|
+
return value;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
504
|
+
//
|
|
505
|
+
// Copyright (c) 2022 - 2024.
|
|
506
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
507
|
+
//
|
|
508
|
+
// All rights reserved.
|
|
509
|
+
//
|
|
510
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* A customized JSON object which supports lossless number parsing and stringifying.
|
|
514
|
+
*
|
|
515
|
+
* This object provides two methods: `parse` and `stringify`, which are the same as the
|
|
516
|
+
* `JSON.parse` and `JSON.stringify` methods, except that they support lossless number
|
|
517
|
+
* parsing and stringifying.
|
|
518
|
+
*
|
|
519
|
+
* @type {object}
|
|
520
|
+
*/
|
|
521
|
+
var json = {
|
|
522
|
+
parse: function parse(text, reviver) {
|
|
523
|
+
return K$1(text, reviver, parseNumber);
|
|
524
|
+
},
|
|
525
|
+
stringify: function stringify(value, replacer, space) {
|
|
526
|
+
return C(value, function (k, v) {
|
|
527
|
+
return collectionReplacer(k, v, replacer);
|
|
528
|
+
}, space, formatNumber);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
json[Symbol.toStringTag] = 'JSON';
|
|
532
|
+
|
|
533
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
534
|
+
//
|
|
535
|
+
// Copyright (c) 2022 - 2024.
|
|
536
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
537
|
+
//
|
|
538
|
+
// All rights reserved.
|
|
539
|
+
//
|
|
540
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
541
|
+
/**
|
|
542
|
+
* A regular expression for testing whether a string represents a BigInt.
|
|
543
|
+
*
|
|
544
|
+
* @type {RegExp}
|
|
545
|
+
* @private
|
|
546
|
+
*/
|
|
547
|
+
var BIG_INTEGER_REGEX = /^[+-]?\d+n$/;
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Test whether a string represents a BigInt.
|
|
551
|
+
*
|
|
552
|
+
* @param value
|
|
553
|
+
* The string to test.
|
|
554
|
+
* @return {boolean}
|
|
555
|
+
* true if the string contains a BigInt; false otherwise.
|
|
556
|
+
*/
|
|
557
|
+
function isBigInt(value) {
|
|
558
|
+
return BIG_INTEGER_REGEX.test(value);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
562
|
+
//
|
|
563
|
+
// Copyright (c) 2022 - 2024.
|
|
564
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
565
|
+
//
|
|
566
|
+
// All rights reserved.
|
|
567
|
+
//
|
|
568
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Convert a string into a number when it is safe to do so.
|
|
572
|
+
* Throws an error otherwise, explaining the reason.
|
|
573
|
+
*
|
|
574
|
+
* @param {string} value
|
|
575
|
+
* The string to convert into a number.
|
|
576
|
+
* @param {object} options
|
|
577
|
+
* The options for conversion.
|
|
578
|
+
* @return {number}
|
|
579
|
+
* The converted safe number.
|
|
580
|
+
* @throws {Error}
|
|
581
|
+
* When the value is not safe to convert.
|
|
582
|
+
*/
|
|
583
|
+
function toSafeNumberOrThrow(value) {
|
|
584
|
+
var _options$approx;
|
|
585
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
|
|
586
|
+
var number = parseFloat(value);
|
|
587
|
+
var unsafeReason = getUnsafeReason(value);
|
|
588
|
+
if (unsafeReason === 'none') {
|
|
589
|
+
return number;
|
|
590
|
+
}
|
|
591
|
+
var approx = (_options$approx = options === null || options === void 0 ? void 0 : options.approx) !== null && _options$approx !== void 0 ? _options$approx : DEFAULT_APPROX;
|
|
592
|
+
// when approx is true, we allow truncating float values
|
|
593
|
+
if (approx && unsafeReason === 'truncate_float') {
|
|
594
|
+
return number;
|
|
595
|
+
}
|
|
596
|
+
var unsafeReasonText = unsafeReason === null || unsafeReason === void 0 ? void 0 : unsafeReason.replace(/_/, ' ');
|
|
597
|
+
throw new Error('Cannot safely convert to number: ' + "the value '".concat(value, "' would ").concat(unsafeReasonText, " and become ").concat(number));
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
601
|
+
//
|
|
602
|
+
// Copyright (c) 2022 - 2024.
|
|
603
|
+
// Haixing Hu, Qubit Co. Ltd.
|
|
604
|
+
//
|
|
605
|
+
// All rights reserved.
|
|
606
|
+
//
|
|
607
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
608
|
+
|
|
609
|
+
export { json as Json, LosslessNumber, json as default, getUnsafeReason, isBigInt, isInteger, isNumber, isSafeNumber, toSafeNumberOrThrow };
|
|
610
|
+
//# sourceMappingURL=json.mjs.map
|