diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml
index 3ff354d55362c6..d29a0f9be67c97 100644
--- a/.github/workflows/tools.yml
+++ b/.github/workflows/tools.yml
@@ -36,6 +36,7 @@ on:
- ngtcp2
- postject
- root-certificates
+ - simdjson
- simdutf
- undici
- uvwasi
@@ -252,6 +253,14 @@ jobs:
label: crypto, notable-change
run: |
node ./tools/dep_updaters/update-root-certs.mjs -v -f "$GITHUB_ENV"
+ - id: simdjson
+ subsystem: deps
+ label: dependencies
+ run: |
+ ./tools/dep_updaters/update-simdjson.sh > temp-output
+ cat temp-output
+ tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true
+ rm temp-output
- id: simdutf
subsystem: deps
label: dependencies
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f777ea59bfe239..95d5ad1ebd0e05 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,7 +36,8 @@ release.
-21.4.0
+21.5.0
+21.4.0
21.3.0
21.2.0
21.1.0
diff --git a/LICENSE b/LICENSE
index 9cee50463b0ca2..f4395bd0ea1df9 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1285,9 +1285,9 @@ The externally maintained libraries used by Node.js are:
- zlib, located at deps/zlib, is licensed as follows:
"""
zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.13.1, October xxth, 2022
+ version 1.3, August 18th, 2023
- Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -1309,6 +1309,211 @@ The externally maintained libraries used by Node.js are:
jloup@gzip.org madler@alumni.caltech.edu
"""
+- simdjson, located at deps/simdjson, is licensed as follows:
+ """
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2018-2023 The simdjson authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ """
+
- simdutf, located at deps/simdutf, is licensed as follows:
"""
Copyright 2021 The simdutf authors
diff --git a/benchmark/crypto/aes-gcm-throughput.js b/benchmark/crypto/aes-gcm-throughput.js
index 0ac88f6e6ee5ea..cf249c6b6d832a 100644
--- a/benchmark/crypto/aes-gcm-throughput.js
+++ b/benchmark/crypto/aes-gcm-throughput.js
@@ -3,7 +3,7 @@ const common = require('../common.js');
const crypto = require('crypto');
const keylen = { 'aes-128-gcm': 16, 'aes-192-gcm': 24, 'aes-256-gcm': 32 };
const bench = common.createBenchmark(main, {
- n: [500],
+ n: [2500],
cipher: ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'],
len: [1024, 4 * 1024, 16 * 1024, 64 * 1024, 256 * 1024, 1024 * 1024],
});
diff --git a/benchmark/crypto/create-hash.js b/benchmark/crypto/create-hash.js
new file mode 100644
index 00000000000000..119534d5c24f83
--- /dev/null
+++ b/benchmark/crypto/create-hash.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const common = require('../common.js');
+const { createHash } = require('crypto');
+const assert = require('assert');
+
+const bench = common.createBenchmark(main, {
+ n: [1e5],
+});
+
+function main({ n }) {
+ const array = [];
+ for (let i = 0; i < n; ++i) {
+ array.push(null);
+ }
+ bench.start();
+ for (let i = 0; i < n; ++i) {
+ array[i] = createHash('sha1');
+ }
+ bench.end(n);
+ assert.strictEqual(typeof array[n - 1], 'object');
+}
diff --git a/benchmark/crypto/randomBytes.js b/benchmark/crypto/randomBytes.js
index 50ad3f08387566..a47080a017d250 100644
--- a/benchmark/crypto/randomBytes.js
+++ b/benchmark/crypto/randomBytes.js
@@ -3,14 +3,21 @@
const common = require('../common.js');
const { randomBytes } = require('crypto');
+// Add together with imports
+const assert = require('assert');
+
+let _cryptoResult;
+
const bench = common.createBenchmark(main, {
- size: [64, 1024, 8192, 512 * 1024],
- n: [1e3],
+ size: [64, 1024, 8 * 1024, 16 * 1024],
+ n: [1e5],
});
function main({ n, size }) {
bench.start();
for (let i = 0; i < n; ++i)
- randomBytes(size);
+ _cryptoResult = randomBytes(size);
bench.end(n);
+ // Avoid V8 deadcode (elimination)
+ assert.ok(_cryptoResult);
}
diff --git a/benchmark/fs/bench-readvSync.js b/benchmark/fs/bench-readvSync.js
new file mode 100644
index 00000000000000..c163429b5f6212
--- /dev/null
+++ b/benchmark/fs/bench-readvSync.js
@@ -0,0 +1,58 @@
+'use strict';
+
+const common = require('../common');
+const fs = require('fs');
+const assert = require('assert');
+const tmpdir = require('../../test/common/tmpdir');
+tmpdir.refresh();
+
+const exptectedBuff = Buffer.from('Benchmark Data');
+const expectedLength = exptectedBuff.length;
+
+const bufferArr = [Buffer.alloc(expectedLength)];
+
+const filename = tmpdir.resolve('readv_sync.txt');
+fs.writeFileSync(filename, exptectedBuff);
+
+const bench = common.createBenchmark(main, {
+ type: ['valid', 'invalid'],
+ n: [1e5],
+});
+
+function main({ n, type }) {
+ let fd;
+ let result;
+
+ switch (type) {
+ case 'valid':
+ fd = fs.openSync(filename, 'r');
+
+ bench.start();
+ for (let i = 0; i < n; i++) {
+ result = fs.readvSync(fd, bufferArr, 0);
+ }
+
+ bench.end(n);
+ assert.strictEqual(result, expectedLength);
+ fs.closeSync(fd);
+ break;
+ case 'invalid': {
+ fd = 1 << 30;
+ let hasError = false;
+ bench.start();
+ for (let i = 0; i < n; i++) {
+ try {
+ result = fs.readvSync(fd, bufferArr, 0);
+ } catch {
+ hasError = true;
+ }
+ }
+
+ bench.end(n);
+ assert(hasError);
+ break;
+ }
+ default:
+ throw new Error('Invalid type');
+ }
+}
diff --git a/benchmark/perf_hooks/performance-observer.js b/benchmark/perf_hooks/performance-observer.js
index 42a94932860c38..d943c4547e0431 100644
--- a/benchmark/perf_hooks/performance-observer.js
+++ b/benchmark/perf_hooks/performance-observer.js
@@ -13,7 +13,7 @@ function randomFn() {
}
const bench = common.createBenchmark(main, {
- n: [1e5],
+ n: [1e6],
pending: [1, 10],
}, {
options: ['--expose-internals'],
diff --git a/benchmark/perf_hooks/resourcetiming.js b/benchmark/perf_hooks/resourcetiming.js
index 51c4778d20065f..69ee06c92cbd9f 100644
--- a/benchmark/perf_hooks/resourcetiming.js
+++ b/benchmark/perf_hooks/resourcetiming.js
@@ -50,7 +50,7 @@ function createTimingInfo({
}
const bench = common.createBenchmark(main, {
- n: [1e5],
+ n: [1e6],
observe: ['resource'],
});
diff --git a/benchmark/perf_hooks/timerfied.js b/benchmark/perf_hooks/timerfied.js
index 50be0a47fc1b5a..f1cc62637187dd 100644
--- a/benchmark/perf_hooks/timerfied.js
+++ b/benchmark/perf_hooks/timerfied.js
@@ -13,7 +13,7 @@ function randomFn() {
}
const bench = common.createBenchmark(main, {
- n: [1e5],
+ n: [1e6],
observe: ['function'],
});
diff --git a/benchmark/perf_hooks/usertiming.js b/benchmark/perf_hooks/usertiming.js
index 24a53a116785df..92017861d58c4a 100644
--- a/benchmark/perf_hooks/usertiming.js
+++ b/benchmark/perf_hooks/usertiming.js
@@ -8,7 +8,7 @@ const {
} = require('perf_hooks');
const bench = common.createBenchmark(main, {
- n: [1e5],
+ n: [1e6],
observe: ['all', 'measure'],
});
diff --git a/benchmark/util/format.js b/benchmark/util/format.js
index 4078fe5e3da7cd..dfbb6c3372a23b 100644
--- a/benchmark/util/format.js
+++ b/benchmark/util/format.js
@@ -18,7 +18,7 @@ const inputs = {
};
const bench = common.createBenchmark(main, {
- n: [1e5],
+ n: [1e6],
type: Object.keys(inputs),
});
diff --git a/benchmark/util/inspect-array.js b/benchmark/util/inspect-array.js
index 7b2394d80e9cfe..ed40f5c4324ac3 100644
--- a/benchmark/util/inspect-array.js
+++ b/benchmark/util/inspect-array.js
@@ -4,7 +4,7 @@ const common = require('../common');
const util = require('util');
const bench = common.createBenchmark(main, {
- n: [5e2],
+ n: [5e3],
len: [1e2, 1e5],
type: [
'denseArray',
diff --git a/benchmark/util/normalize-encoding.js b/benchmark/util/normalize-encoding.js
index cd65caca4a4056..204ea67c54ce1a 100644
--- a/benchmark/util/normalize-encoding.js
+++ b/benchmark/util/normalize-encoding.js
@@ -21,7 +21,7 @@ const inputs = [
const bench = common.createBenchmark(main, {
input: inputs.concat(Object.keys(groupedInputs)),
- n: [1e5],
+ n: [1e6],
}, {
flags: '--expose-internals',
});
diff --git a/benchmark/util/text-decoder.js b/benchmark/util/text-decoder.js
index f85dd4db008ed8..dd4f02016df077 100644
--- a/benchmark/util/text-decoder.js
+++ b/benchmark/util/text-decoder.js
@@ -6,8 +6,8 @@ const bench = common.createBenchmark(main, {
encoding: ['utf-8', 'latin1', 'iso-8859-3'],
ignoreBOM: [0, 1],
fatal: [0, 1],
- len: [256, 1024 * 16, 1024 * 512],
- n: [1e2],
+ len: [256, 1024 * 16, 1024 * 128],
+ n: [1e3],
type: ['SharedArrayBuffer', 'ArrayBuffer', 'Buffer'],
});
diff --git a/benchmark/util/type-check.js b/benchmark/util/type-check.js
index 2bb956f4ed87ee..269c2a4e9c1374 100644
--- a/benchmark/util/type-check.js
+++ b/benchmark/util/type-check.js
@@ -29,7 +29,7 @@ const bench = common.createBenchmark(main, {
type: Object.keys(args),
version: ['native', 'js'],
argument: ['true', 'false-primitive', 'false-object'],
- n: [1e5],
+ n: [1e6],
}, {
flags: ['--expose-internals', '--no-warnings'],
});
diff --git a/benchmark/websocket/simple.js b/benchmark/websocket/simple.js
new file mode 100644
index 00000000000000..1147602a7b1ea7
--- /dev/null
+++ b/benchmark/websocket/simple.js
@@ -0,0 +1,100 @@
+'use strict';
+
+const common = require('../common.js');
+const crypto = require('crypto');
+const http = require('http');
+const { WebSocket } = require('../../deps/undici/undici');
+
+const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
+
+const configs = {
+ size: [64, 16 * 1024, 128 * 1024, 1024 * 1024],
+ useBinary: ['true', 'false'],
+ roundtrips: [5000, 1000, 100],
+};
+
+const bench = common.createBenchmark(main, configs);
+
+function createFrame(data, opcode) {
+ let infoLength = 2;
+ let payloadLength = data.length;
+
+ if (payloadLength >= 65536) {
+ infoLength += 8;
+ payloadLength = 127;
+ } else if (payloadLength > 125) {
+ infoLength += 2;
+ payloadLength = 126;
+ }
+
+ const info = Buffer.alloc(infoLength);
+
+ info[0] = opcode | 0x80;
+ info[1] = payloadLength;
+
+ if (payloadLength === 126) {
+ info.writeUInt16BE(data.length, 2);
+ } else if (payloadLength === 127) {
+ info[2] = info[3] = 0;
+ info.writeUIntBE(data.length, 4, 6);
+ }
+
+ return Buffer.concat([info, data]);
+}
+
+function main(conf) {
+ const frame = createFrame(Buffer.alloc(conf.size).fill('.'), conf.useBinary === 'true' ? 2 : 1);
+ const server = http.createServer();
+ server.on('upgrade', (req, socket) => {
+ const key = crypto
+ .createHash('sha1')
+ .update(req.headers['sec-websocket-key'] + GUID)
+ .digest('base64');
+
+ let bytesReceived = 0;
+ let roundtrip = 0;
+
+ socket.on('data', function onData(chunk) {
+ bytesReceived += chunk.length;
+
+ if (bytesReceived === frame.length + 4) { // +4 for the mask.
+ // Message completely received.
+ bytesReceived = 0;
+
+ if (++roundtrip === conf.roundtrips) {
+ socket.removeListener('data', onData);
+ socket.resume();
+ socket.end();
+ server.close();
+
+ bench.end(conf.roundtrips);
+ } else {
+ socket.write(frame);
+ }
+ }
+ });
+
+ socket.write(
+ [
+ 'HTTP/1.1 101 Switching Protocols',
+ 'Upgrade: websocket',
+ 'Connection: Upgrade',
+ `Sec-WebSocket-Accept: ${key}`,
+ '\r\n',
+ ].join('\r\n'),
+ );
+
+ socket.write(frame);
+ });
+
+ server.listen(0, () => {
+ const ws = new WebSocket(`ws://localhost:${server.address().port}`);
+ ws.addEventListener('open', () => {
+ bench.start();
+ });
+
+ ws.addEventListener('message', (event) => {
+ ws.send(event.data);
+ });
+ });
+}
diff --git a/common.gypi b/common.gypi
index 28522c9fbf83b4..c6b9fa05b44c96 100644
--- a/common.gypi
+++ b/common.gypi
@@ -36,7 +36,7 @@
# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
- 'v8_embedder_string': '-node.17',
+ 'v8_embedder_string': '-node.18',
##### V8 defaults for Node.js #####
diff --git a/deps/simdjson/LICENSE b/deps/simdjson/LICENSE
new file mode 100644
index 00000000000000..71f65b598d907f
--- /dev/null
+++ b/deps/simdjson/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2018-2023 The simdjson authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/deps/simdjson/simdjson.cpp b/deps/simdjson/simdjson.cpp
new file mode 100644
index 00000000000000..6de55c7222448d
--- /dev/null
+++ b/deps/simdjson/simdjson.cpp
@@ -0,0 +1,43382 @@
+/* auto-generated on 2023-12-01 13:55:28 -0500. Do not edit! */
+/* including simdjson.cpp: */
+/* begin file simdjson.cpp */
+#define SIMDJSON_SRC_SIMDJSON_CPP
+
+/* including base.h: #include */
+/* begin file base.h */
+#ifndef SIMDJSON_SRC_BASE_H
+#define SIMDJSON_SRC_BASE_H
+
+/* including simdjson/base.h: #include */
+/* begin file simdjson/base.h */
+/**
+ * @file Base declarations for all simdjson headers
+ * @private
+ */
+#ifndef SIMDJSON_BASE_H
+#define SIMDJSON_BASE_H
+
+/* including simdjson/common_defs.h: #include "simdjson/common_defs.h" */
+/* begin file simdjson/common_defs.h */
+#ifndef SIMDJSON_COMMON_DEFS_H
+#define SIMDJSON_COMMON_DEFS_H
+
+#include
+/* including simdjson/compiler_check.h: #include "simdjson/compiler_check.h" */
+/* begin file simdjson/compiler_check.h */
+#ifndef SIMDJSON_COMPILER_CHECK_H
+#define SIMDJSON_COMPILER_CHECK_H
+
+#ifndef __cplusplus
+#error simdjson requires a C++ compiler
+#endif
+
+#ifndef SIMDJSON_CPLUSPLUS
+#if defined(_MSVC_LANG) && !defined(__clang__)
+#define SIMDJSON_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
+#else
+#define SIMDJSON_CPLUSPLUS __cplusplus
+#endif
+#endif
+
+// C++ 17
+#if !defined(SIMDJSON_CPLUSPLUS17) && (SIMDJSON_CPLUSPLUS >= 201703L)
+#define SIMDJSON_CPLUSPLUS17 1
+#endif
+
+// C++ 14
+#if !defined(SIMDJSON_CPLUSPLUS14) && (SIMDJSON_CPLUSPLUS >= 201402L)
+#define SIMDJSON_CPLUSPLUS14 1
+#endif
+
+// C++ 11
+#if !defined(SIMDJSON_CPLUSPLUS11) && (SIMDJSON_CPLUSPLUS >= 201103L)
+#define SIMDJSON_CPLUSPLUS11 1
+#endif
+
+#ifndef SIMDJSON_CPLUSPLUS11
+#error simdjson requires a compiler compliant with the C++11 standard
+#endif
+
+#ifndef SIMDJSON_IF_CONSTEXPR
+#if SIMDJSON_CPLUSPLUS17
+#define SIMDJSON_IF_CONSTEXPR if constexpr
+#else
+#define SIMDJSON_IF_CONSTEXPR if
+#endif
+#endif
+
+#endif // SIMDJSON_COMPILER_CHECK_H
+/* end file simdjson/compiler_check.h */
+/* including simdjson/portability.h: #include "simdjson/portability.h" */
+/* begin file simdjson/portability.h */
+#ifndef SIMDJSON_PORTABILITY_H
+#define SIMDJSON_PORTABILITY_H
+
+#include
+#include
+#include
+#include
+#include
+#ifndef _WIN32
+// strcasecmp, strncasecmp
+#include
+#endif
+
+#ifdef _MSC_VER
+#define SIMDJSON_VISUAL_STUDIO 1
+/**
+ * We want to differentiate carefully between
+ * clang under visual studio and regular visual
+ * studio.
+ *
+ * Under clang for Windows, we enable:
+ * * target pragmas so that part and only part of the
+ * code gets compiled for advanced instructions.
+ *
+ */
+#ifdef __clang__
+// clang under visual studio
+#define SIMDJSON_CLANG_VISUAL_STUDIO 1
+#else
+// just regular visual studio (best guess)
+#define SIMDJSON_REGULAR_VISUAL_STUDIO 1
+#endif // __clang__
+#endif // _MSC_VER
+
+#if defined(__x86_64__) || defined(_M_AMD64)
+#define SIMDJSON_IS_X86_64 1
+#elif defined(__aarch64__) || defined(_M_ARM64)
+#define SIMDJSON_IS_ARM64 1
+#elif defined(__riscv) && __riscv_xlen == 64
+#define SIMDJSON_IS_RISCV64 1
+#elif defined(__PPC64__) || defined(_M_PPC64)
+#if defined(__ALTIVEC__)
+#define SIMDJSON_IS_PPC64_VMX 1
+#endif // defined(__ALTIVEC__)
+#else
+#define SIMDJSON_IS_32BITS 1
+
+#if defined(_M_IX86) || defined(__i386__)
+#define SIMDJSON_IS_X86_32BITS 1
+#elif defined(__arm__) || defined(_M_ARM)
+#define SIMDJSON_IS_ARM_32BITS 1
+#elif defined(__PPC__) || defined(_M_PPC)
+#define SIMDJSON_IS_PPC_32BITS 1
+#endif
+
+#endif // defined(__x86_64__) || defined(_M_AMD64)
+#ifndef SIMDJSON_IS_32BITS
+#define SIMDJSON_IS_32BITS 0
+#endif
+
+#if SIMDJSON_IS_32BITS
+#ifndef SIMDJSON_NO_PORTABILITY_WARNING
+// In the future, we should allow programmers
+// to get warning.
+#endif // SIMDJSON_NO_PORTABILITY_WARNING
+#endif // SIMDJSON_IS_32BITS
+
+#define SIMDJSON_CAT_IMPLEMENTATION_(a,...) a ## __VA_ARGS__
+#define SIMDJSON_CAT(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
+
+#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a,...) #a SIMDJSON_STRINGIFY(__VA_ARGS__)
+#define SIMDJSON_STRINGIFY(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
+
+// this is almost standard?
+#undef SIMDJSON_STRINGIFY_IMPLEMENTATION_
+#undef SIMDJSON_STRINGIFY
+#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a) #a
+#define SIMDJSON_STRINGIFY(a) SIMDJSON_STRINGIFY_IMPLEMENTATION_(a)
+
+// Our fast kernels require 64-bit systems.
+//
+// On 32-bit x86, we lack 64-bit popcnt, lzcnt, blsr instructions.
+// Furthermore, the number of SIMD registers is reduced.
+//
+// On 32-bit ARM, we would have smaller registers.
+//
+// The simdjson users should still have the fallback kernel. It is
+// slower, but it should run everywhere.
+
+//
+// Enable valid runtime implementations, and select SIMDJSON_BUILTIN_IMPLEMENTATION
+//
+
+// We are going to use runtime dispatch.
+#if SIMDJSON_IS_X86_64
+#ifdef __clang__
+// clang does not have GCC push pop
+// warning: clang attribute push can't be used within a namespace in clang up
+// til 8.0 so SIMDJSON_TARGET_REGION and SIMDJSON_UNTARGET_REGION must be *outside* of a
+// namespace.
+#define SIMDJSON_TARGET_REGION(T) \
+ _Pragma(SIMDJSON_STRINGIFY( \
+ clang attribute push(__attribute__((target(T))), apply_to = function)))
+#define SIMDJSON_UNTARGET_REGION _Pragma("clang attribute pop")
+#elif defined(__GNUC__)
+// GCC is easier
+#define SIMDJSON_TARGET_REGION(T) \
+ _Pragma("GCC push_options") _Pragma(SIMDJSON_STRINGIFY(GCC target(T)))
+#define SIMDJSON_UNTARGET_REGION _Pragma("GCC pop_options")
+#endif // clang then gcc
+
+#endif // x86
+
+// Default target region macros don't do anything.
+#ifndef SIMDJSON_TARGET_REGION
+#define SIMDJSON_TARGET_REGION(T)
+#define SIMDJSON_UNTARGET_REGION
+#endif
+
+// Is threading enabled?
+#if defined(_REENTRANT) || defined(_MT)
+#ifndef SIMDJSON_THREADS_ENABLED
+#define SIMDJSON_THREADS_ENABLED
+#endif
+#endif
+
+// workaround for large stack sizes under -O0.
+// https://github.com/simdjson/simdjson/issues/691
+#ifdef __APPLE__
+#ifndef __OPTIMIZE__
+// Apple systems have small stack sizes in secondary threads.
+// Lack of compiler optimization may generate high stack usage.
+// Users may want to disable threads for safety, but only when
+// in debug mode which we detect by the fact that the __OPTIMIZE__
+// macro is not defined.
+#undef SIMDJSON_THREADS_ENABLED
+#endif
+#endif
+
+
+#if defined(__clang__)
+#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
+#elif defined(__GNUC__)
+#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
+#else
+#define SIMDJSON_NO_SANITIZE_UNDEFINED
+#endif
+
+
+#if defined(__clang__) || defined(__GNUC__)
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+#define SIMDJSON_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
+# endif // if __has_feature(memory_sanitizer)
+#endif // defined(__has_feature)
+#endif
+// make sure it is defined as 'nothing' if it is unapplicable.
+#ifndef SIMDJSON_NO_SANITIZE_MEMORY
+#define SIMDJSON_NO_SANITIZE_MEMORY
+#endif
+
+#if SIMDJSON_VISUAL_STUDIO
+// This is one case where we do not distinguish between
+// regular visual studio and clang under visual studio.
+// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
+#define simdjson_strcasecmp _stricmp
+#define simdjson_strncasecmp _strnicmp
+#else
+// The strcasecmp, strncasecmp, and strcasestr functions do not work with multibyte strings (e.g. UTF-8).
+// So they are only useful for ASCII in our context.
+// https://www.gnu.org/software/libunistring/manual/libunistring.html#char-_002a-strings
+#define simdjson_strcasecmp strcasecmp
+#define simdjson_strncasecmp strncasecmp
+#endif
+
+#if defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
+// If NDEBUG is set, or __OPTIMIZE__ is set, or we are under MSVC in release mode,
+// then do away with asserts and use __assume.
+#if SIMDJSON_VISUAL_STUDIO
+#define SIMDJSON_UNREACHABLE() __assume(0)
+#define SIMDJSON_ASSUME(COND) __assume(COND)
+#else
+#define SIMDJSON_UNREACHABLE() __builtin_unreachable();
+#define SIMDJSON_ASSUME(COND) do { if (!(COND)) __builtin_unreachable(); } while (0)
+#endif
+
+#else // defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
+// This should only ever be enabled in debug mode.
+#define SIMDJSON_UNREACHABLE() assert(0);
+#define SIMDJSON_ASSUME(COND) assert(COND)
+
+#endif
+
+#endif // SIMDJSON_PORTABILITY_H
+/* end file simdjson/portability.h */
+
+namespace simdjson {
+namespace internal {
+/**
+ * @private
+ * Our own implementation of the C++17 to_chars function.
+ * Defined in src/to_chars
+ */
+char *to_chars(char *first, const char *last, double value);
+/**
+ * @private
+ * A number parsing routine.
+ * Defined in src/from_chars
+ */
+double from_chars(const char *first) noexcept;
+double from_chars(const char *first, const char* end) noexcept;
+}
+
+#ifndef SIMDJSON_EXCEPTIONS
+#if __cpp_exceptions
+#define SIMDJSON_EXCEPTIONS 1
+#else
+#define SIMDJSON_EXCEPTIONS 0
+#endif
+#endif
+
+} // namespace simdjson
+
+#if defined(__GNUC__)
+ // Marks a block with a name so that MCA analysis can see it.
+ #define SIMDJSON_BEGIN_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-BEGIN " #name);
+ #define SIMDJSON_END_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-END " #name);
+ #define SIMDJSON_DEBUG_BLOCK(name, block) BEGIN_DEBUG_BLOCK(name); block; END_DEBUG_BLOCK(name);
+#else
+ #define SIMDJSON_BEGIN_DEBUG_BLOCK(name)
+ #define SIMDJSON_END_DEBUG_BLOCK(name)
+ #define SIMDJSON_DEBUG_BLOCK(name, block)
+#endif
+
+// Align to N-byte boundary
+#define SIMDJSON_ROUNDUP_N(a, n) (((a) + ((n)-1)) & ~((n)-1))
+#define SIMDJSON_ROUNDDOWN_N(a, n) ((a) & ~((n)-1))
+
+#define SIMDJSON_ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n)-1)) == 0)
+
+#if SIMDJSON_REGULAR_VISUAL_STUDIO
+
+ #define simdjson_really_inline __forceinline
+ #define simdjson_never_inline __declspec(noinline)
+
+ #define simdjson_unused
+ #define simdjson_warn_unused
+
+ #ifndef simdjson_likely
+ #define simdjson_likely(x) x
+ #endif
+ #ifndef simdjson_unlikely
+ #define simdjson_unlikely(x) x
+ #endif
+
+ #define SIMDJSON_PUSH_DISABLE_WARNINGS __pragma(warning( push ))
+ #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS __pragma(warning( push, 0 ))
+ #define SIMDJSON_DISABLE_VS_WARNING(WARNING_NUMBER) __pragma(warning( disable : WARNING_NUMBER ))
+ // Get rid of Intellisense-only warnings (Code Analysis)
+ // Though __has_include is C++17, it is supported in Visual Studio 2017 or better (_MSC_VER>=1910).
+ #ifdef __has_include
+ #if __has_include()
+ #include
+ #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS SIMDJSON_DISABLE_VS_WARNING(ALL_CPPCORECHECK_WARNINGS)
+ #endif
+ #endif
+
+ #ifndef SIMDJSON_DISABLE_UNDESIRED_WARNINGS
+ #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS
+ #endif
+
+ #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996)
+ #define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
+ #define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop ))
+
+ #define SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
+ #define SIMDJSON_POP_DISABLE_UNUSED_WARNINGS
+
+#else // SIMDJSON_REGULAR_VISUAL_STUDIO
+
+ #define simdjson_really_inline inline __attribute__((always_inline))
+ #define simdjson_never_inline inline __attribute__((noinline))
+
+ #define simdjson_unused __attribute__((unused))
+ #define simdjson_warn_unused __attribute__((warn_unused_result))
+
+ #ifndef simdjson_likely
+ #define simdjson_likely(x) __builtin_expect(!!(x), 1)
+ #endif
+ #ifndef simdjson_unlikely
+ #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
+ #endif
+
+ #define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push")
+ // gcc doesn't seem to disable all warnings with all and extra, add warnings here as necessary
+ // We do it separately for clang since it has different warnings.
+ #ifdef __clang__
+ // clang is missing -Wmaybe-uninitialized.
+ #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
+ SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wall) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wconversion) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wattributes) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wreturn-type) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable)
+ #else // __clang__
+ #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
+ SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wall) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wconversion) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wattributes) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wreturn-type) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wmaybe-uninitialized) \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wformat-security)
+ #endif // __clang__
+
+ #define SIMDJSON_PRAGMA(P) _Pragma(#P)
+ #define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING)
+ #if SIMDJSON_CLANG_VISUAL_STUDIO
+ #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS SIMDJSON_DISABLE_GCC_WARNING(-Wmicrosoft-include)
+ #else
+ #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS
+ #endif
+ #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations)
+ #define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wstrict-overflow)
+ #define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
+
+ #define SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
+ SIMDJSON_DISABLE_GCC_WARNING(-Wunused)
+ #define SIMDJSON_POP_DISABLE_UNUSED_WARNINGS SIMDJSON_POP_DISABLE_WARNINGS
+
+
+
+#endif // MSC_VER
+
+#if defined(simdjson_inline)
+ // Prefer the user's definition of simdjson_inline; don't define it ourselves.
+#elif defined(__GNUC__) && !defined(__OPTIMIZE__)
+ // If optimizations are disabled, forcing inlining can lead to significant
+ // code bloat and high compile times. Don't use simdjson_really_inline for
+ // unoptimized builds.
+ #define simdjson_inline inline
+#else
+ // Force inlining for most simdjson functions.
+ #define simdjson_inline simdjson_really_inline
+#endif
+
+#if SIMDJSON_VISUAL_STUDIO
+ /**
+ * Windows users need to do some extra work when building
+ * or using a dynamic library (DLL). When building, we need
+ * to set SIMDJSON_DLLIMPORTEXPORT to __declspec(dllexport).
+ * When *using* the DLL, the user needs to set
+ * SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport).
+ *
+ * Static libraries not need require such work.
+ *
+ * It does not matter here whether you are using
+ * the regular visual studio or clang under visual
+ * studio, you still need to handle these issues.
+ *
+ * Non-Windows systems do not have this complexity.
+ */
+ #if SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY
+ // We set SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY when we build a DLL under Windows.
+ // It should never happen that both SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY and
+ // SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY are set.
+ #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport)
+ #elif SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY
+ // Windows user who call a dynamic library should set SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY to 1.
+ #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
+ #else
+ // We assume by default static linkage
+ #define SIMDJSON_DLLIMPORTEXPORT
+ #endif
+
+/**
+ * Workaround for the vcpkg package manager. Only vcpkg should
+ * ever touch the next line. The SIMDJSON_USING_LIBRARY macro is otherwise unused.
+ */
+#if SIMDJSON_USING_LIBRARY
+#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
+#endif
+/**
+ * End of workaround for the vcpkg package manager.
+ */
+#else
+ #define SIMDJSON_DLLIMPORTEXPORT
+#endif
+
+// C++17 requires string_view.
+#if SIMDJSON_CPLUSPLUS17
+#define SIMDJSON_HAS_STRING_VIEW
+#include // by the standard, this has to be safe.
+#endif
+
+// This macro (__cpp_lib_string_view) has to be defined
+// for C++17 and better, but if it is otherwise defined,
+// we are going to assume that string_view is available
+// even if we do not have C++17 support.
+#ifdef __cpp_lib_string_view
+#define SIMDJSON_HAS_STRING_VIEW
+#endif
+
+// Some systems have string_view even if we do not have C++17 support,
+// and even if __cpp_lib_string_view is undefined, it is the case
+// with Apple clang version 11.
+// We must handle it. *This is important.*
+#ifndef SIMDJSON_HAS_STRING_VIEW
+#if defined __has_include
+// do not combine the next #if with the previous one (unsafe)
+#if __has_include ()
+// now it is safe to trigger the include
+#include // though the file is there, it does not follow that we got the implementation
+#if defined(_LIBCPP_STRING_VIEW)
+// Ah! So we under libc++ which under its Library Fundamentals Technical Specification, which preceded C++17,
+// included string_view.
+// This means that we have string_view *even though* we may not have C++17.
+#define SIMDJSON_HAS_STRING_VIEW
+#endif // _LIBCPP_STRING_VIEW
+#endif // __has_include ()
+#endif // defined __has_include
+#endif // def SIMDJSON_HAS_STRING_VIEW
+// end of complicated but important routine to try to detect string_view.
+
+//
+// Backfill std::string_view using nonstd::string_view on systems where
+// we expect that string_view is missing. Important: if we get this wrong,
+// we will end up with two string_view definitions and potential trouble.
+// That is why we work so hard above to avoid it.
+//
+#ifndef SIMDJSON_HAS_STRING_VIEW
+SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
+/* including simdjson/nonstd/string_view.hpp: #include "simdjson/nonstd/string_view.hpp" */
+/* begin file simdjson/nonstd/string_view.hpp */
+// Copyright 2017-2020 by Martin Moene
+//
+// string-view lite, a C++17-like string_view for C++98 and later.
+// For more information see https://github.com/martinmoene/string-view-lite
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#pragma once
+
+#ifndef NONSTD_SV_LITE_H_INCLUDED
+#define NONSTD_SV_LITE_H_INCLUDED
+
+#define string_view_lite_MAJOR 1
+#define string_view_lite_MINOR 7
+#define string_view_lite_PATCH 0
+
+#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
+
+#define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x )
+#define nssv_STRINGIFY_( x ) #x
+
+// string-view lite configuration:
+
+#define nssv_STRING_VIEW_DEFAULT 0
+#define nssv_STRING_VIEW_NONSTD 1
+#define nssv_STRING_VIEW_STD 2
+
+// tweak header support:
+
+#ifdef __has_include
+# if __has_include()
+# include
+# endif
+#define nssv_HAVE_TWEAK_HEADER 1
+#else
+#define nssv_HAVE_TWEAK_HEADER 0
+//# pragma message("string_view.hpp: Note: Tweak header not supported.")
+#endif
+
+// string_view selection and configuration:
+
+#if !defined( nssv_CONFIG_SELECT_STRING_VIEW )
+# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )
+#endif
+
+#ifndef nssv_CONFIG_STD_SV_OPERATOR
+# define nssv_CONFIG_STD_SV_OPERATOR 0
+#endif
+
+#ifndef nssv_CONFIG_USR_SV_OPERATOR
+# define nssv_CONFIG_USR_SV_OPERATOR 1
+#endif
+
+#ifdef nssv_CONFIG_CONVERSION_STD_STRING
+# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING
+# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING
+#endif
+
+#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
+# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
+#endif
+
+#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
+# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
+#endif
+
+#ifndef nssv_CONFIG_NO_STREAM_INSERTION
+# define nssv_CONFIG_NO_STREAM_INSERTION 0
+#endif
+
+// Control presence of exception handling (try and auto discover):
+
+#ifndef nssv_CONFIG_NO_EXCEPTIONS
+# if defined(_MSC_VER)
+# include // for _HAS_EXCEPTIONS
+# endif
+# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
+# define nssv_CONFIG_NO_EXCEPTIONS 0
+# else
+# define nssv_CONFIG_NO_EXCEPTIONS 1
+# endif
+#endif
+
+// C++ language version detection (C++23 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef nssv_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+# define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+# define nssv_CPLUSPLUS __cplusplus
+# endif
+#endif
+
+#define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L )
+#define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L )
+#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L )
+#define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L )
+#define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L )
+#define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202002L )
+#define nssv_CPP23_OR_GREATER ( nssv_CPLUSPLUS >= 202300L )
+
+// use C++17 std::string_view if available and requested:
+
+#if nssv_CPP17_OR_GREATER && defined(__has_include )
+# if __has_include( )
+# define nssv_HAVE_STD_STRING_VIEW 1
+# else
+# define nssv_HAVE_STD_STRING_VIEW 0
+# endif
+#else
+# define nssv_HAVE_STD_STRING_VIEW 0
+#endif
+
+#define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) )
+
+#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW )
+#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
+
+//
+// Use C++17 std::string_view:
+//
+
+#if nssv_USES_STD_STRING_VIEW
+
+#include
+
+// Extensions for std::string:
+
+#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
+
+namespace nonstd {
+
+template< class CharT, class Traits, class Allocator = std::allocator >
+std::basic_string
+to_string( std::basic_string_view v, Allocator const & a = Allocator() )
+{
+ return std::basic_string( v.begin(), v.end(), a );
+}
+
+template< class CharT, class Traits, class Allocator >
+std::basic_string_view
+to_string_view( std::basic_string const & s )
+{
+ return std::basic_string_view( s.data(), s.size() );
+}
+
+// Literal operators sv and _sv:
+
+#if nssv_CONFIG_STD_SV_OPERATOR
+
+using namespace std::literals::string_view_literals;
+
+#endif
+
+#if nssv_CONFIG_USR_SV_OPERATOR
+
+inline namespace literals {
+inline namespace string_view_literals {
+
+
+constexpr std::string_view operator "" _sv( const char* str, size_t len ) noexcept // (1)
+{
+ return std::string_view{ str, len };
+}
+
+constexpr std::u16string_view operator "" _sv( const char16_t* str, size_t len ) noexcept // (2)
+{
+ return std::u16string_view{ str, len };
+}
+
+constexpr std::u32string_view operator "" _sv( const char32_t* str, size_t len ) noexcept // (3)
+{
+ return std::u32string_view{ str, len };
+}
+
+constexpr std::wstring_view operator "" _sv( const wchar_t* str, size_t len ) noexcept // (4)
+{
+ return std::wstring_view{ str, len };
+}
+
+}} // namespace literals::string_view_literals
+
+#endif // nssv_CONFIG_USR_SV_OPERATOR
+
+} // namespace nonstd
+
+#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
+
+namespace nonstd {
+
+using std::string_view;
+using std::wstring_view;
+using std::u16string_view;
+using std::u32string_view;
+using std::basic_string_view;
+
+// literal "sv" and "_sv", see above
+
+using std::operator==;
+using std::operator!=;
+using std::operator<;
+using std::operator<=;
+using std::operator>;
+using std::operator>=;
+
+using std::operator<<;
+
+} // namespace nonstd
+
+#else // nssv_HAVE_STD_STRING_VIEW
+
+//
+// Before C++17: use string_view lite:
+//
+
+// Compiler versions:
+//
+// MSVC++ 6.0 _MSC_VER == 1200 nssv_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
+// MSVC++ 7.0 _MSC_VER == 1300 nssv_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
+// MSVC++ 7.1 _MSC_VER == 1310 nssv_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
+// MSVC++ 8.0 _MSC_VER == 1400 nssv_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
+// MSVC++ 9.0 _MSC_VER == 1500 nssv_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
+// MSVC++ 10.0 _MSC_VER == 1600 nssv_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
+// MSVC++ 11.0 _MSC_VER == 1700 nssv_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
+// MSVC++ 12.0 _MSC_VER == 1800 nssv_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
+// MSVC++ 14.0 _MSC_VER == 1900 nssv_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
+// MSVC++ 14.1 _MSC_VER >= 1910 nssv_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
+// MSVC++ 14.2 _MSC_VER >= 1920 nssv_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
+
+#if defined(_MSC_VER ) && !defined(__clang__)
+# define nssv_COMPILER_MSVC_VER (_MSC_VER )
+# define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define nssv_COMPILER_MSVC_VER 0
+# define nssv_COMPILER_MSVC_VERSION 0
+#endif
+
+#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+#if defined( __apple_build_version__ )
+# define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+# define nssv_COMPILER_CLANG_VERSION 0
+#elif defined( __clang__ )
+# define nssv_COMPILER_APPLECLANG_VERSION 0
+# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define nssv_COMPILER_APPLECLANG_VERSION 0
+# define nssv_COMPILER_CLANG_VERSION 0
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define nssv_COMPILER_GNUC_VERSION 0
+#endif
+
+// half-open range [lo..hi):
+#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Presence of language and library features:
+
+#ifdef _HAS_CPP0X
+# define nssv_HAS_CPP0X _HAS_CPP0X
+#else
+# define nssv_HAS_CPP0X 0
+#endif
+
+// Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
+
+#if nssv_COMPILER_MSVC_VER >= 1900
+# undef nssv_CPP11_OR_GREATER
+# define nssv_CPP11_OR_GREATER 1
+#endif
+
+#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
+#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
+#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
+#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
+#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
+#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
+
+#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
+#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
+
+// Presence of C++11 language features:
+
+#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
+#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
+#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
+#define nssv_HAVE_IS_DEFAULT nssv_CPP11_140
+#define nssv_HAVE_IS_DELETE nssv_CPP11_140
+#define nssv_HAVE_NOEXCEPT nssv_CPP11_140
+#define nssv_HAVE_NULLPTR nssv_CPP11_100
+#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
+#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
+#define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
+#define nssv_HAVE_WCHAR16_T nssv_CPP11_100
+#define nssv_HAVE_WCHAR32_T nssv_CPP11_100
+
+#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
+# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
+#else
+# define nssv_HAVE_STD_DEFINED_LITERALS 0
+#endif
+
+// Presence of C++14 language features:
+
+#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
+
+// Presence of C++17 language features:
+
+#define nssv_HAVE_NODISCARD nssv_CPP17_000
+
+// Presence of C++ library features:
+
+#define nssv_HAVE_STD_HASH nssv_CPP11_120
+
+// Presence of compiler intrinsics:
+
+// Providing char-type specializations for compare() and length() that
+// use compiler intrinsics can improve compile- and run-time performance.
+//
+// The challenge is in using the right combinations of builtin availability
+// and its constexpr-ness.
+//
+// | compiler | __builtin_memcmp (constexpr) | memcmp (constexpr) |
+// |----------|------------------------------|---------------------|
+// | clang | 4.0 (>= 4.0 ) | any (? ) |
+// | clang-a | 9.0 (>= 9.0 ) | any (? ) |
+// | gcc | any (constexpr) | any (? ) |
+// | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) |
+
+#define nssv_HAVE_BUILTIN_VER ( (nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || nssv_COMPILER_APPLECLANG_VERSION >= 900 )
+#define nssv_HAVE_BUILTIN_CE ( nssv_HAVE_BUILTIN_VER )
+
+#define nssv_HAVE_BUILTIN_MEMCMP ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 )
+#define nssv_HAVE_BUILTIN_STRLEN ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 )
+
+#ifdef __has_builtin
+# define nssv_HAVE_BUILTIN( x ) __has_builtin( x )
+#else
+# define nssv_HAVE_BUILTIN( x ) 0
+#endif
+
+#if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER
+# define nssv_BUILTIN_MEMCMP __builtin_memcmp
+#else
+# define nssv_BUILTIN_MEMCMP memcmp
+#endif
+
+#if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER
+# define nssv_BUILTIN_STRLEN __builtin_strlen
+#else
+# define nssv_BUILTIN_STRLEN strlen
+#endif
+
+// C++ feature usage:
+
+#if nssv_HAVE_CONSTEXPR_11
+# define nssv_constexpr constexpr
+#else
+# define nssv_constexpr /*constexpr*/
+#endif
+
+#if nssv_HAVE_CONSTEXPR_14
+# define nssv_constexpr14 constexpr
+#else
+# define nssv_constexpr14 /*constexpr*/
+#endif
+
+#if nssv_HAVE_EXPLICIT_CONVERSION
+# define nssv_explicit explicit
+#else
+# define nssv_explicit /*explicit*/
+#endif
+
+#if nssv_HAVE_INLINE_NAMESPACE
+# define nssv_inline_ns inline
+#else
+# define nssv_inline_ns /*inline*/
+#endif
+
+#if nssv_HAVE_NOEXCEPT
+# define nssv_noexcept noexcept
+#else
+# define nssv_noexcept /*noexcept*/
+#endif
+
+//#if nssv_HAVE_REF_QUALIFIER
+//# define nssv_ref_qual &
+//# define nssv_refref_qual &&
+//#else
+//# define nssv_ref_qual /*&*/
+//# define nssv_refref_qual /*&&*/
+//#endif
+
+#if nssv_HAVE_NULLPTR
+# define nssv_nullptr nullptr
+#else
+# define nssv_nullptr NULL
+#endif
+
+#if nssv_HAVE_NODISCARD
+# define nssv_nodiscard [[nodiscard]]
+#else
+# define nssv_nodiscard /*[[nodiscard]]*/
+#endif
+
+// Additional includes:
+
+#include
+#include
+#include
+#include
+#include // std::char_traits<>
+
+#if ! nssv_CONFIG_NO_STREAM_INSERTION
+# include
+#endif
+
+#if ! nssv_CONFIG_NO_EXCEPTIONS
+# include
+#endif
+
+#if nssv_CPP11_OR_GREATER
+# include
+#endif
+
+// Clang, GNUC, MSVC warning suppression macros:
+
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wuser-defined-literals"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wliteral-suffix"
+#endif // __clang__
+
+#if nssv_COMPILER_MSVC_VERSION >= 140
+# define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
+# define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) )
+# define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
+#else
+# define nssv_SUPPRESS_MSGSL_WARNING(expr)
+# define nssv_SUPPRESS_MSVC_WARNING(code, descr)
+# define nssv_DISABLE_MSVC_WARNINGS(codes)
+#endif
+
+#if defined(__clang__)
+# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
+#elif defined(__GNUC__)
+# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
+#elif nssv_COMPILER_MSVC_VERSION >= 140
+# define nssv_RESTORE_WARNINGS() __pragma(warning(pop ))
+#else
+# define nssv_RESTORE_WARNINGS()
+#endif
+
+// Suppress the following MSVC (GSL) warnings:
+// - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not
+// start with an underscore are reserved
+// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
+// use brace initialization, gsl::narrow_cast or gsl::narow
+// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
+
+nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
+//nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
+//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
+
+namespace nonstd { namespace sv_lite {
+
+//
+// basic_string_view declaration:
+//
+
+template
+<
+ class CharT,
+ class Traits = std::char_traits
+>
+class basic_string_view;
+
+namespace detail {
+
+// support constexpr comparison in C++14;
+// for C++17 and later, use provided traits:
+
+template< typename CharT >
+inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count )
+{
+ while ( count-- != 0 )
+ {
+ if ( *s1 < *s2 ) return -1;
+ if ( *s1 > *s2 ) return +1;
+ ++s1; ++s2;
+ }
+ return 0;
+}
+
+#if nssv_HAVE_BUILTIN_MEMCMP
+
+// specialization of compare() for char, see also generic compare() above:
+
+inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count )
+{
+ return nssv_BUILTIN_MEMCMP( s1, s2, count );
+}
+
+#endif
+
+#if nssv_HAVE_BUILTIN_STRLEN
+
+// specialization of length() for char, see also generic length() further below:
+
+inline nssv_constexpr std::size_t length( char const * s )
+{
+ return nssv_BUILTIN_STRLEN( s );
+}
+
+#endif
+
+#if defined(__OPTIMIZE__)
+
+// gcc, clang provide __OPTIMIZE__
+// Expect tail call optimization to make length() non-recursive:
+
+template< typename CharT >
+inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 )
+{
+ return *s == '\0' ? result : length( s + 1, result + 1 );
+}
+
+#else // OPTIMIZE
+
+// non-recursive:
+
+template< typename CharT >
+inline nssv_constexpr14 std::size_t length( CharT * s )
+{
+ std::size_t result = 0;
+ while ( *s++ != '\0' )
+ {
+ ++result;
+ }
+ return result;
+}
+
+#endif // OPTIMIZE
+
+#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
+#if defined(__OPTIMIZE__)
+
+// gcc, clang provide __OPTIMIZE__
+// Expect tail call optimization to make search() non-recursive:
+
+template< class CharT, class Traits = std::char_traits >
+constexpr const CharT* search( basic_string_view haystack, basic_string_view needle )
+{
+ return haystack.starts_with( needle ) ? haystack.begin() :
+ haystack.empty() ? haystack.end() : search( haystack.substr(1), needle );
+}
+
+#else // OPTIMIZE
+
+// non-recursive:
+
+template< class CharT, class Traits = std::char_traits >
+constexpr const CharT* search( basic_string_view haystack, basic_string_view needle )
+{
+ return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
+}
+
+#endif // OPTIMIZE
+#endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
+
+} // namespace detail
+
+//
+// basic_string_view:
+//
+
+template
+<
+ class CharT,
+ class Traits /* = std::char_traits */
+>
+class basic_string_view
+{
+public:
+ // Member types:
+
+ typedef Traits traits_type;
+ typedef CharT value_type;
+
+ typedef CharT * pointer;
+ typedef CharT const * const_pointer;
+ typedef CharT & reference;
+ typedef CharT const & const_reference;
+
+ typedef const_pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef std::reverse_iterator< const_iterator > reverse_iterator;
+ typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ // 24.4.2.1 Construction and assignment:
+
+ nssv_constexpr basic_string_view() nssv_noexcept
+ : data_( nssv_nullptr )
+ , size_( 0 )
+ {}
+
+#if nssv_CPP11_OR_GREATER
+ nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default;
+#else
+ nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept
+ : data_( other.data_)
+ , size_( other.size_)
+ {}
+#endif
+
+ nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept
+ : data_( s )
+ , size_( count )
+ {}
+
+ nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept
+ : data_( s )
+#if nssv_CPP17_OR_GREATER
+ , size_( Traits::length(s) )
+#elif nssv_CPP11_OR_GREATER
+ , size_( detail::length(s) )
+#else
+ , size_( Traits::length(s) )
+#endif
+ {}
+
+#if nssv_HAVE_NULLPTR
+# if nssv_HAVE_IS_DELETE
+ nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept = delete;
+# else
+ private: nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept; public:
+# endif
+#endif
+
+ // Assignment:
+
+#if nssv_CPP11_OR_GREATER
+ nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default;
+#else
+ nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept
+ {
+ data_ = other.data_;
+ size_ = other.size_;
+ return *this;
+ }
+#endif
+
+ // 24.4.2.2 Iterator support:
+
+ nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; }
+ nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; }
+
+ nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }
+ nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); }
+
+ nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator( end() ); }
+ nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator( begin() ); }
+
+ nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }
+ nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); }
+
+ // 24.4.2.3 Capacity:
+
+ nssv_constexpr size_type size() const nssv_noexcept { return size_; }
+ nssv_constexpr size_type length() const nssv_noexcept { return size_; }
+ nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); }
+
+ // since C++20
+ nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept
+ {
+ return 0 == size_;
+ }
+
+ // 24.4.2.4 Element access:
+
+ nssv_constexpr const_reference operator[]( size_type pos ) const
+ {
+ return data_at( pos );
+ }
+
+ nssv_constexpr14 const_reference at( size_type pos ) const
+ {
+#if nssv_CONFIG_NO_EXCEPTIONS
+ assert( pos < size() );
+#else
+ if ( pos >= size() )
+ {
+ throw std::out_of_range("nonstd::string_view::at()");
+ }
+#endif
+ return data_at( pos );
+ }
+
+ nssv_constexpr const_reference front() const { return data_at( 0 ); }
+ nssv_constexpr const_reference back() const { return data_at( size() - 1 ); }
+
+ nssv_constexpr const_pointer data() const nssv_noexcept { return data_; }
+
+ // 24.4.2.5 Modifiers:
+
+ nssv_constexpr14 void remove_prefix( size_type n )
+ {
+ assert( n <= size() );
+ data_ += n;
+ size_ -= n;
+ }
+
+ nssv_constexpr14 void remove_suffix( size_type n )
+ {
+ assert( n <= size() );
+ size_ -= n;
+ }
+
+ nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept
+ {
+ const basic_string_view tmp(other);
+ other = *this;
+ *this = tmp;
+ }
+
+ // 24.4.2.6 String operations:
+
+ size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const
+ {
+#if nssv_CONFIG_NO_EXCEPTIONS
+ assert( pos <= size() );
+#else
+ if ( pos > size() )
+ {
+ throw std::out_of_range("nonstd::string_view::copy()");
+ }
+#endif
+ const size_type rlen = (std::min)( n, size() - pos );
+
+ (void) Traits::copy( dest, data() + pos, rlen );
+
+ return rlen;
+ }
+
+ nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const
+ {
+#if nssv_CONFIG_NO_EXCEPTIONS
+ assert( pos <= size() );
+#else
+ if ( pos > size() )
+ {
+ throw std::out_of_range("nonstd::string_view::substr()");
+ }
+#endif
+ return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );
+ }
+
+ // compare(), 6x:
+
+ nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
+ {
+#if nssv_CPP17_OR_GREATER
+ if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
+#else
+ if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
+#endif
+ {
+ return result;
+ }
+
+ return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
+ }
+
+ nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2)
+ {
+ return substr( pos1, n1 ).compare( other );
+ }
+
+ nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3)
+ {
+ return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) );
+ }
+
+ nssv_constexpr int compare( CharT const * s ) const // (4)
+ {
+ return compare( basic_string_view( s ) );
+ }
+
+ nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5)
+ {
+ return substr( pos1, n1 ).compare( basic_string_view( s ) );
+ }
+
+ nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6)
+ {
+ return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );
+ }
+
+ // 24.4.2.7 Searching:
+
+ // starts_with(), 3x, since C++20:
+
+ nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept // (1)
+ {
+ return size() >= v.size() && compare( 0, v.size(), v ) == 0;
+ }
+
+ nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept // (2)
+ {
+ return starts_with( basic_string_view( &c, 1 ) );
+ }
+
+ nssv_constexpr bool starts_with( CharT const * s ) const // (3)
+ {
+ return starts_with( basic_string_view( s ) );
+ }
+
+ // ends_with(), 3x, since C++20:
+
+ nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept // (1)
+ {
+ return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0;
+ }
+
+ nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept // (2)
+ {
+ return ends_with( basic_string_view( &c, 1 ) );
+ }
+
+ nssv_constexpr bool ends_with( CharT const * s ) const // (3)
+ {
+ return ends_with( basic_string_view( s ) );
+ }
+
+ // find(), 4x:
+
+ nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
+ {
+ return assert( v.size() == 0 || v.data() != nssv_nullptr )
+ , pos >= size()
+ ? npos : to_pos(
+#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
+ detail::search( substr(pos), v )
+#else
+ std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq )
+#endif
+ );
+ }
+
+ nssv_constexpr size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
+ {
+ return find( basic_string_view( &c, 1 ), pos );
+ }
+
+ nssv_constexpr size_type find( CharT const * s, size_type pos, size_type n ) const // (3)
+ {
+ return find( basic_string_view( s, n ), pos );
+ }
+
+ nssv_constexpr size_type find( CharT const * s, size_type pos = 0 ) const // (4)
+ {
+ return find( basic_string_view( s ), pos );
+ }
+
+ // rfind(), 4x:
+
+ nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
+ {
+ if ( size() < v.size() )
+ {
+ return npos;
+ }
+
+ if ( v.empty() )
+ {
+ return (std::min)( size(), pos );
+ }
+
+ const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();
+ const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );
+
+ return result != last ? size_type( result - cbegin() ) : npos;
+ }
+
+ nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
+ {
+ return rfind( basic_string_view( &c, 1 ), pos );
+ }
+
+ nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const // (3)
+ {
+ return rfind( basic_string_view( s, n ), pos );
+ }
+
+ nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const // (4)
+ {
+ return rfind( basic_string_view( s ), pos );
+ }
+
+ // find_first_of(), 4x:
+
+ nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
+ {
+ return pos >= size()
+ ? npos
+ : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );
+ }
+
+ nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
+ {
+ return find_first_of( basic_string_view( &c, 1 ), pos );
+ }
+
+ nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const // (3)
+ {
+ return find_first_of( basic_string_view( s, n ), pos );
+ }
+
+ nssv_constexpr size_type find_first_of( CharT const * s, size_type pos = 0 ) const // (4)
+ {
+ return find_first_of( basic_string_view( s ), pos );
+ }
+
+ // find_last_of(), 4x:
+
+ nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
+ {
+ return empty()
+ ? npos
+ : pos >= size()
+ ? find_last_of( v, size() - 1 )
+ : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) );
+ }
+
+ nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
+ {
+ return find_last_of( basic_string_view( &c, 1 ), pos );
+ }
+
+ nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const // (3)
+ {
+ return find_last_of( basic_string_view( s, count ), pos );
+ }
+
+ nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const // (4)
+ {
+ return find_last_of( basic_string_view( s ), pos );
+ }
+
+ // find_first_not_of(), 4x:
+
+ nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
+ {
+ return pos >= size()
+ ? npos
+ : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) );
+ }
+
+ nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
+ {
+ return find_first_not_of( basic_string_view( &c, 1 ), pos );
+ }
+
+ nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
+ {
+ return find_first_not_of( basic_string_view( s, count ), pos );
+ }
+
+ nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const // (4)
+ {
+ return find_first_not_of( basic_string_view( s ), pos );
+ }
+
+ // find_last_not_of(), 4x:
+
+ nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
+ {
+ return empty()
+ ? npos
+ : pos >= size()
+ ? find_last_not_of( v, size() - 1 )
+ : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) );
+ }
+
+ nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
+ {
+ return find_last_not_of( basic_string_view( &c, 1 ), pos );
+ }
+
+ nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
+ {
+ return find_last_not_of( basic_string_view( s, count ), pos );
+ }
+
+ nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const // (4)
+ {
+ return find_last_not_of( basic_string_view( s ), pos );
+ }
+
+ // Constants:
+
+#if nssv_CPP17_OR_GREATER
+ static nssv_constexpr size_type npos = size_type(-1);
+#elif nssv_CPP11_OR_GREATER
+ enum : size_type { npos = size_type(-1) };
+#else
+ enum { npos = size_type(-1) };
+#endif
+
+private:
+ struct not_in_view
+ {
+ const basic_string_view v;
+
+ nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {}
+
+ nssv_constexpr bool operator()( CharT c ) const
+ {
+ return npos == v.find_first_of( c );
+ }
+ };
+
+ nssv_constexpr size_type to_pos( const_iterator it ) const
+ {
+ return it == cend() ? npos : size_type( it - cbegin() );
+ }
+
+ nssv_constexpr size_type to_pos( const_reverse_iterator it ) const
+ {
+ return it == crend() ? npos : size_type( crend() - it - 1 );
+ }
+
+ nssv_constexpr const_reference data_at( size_type pos ) const
+ {
+#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 )
+ return data_[pos];
+#else
+ return assert( pos < size() ), data_[pos];
+#endif
+ }
+
+private:
+ const_pointer data_;
+ size_type size_;
+
+public:
+#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
+
+ template< class Allocator >
+ basic_string_view( std::basic_string const & s ) nssv_noexcept
+ : data_( s.data() )
+ , size_( s.size() )
+ {}
+
+#if nssv_HAVE_EXPLICIT_CONVERSION
+
+ template< class Allocator >
+ explicit operator std::basic_string() const
+ {
+ return to_string( Allocator() );
+ }
+
+#endif // nssv_HAVE_EXPLICIT_CONVERSION
+
+#if nssv_CPP11_OR_GREATER
+
+ template< class Allocator = std::allocator >
+ std::basic_string
+ to_string( Allocator const & a = Allocator() ) const
+ {
+ return std::basic_string( begin(), end(), a );
+ }
+
+#else
+
+ std::basic_string
+ to_string() const
+ {
+ return std::basic_string( begin(), end() );
+ }
+
+ template< class Allocator >
+ std::basic_string
+ to_string( Allocator const & a ) const
+ {
+ return std::basic_string( begin(), end(), a );
+ }
+
+#endif // nssv_CPP11_OR_GREATER
+
+#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
+};
+
+//
+// Non-member functions:
+//
+
+// 24.4.3 Non-member comparison functions:
+// lexicographically compare two string views (function template):
+
+template< class CharT, class Traits >
+nssv_constexpr bool operator== (
+ basic_string_view lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
+
+template< class CharT, class Traits >
+nssv_constexpr bool operator!= (
+ basic_string_view lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return !( lhs == rhs ); }
+
+template< class CharT, class Traits >
+nssv_constexpr bool operator< (
+ basic_string_view lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) < 0; }
+
+template< class CharT, class Traits >
+nssv_constexpr bool operator<= (
+ basic_string_view lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) <= 0; }
+
+template< class CharT, class Traits >
+nssv_constexpr bool operator> (
+ basic_string_view lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) > 0; }
+
+template< class CharT, class Traits >
+nssv_constexpr bool operator>= (
+ basic_string_view lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) >= 0; }
+
+// Let S be basic_string_view, and sv be an instance of S.
+// Implementations shall provide sufficient additional overloads marked
+// constexpr and noexcept so that an object t with an implicit conversion
+// to S can be compared according to Table 67.
+
+#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
+
+// accommodate for older compilers:
+
+// ==
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator==(
+ basic_string_view lhs,
+ CharT const * rhs ) nssv_noexcept
+{ return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator==(
+ CharT const * lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator==(
+ basic_string_view lhs,
+ std::basic_string rhs ) nssv_noexcept
+{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator==(
+ std::basic_string rhs,
+ basic_string_view lhs ) nssv_noexcept
+{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
+
+// !=
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator!=(
+ basic_string_view lhs,
+ CharT const * rhs ) nssv_noexcept
+{ return !( lhs == rhs ); }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator!=(
+ CharT const * lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return !( lhs == rhs ); }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator!=(
+ basic_string_view lhs,
+ std::basic_string rhs ) nssv_noexcept
+{ return !( lhs == rhs ); }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator!=(
+ std::basic_string rhs,
+ basic_string_view lhs ) nssv_noexcept
+{ return !( lhs == rhs ); }
+
+// <
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<(
+ basic_string_view lhs,
+ CharT const * rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) < 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<(
+ CharT const * lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return rhs.compare( lhs ) > 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<(
+ basic_string_view lhs,
+ std::basic_string rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) < 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<(
+ std::basic_string rhs,
+ basic_string_view lhs ) nssv_noexcept
+{ return rhs.compare( lhs ) > 0; }
+
+// <=
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<=(
+ basic_string_view lhs,
+ CharT const * rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) <= 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<=(
+ CharT const * lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return rhs.compare( lhs ) >= 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<=(
+ basic_string_view lhs,
+ std::basic_string rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) <= 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator<=(
+ std::basic_string rhs,
+ basic_string_view lhs ) nssv_noexcept
+{ return rhs.compare( lhs ) >= 0; }
+
+// >
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>(
+ basic_string_view lhs,
+ CharT const * rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) > 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>(
+ CharT const * lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return rhs.compare( lhs ) < 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>(
+ basic_string_view lhs,
+ std::basic_string rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) > 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>(
+ std::basic_string rhs,
+ basic_string_view lhs ) nssv_noexcept
+{ return rhs.compare( lhs ) < 0; }
+
+// >=
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>=(
+ basic_string_view lhs,
+ CharT const * rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) >= 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>=(
+ CharT const * lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return rhs.compare( lhs ) <= 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>=(
+ basic_string_view lhs,
+ std::basic_string rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) >= 0; }
+
+template< class CharT, class Traits>
+nssv_constexpr bool operator>=(
+ std::basic_string rhs,
+ basic_string_view lhs ) nssv_noexcept
+{ return rhs.compare( lhs ) <= 0; }
+
+#else // newer compilers:
+
+#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view >::type
+
+#if defined(_MSC_VER) // issue 40
+# define nssv_MSVC_ORDER(x) , int=x
+#else
+# define nssv_MSVC_ORDER(x) /*, int=x*/
+#endif
+
+// ==
+
+template< class CharT, class Traits nssv_MSVC_ORDER(1) >
+nssv_constexpr bool operator==(
+ basic_string_view lhs,
+ nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept
+{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
+
+template< class CharT, class Traits nssv_MSVC_ORDER(2) >
+nssv_constexpr bool operator==(
+ nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
+ basic_string_view rhs ) nssv_noexcept
+{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
+
+// !=
+
+template< class CharT, class Traits nssv_MSVC_ORDER(1) >
+nssv_constexpr bool operator!= (
+ basic_string_view < CharT, Traits > lhs,
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
+{ return !( lhs == rhs ); }
+
+template< class CharT, class Traits nssv_MSVC_ORDER(2) >
+nssv_constexpr bool operator!= (
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
+ basic_string_view < CharT, Traits > rhs ) nssv_noexcept
+{ return !( lhs == rhs ); }
+
+// <
+
+template< class CharT, class Traits nssv_MSVC_ORDER(1) >
+nssv_constexpr bool operator< (
+ basic_string_view < CharT, Traits > lhs,
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) < 0; }
+
+template< class CharT, class Traits nssv_MSVC_ORDER(2) >
+nssv_constexpr bool operator< (
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
+ basic_string_view < CharT, Traits > rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) < 0; }
+
+// <=
+
+template< class CharT, class Traits nssv_MSVC_ORDER(1) >
+nssv_constexpr bool operator<= (
+ basic_string_view < CharT, Traits > lhs,
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) <= 0; }
+
+template< class CharT, class Traits nssv_MSVC_ORDER(2) >
+nssv_constexpr bool operator<= (
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
+ basic_string_view < CharT, Traits > rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) <= 0; }
+
+// >
+
+template< class CharT, class Traits nssv_MSVC_ORDER(1) >
+nssv_constexpr bool operator> (
+ basic_string_view < CharT, Traits > lhs,
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) > 0; }
+
+template< class CharT, class Traits nssv_MSVC_ORDER(2) >
+nssv_constexpr bool operator> (
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
+ basic_string_view < CharT, Traits > rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) > 0; }
+
+// >=
+
+template< class CharT, class Traits nssv_MSVC_ORDER(1) >
+nssv_constexpr bool operator>= (
+ basic_string_view < CharT, Traits > lhs,
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) >= 0; }
+
+template< class CharT, class Traits nssv_MSVC_ORDER(2) >
+nssv_constexpr bool operator>= (
+ nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
+ basic_string_view < CharT, Traits > rhs ) nssv_noexcept
+{ return lhs.compare( rhs ) >= 0; }
+
+#undef nssv_MSVC_ORDER
+#undef nssv_BASIC_STRING_VIEW_I
+
+#endif // compiler-dependent approach to comparisons
+
+// 24.4.4 Inserters and extractors:
+
+#if ! nssv_CONFIG_NO_STREAM_INSERTION
+
+namespace detail {
+
+template< class Stream >
+void write_padding( Stream & os, std::streamsize n )
+{
+ for ( std::streamsize i = 0; i < n; ++i )
+ os.rdbuf()->sputc( os.fill() );
+}
+
+template< class Stream, class View >
+Stream & write_to_stream( Stream & os, View const & sv )
+{
+ typename Stream::sentry sentry( os );
+
+ if ( !sentry )
+ return os;
+
+ const std::streamsize length = static_cast( sv.length() );
+
+ // Whether, and how, to pad:
+ const bool pad = ( length < os.width() );
+ const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;
+
+ if ( left_pad )
+ write_padding( os, os.width() - length );
+
+ // Write span characters:
+ os.rdbuf()->sputn( sv.begin(), length );
+
+ if ( pad && !left_pad )
+ write_padding( os, os.width() - length );
+
+ // Reset output stream width:
+ os.width( 0 );
+
+ return os;
+}
+
+} // namespace detail
+
+template< class CharT, class Traits >
+std::basic_ostream &
+operator<<(
+ std::basic_ostream& os,
+ basic_string_view sv )
+{
+ return detail::write_to_stream( os, sv );
+}
+
+#endif // nssv_CONFIG_NO_STREAM_INSERTION
+
+// Several typedefs for common character types are provided:
+
+typedef basic_string_view string_view;
+typedef basic_string_view wstring_view;
+#if nssv_HAVE_WCHAR16_T
+typedef basic_string_view u16string_view;
+typedef basic_string_view u32string_view;
+#endif
+
+}} // namespace nonstd::sv_lite
+
+//
+// 24.4.6 Suffix for basic_string_view literals:
+//
+
+#if nssv_HAVE_USER_DEFINED_LITERALS
+
+namespace nonstd {
+nssv_inline_ns namespace literals {
+nssv_inline_ns namespace string_view_literals {
+
+#if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
+
+nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept // (1)
+{
+ return nonstd::sv_lite::string_view{ str, len };
+}
+
+nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
+{
+ return nonstd::sv_lite::u16string_view{ str, len };
+}
+
+nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
+{
+ return nonstd::sv_lite::u32string_view{ str, len };
+}
+
+nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
+{
+ return nonstd::sv_lite::wstring_view{ str, len };
+}
+
+#endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
+
+#if nssv_CONFIG_USR_SV_OPERATOR
+
+nssv_constexpr nonstd::sv_lite::string_view operator "" _sv( const char* str, size_t len ) nssv_noexcept // (1)
+{
+ return nonstd::sv_lite::string_view{ str, len };
+}
+
+nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
+{
+ return nonstd::sv_lite::u16string_view{ str, len };
+}
+
+nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
+{
+ return nonstd::sv_lite::u32string_view{ str, len };
+}
+
+nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
+{
+ return nonstd::sv_lite::wstring_view{ str, len };
+}
+
+#endif // nssv_CONFIG_USR_SV_OPERATOR
+
+}}} // namespace nonstd::literals::string_view_literals
+
+#endif
+
+//
+// Extensions for std::string:
+//
+
+#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
+
+namespace nonstd {
+namespace sv_lite {
+
+// Exclude MSVC 14 (19.00): it yields ambiguous to_string():
+
+#if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
+
+template< class CharT, class Traits, class Allocator = std::allocator >
+std::basic_string
+to_string( basic_string_view v, Allocator const & a = Allocator() )
+{
+ return std::basic_string( v.begin(), v.end(), a );
+}
+
+#else
+
+template< class CharT, class Traits >
+std::basic_string
+to_string( basic_string_view v )
+{
+ return std::basic_string( v.begin(), v.end() );
+}
+
+template< class CharT, class Traits, class Allocator >
+std::basic_string
+to_string( basic_string_view v, Allocator const & a )
+{
+ return std::basic_string( v.begin(), v.end(), a );
+}
+
+#endif // nssv_CPP11_OR_GREATER
+
+template< class CharT, class Traits, class Allocator >
+basic_string_view
+to_string_view( std::basic_string const & s )
+{
+ return basic_string_view( s.data(), s.size() );
+}
+
+}} // namespace nonstd::sv_lite
+
+#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
+
+//
+// make types and algorithms available in namespace nonstd:
+//
+
+namespace nonstd {
+
+using sv_lite::basic_string_view;
+using sv_lite::string_view;
+using sv_lite::wstring_view;
+
+#if nssv_HAVE_WCHAR16_T
+using sv_lite::u16string_view;
+#endif
+#if nssv_HAVE_WCHAR32_T
+using sv_lite::u32string_view;
+#endif
+
+// literal "sv"
+
+using sv_lite::operator==;
+using sv_lite::operator!=;
+using sv_lite::operator<;
+using sv_lite::operator<=;
+using sv_lite::operator>;
+using sv_lite::operator>=;
+
+#if ! nssv_CONFIG_NO_STREAM_INSERTION
+using sv_lite::operator<<;
+#endif
+
+#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
+using sv_lite::to_string;
+using sv_lite::to_string_view;
+#endif
+
+} // namespace nonstd
+
+// 24.4.5 Hash support (C++11):
+
+// Note: The hash value of a string view object is equal to the hash value of
+// the corresponding string object.
+
+#if nssv_HAVE_STD_HASH
+
+#include
+
+namespace std {
+
+template<>
+struct hash< nonstd::string_view >
+{
+public:
+ std::size_t operator()( nonstd::string_view v ) const nssv_noexcept
+ {
+ return std::hash()( std::string( v.data(), v.size() ) );
+ }
+};
+
+template<>
+struct hash< nonstd::wstring_view >
+{
+public:
+ std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept
+ {
+ return std::hash()( std::wstring( v.data(), v.size() ) );
+ }
+};
+
+template<>
+struct hash< nonstd::u16string_view >
+{
+public:
+ std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept
+ {
+ return std::hash()( std::u16string( v.data(), v.size() ) );
+ }
+};
+
+template<>
+struct hash< nonstd::u32string_view >
+{
+public:
+ std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept
+ {
+ return std::hash()( std::u32string( v.data(), v.size() ) );
+ }
+};
+
+} // namespace std
+
+#endif // nssv_HAVE_STD_HASH
+
+nssv_RESTORE_WARNINGS()
+
+#endif // nssv_HAVE_STD_STRING_VIEW
+#endif // NONSTD_SV_LITE_H_INCLUDED
+/* end file simdjson/nonstd/string_view.hpp */
+SIMDJSON_POP_DISABLE_WARNINGS
+
+namespace std {
+ using string_view = nonstd::string_view;
+}
+#endif // SIMDJSON_HAS_STRING_VIEW
+#undef SIMDJSON_HAS_STRING_VIEW // We are not going to need this macro anymore.
+
+/// If EXPR is an error, returns it.
+#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
+
+// Unless the programmer has already set SIMDJSON_DEVELOPMENT_CHECKS,
+// we want to set it under debug builds. We detect a debug build
+// under Visual Studio when the _DEBUG macro is set. Under the other
+// compilers, we use the fact that they define __OPTIMIZE__ whenever
+// they allow optimizations.
+// It is possible that this could miss some cases where SIMDJSON_DEVELOPMENT_CHECKS
+// is helpful, but the programmer can set the macro SIMDJSON_DEVELOPMENT_CHECKS.
+// It could also wrongly set SIMDJSON_DEVELOPMENT_CHECKS (e.g., if the programmer
+// sets _DEBUG in a release build under Visual Studio, or if some compiler fails to
+// set the __OPTIMIZE__ macro).
+#ifndef SIMDJSON_DEVELOPMENT_CHECKS
+#ifdef _MSC_VER
+// Visual Studio seems to set _DEBUG for debug builds.
+#ifdef _DEBUG
+#define SIMDJSON_DEVELOPMENT_CHECKS 1
+#endif // _DEBUG
+#else // _MSC_VER
+// All other compilers appear to set __OPTIMIZE__ to a positive integer
+// when the compiler is optimizing.
+#ifndef __OPTIMIZE__
+#define SIMDJSON_DEVELOPMENT_CHECKS 1
+#endif // __OPTIMIZE__
+#endif // _MSC_VER
+#endif // SIMDJSON_DEVELOPMENT_CHECKS
+
+// The SIMDJSON_CHECK_EOF macro is a feature flag for the "don't require padding"
+// feature.
+
+#if SIMDJSON_CPLUSPLUS17
+// if we have C++, then fallthrough is a default attribute
+# define simdjson_fallthrough [[fallthrough]]
+// check if we have __attribute__ support
+#elif defined(__has_attribute)
+// check if we have the __fallthrough__ attribute
+#if __has_attribute(__fallthrough__)
+// we are good to go:
+# define simdjson_fallthrough __attribute__((__fallthrough__))
+#endif // __has_attribute(__fallthrough__)
+#endif // SIMDJSON_CPLUSPLUS17
+// on some systems, we simply do not have support for fallthrough, so use a default:
+#ifndef simdjson_fallthrough
+# define simdjson_fallthrough do {} while (0) /* fallthrough */
+#endif // simdjson_fallthrough
+
+#if SIMDJSON_DEVELOPMENT_CHECKS
+#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0)
+#else
+#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
+#endif
+
+#ifndef SIMDJSON_UTF8VALIDATION
+#define SIMDJSON_UTF8VALIDATION 1
+#endif
+
+#ifdef __has_include
+// How do we detect that a compiler supports vbmi2?
+// For sure if the following header is found, we are ok?
+#if __has_include()
+#define SIMDJSON_COMPILER_SUPPORTS_VBMI2 1
+#endif
+#endif
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1920
+// Visual Studio 2019 and up support VBMI2 under x64 even if the header
+// avx512vbmi2intrin.h is not found.
+#define SIMDJSON_COMPILER_SUPPORTS_VBMI2 1
+#endif
+#endif
+
+// By default, we allow AVX512.
+#ifndef SIMDJSON_AVX512_ALLOWED
+#define SIMDJSON_AVX512_ALLOWED 1
+#endif
+
+#endif // SIMDJSON_COMMON_DEFS_H
+/* end file simdjson/common_defs.h */
+/* skipped duplicate #include "simdjson/compiler_check.h" */
+/* including simdjson/error.h: #include "simdjson/error.h" */
+/* begin file simdjson/error.h */
+#ifndef SIMDJSON_ERROR_H
+#define SIMDJSON_ERROR_H
+
+/* skipped duplicate #include "simdjson/base.h" */
+
+#include
+#include
+
+namespace simdjson {
+
+/**
+ * All possible errors returned by simdjson. These error codes are subject to change
+ * and not all simdjson kernel returns the same error code given the same input: it is not
+ * well defined which error a given input should produce.
+ *
+ * Only SUCCESS evaluates to false as a Boolean. All other error codes will evaluate
+ * to true as a Boolean.
+ */
+enum error_code {
+ SUCCESS = 0, ///< No error
+ CAPACITY, ///< This parser can't support a document that big
+ MEMALLOC, ///< Error allocating memory, most likely out of memory
+ TAPE_ERROR, ///< Something went wrong, this is a generic error
+ DEPTH_ERROR, ///< Your document exceeds the user-specified depth limitation
+ STRING_ERROR, ///< Problem while parsing a string
+ T_ATOM_ERROR, ///< Problem while parsing an atom starting with the letter 't'
+ F_ATOM_ERROR, ///< Problem while parsing an atom starting with the letter 'f'
+ N_ATOM_ERROR, ///< Problem while parsing an atom starting with the letter 'n'
+ NUMBER_ERROR, ///< Problem while parsing a number
+ UTF8_ERROR, ///< the input is not valid UTF-8
+ UNINITIALIZED, ///< unknown error, or uninitialized document
+ EMPTY, ///< no structural element found
+ UNESCAPED_CHARS, ///< found unescaped characters in a string.
+ UNCLOSED_STRING, ///< missing quote at the end
+ UNSUPPORTED_ARCHITECTURE, ///< unsupported architecture
+ INCORRECT_TYPE, ///< JSON element has a different type than user expected
+ NUMBER_OUT_OF_RANGE, ///< JSON number does not fit in 64 bits
+ INDEX_OUT_OF_BOUNDS, ///< JSON array index too large
+ NO_SUCH_FIELD, ///< JSON field not found in object
+ IO_ERROR, ///< Error reading a file
+ INVALID_JSON_POINTER, ///< Invalid JSON pointer reference
+ INVALID_URI_FRAGMENT, ///< Invalid URI fragment
+ UNEXPECTED_ERROR, ///< indicative of a bug in simdjson
+ PARSER_IN_USE, ///< parser is already in use.
+ OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1)
+ INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it.
+ INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
+ SCALAR_DOCUMENT_AS_VALUE, ///< A scalar document is treated as a value.
+ OUT_OF_BOUNDS, ///< Attempted to access location outside of document.
+ TRAILING_CONTENT, ///< Unexpected trailing content in the JSON input
+ NUM_ERROR_CODES
+};
+
+/**
+ * It is the convention throughout the code that the macro SIMDJSON_DEVELOPMENT_CHECKS determines whether
+ * we check for OUT_OF_ORDER_ITERATION. The logic behind it is that these errors only occurs when the code
+ * that was written while breaking some simdjson::ondemand requirement. They should not occur in released
+ * code after these issues were fixed.
+ */
+
+/**
+ * Get the error message for the given error code.
+ *
+ * dom::parser parser;
+ * dom::element doc;
+ * auto error = parser.parse("foo",3).get(doc);
+ * if (error) { printf("Error: %s\n", error_message(error)); }
+ *
+ * @return The error message.
+ */
+inline const char *error_message(error_code error) noexcept;
+
+/**
+ * Write the error message to the output stream
+ */
+inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept;
+
+/**
+ * Exception thrown when an exception-supporting simdjson method is called
+ */
+struct simdjson_error : public std::exception {
+ /**
+ * Create an exception from a simdjson error code.
+ * @param error The error code
+ */
+ simdjson_error(error_code error) noexcept : _error{error} { }
+ /** The error message */
+ const char *what() const noexcept { return error_message(error()); }
+ /** The error code */
+ error_code error() const noexcept { return _error; }
+private:
+ /** The error code that was used */
+ error_code _error;
+};
+
+namespace internal {
+
+/**
+ * The result of a simdjson operation that could fail.
+ *
+ * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
+ *
+ * This is a base class for implementations that want to add functions to the result type for
+ * chaining.
+ *
+ * Override like:
+ *
+ * struct simdjson_result : public internal::simdjson_result_base {
+ * simdjson_result() noexcept : internal::simdjson_result_base() {}
+ * simdjson_result(error_code error) noexcept : internal::simdjson_result_base(error) {}
+ * simdjson_result(T &&value) noexcept : internal::simdjson_result_base(std::forward(value)) {}
+ * simdjson_result(T &&value, error_code error) noexcept : internal::simdjson_result_base(value, error) {}
+ * // Your extra methods here
+ * }
+ *
+ * Then any method returning simdjson_result will be chainable with your methods.
+ */
+template
+struct simdjson_result_base : protected std::pair {
+
+ /**
+ * Create a new empty result with error = UNINITIALIZED.
+ */
+ simdjson_inline simdjson_result_base() noexcept;
+
+ /**
+ * Create a new error result.
+ */
+ simdjson_inline simdjson_result_base(error_code error) noexcept;
+
+ /**
+ * Create a new successful result.
+ */
+ simdjson_inline simdjson_result_base(T &&value) noexcept;
+
+ /**
+ * Create a new result with both things (use if you don't want to branch when creating the result).
+ */
+ simdjson_inline simdjson_result_base(T &&value, error_code error) noexcept;
+
+ /**
+ * Move the value and the error to the provided variables.
+ *
+ * @param value The variable to assign the value to. May not be set if there is an error.
+ * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
+ */
+ simdjson_inline void tie(T &value, error_code &error) && noexcept;
+
+ /**
+ * Move the value to the provided variable.
+ *
+ * @param value The variable to assign the value to. May not be set if there is an error.
+ */
+ simdjson_inline error_code get(T &value) && noexcept;
+
+ /**
+ * The error.
+ */
+ simdjson_inline error_code error() const noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+
+ /**
+ * Get the result value.
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline T& value() & noexcept(false);
+
+ /**
+ * Take the result value (move it).
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline T&& value() && noexcept(false);
+
+ /**
+ * Take the result value (move it).
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline T&& take_value() && noexcept(false);
+
+ /**
+ * Cast to the value (will throw on error).
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline operator T&&() && noexcept(false);
+#endif // SIMDJSON_EXCEPTIONS
+
+ /**
+ * Get the result value. This function is safe if and only
+ * the error() method returns a value that evaluates to false.
+ */
+ simdjson_inline const T& value_unsafe() const& noexcept;
+
+ /**
+ * Take the result value (move it). This function is safe if and only
+ * the error() method returns a value that evaluates to false.
+ */
+ simdjson_inline T&& value_unsafe() && noexcept;
+
+}; // struct simdjson_result_base
+
+} // namespace internal
+
+/**
+ * The result of a simdjson operation that could fail.
+ *
+ * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
+ */
+template
+struct simdjson_result : public internal::simdjson_result_base {
+ /**
+ * @private Create a new empty result with error = UNINITIALIZED.
+ */
+ simdjson_inline simdjson_result() noexcept;
+ /**
+ * @private Create a new successful result.
+ */
+ simdjson_inline simdjson_result(T &&value) noexcept;
+ /**
+ * @private Create a new error result.
+ */
+ simdjson_inline simdjson_result(error_code error_code) noexcept;
+ /**
+ * @private Create a new result with both things (use if you don't want to branch when creating the result).
+ */
+ simdjson_inline simdjson_result(T &&value, error_code error) noexcept;
+
+ /**
+ * Move the value and the error to the provided variables.
+ *
+ * @param value The variable to assign the value to. May not be set if there is an error.
+ * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
+ */
+ simdjson_inline void tie(T &value, error_code &error) && noexcept;
+
+ /**
+ * Move the value to the provided variable.
+ *
+ * @param value The variable to assign the value to. May not be set if there is an error.
+ */
+ simdjson_warn_unused simdjson_inline error_code get(T &value) && noexcept;
+
+ /**
+ * The error.
+ */
+ simdjson_inline error_code error() const noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+
+ /**
+ * Get the result value.
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline T& value() & noexcept(false);
+
+ /**
+ * Take the result value (move it).
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline T&& value() && noexcept(false);
+
+ /**
+ * Take the result value (move it).
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline T&& take_value() && noexcept(false);
+
+ /**
+ * Cast to the value (will throw on error).
+ *
+ * @throw simdjson_error if there was an error.
+ */
+ simdjson_inline operator T&&() && noexcept(false);
+#endif // SIMDJSON_EXCEPTIONS
+
+ /**
+ * Get the result value. This function is safe if and only
+ * the error() method returns a value that evaluates to false.
+ */
+ simdjson_inline const T& value_unsafe() const& noexcept;
+
+ /**
+ * Take the result value (move it). This function is safe if and only
+ * the error() method returns a value that evaluates to false.
+ */
+ simdjson_inline T&& value_unsafe() && noexcept;
+
+}; // struct simdjson_result
+
+#if SIMDJSON_EXCEPTIONS
+
+template
+inline std::ostream& operator<<(std::ostream& out, simdjson_result value) { return out << value.value(); }
+#endif // SIMDJSON_EXCEPTIONS
+
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+/**
+ * @deprecated This is an alias and will be removed, use error_code instead
+ */
+using ErrorValues [[deprecated("This is an alias and will be removed, use error_code instead")]] = error_code;
+
+/**
+ * @deprecated Error codes should be stored and returned as `error_code`, use `error_message()` instead.
+ */
+[[deprecated("Error codes should be stored and returned as `error_code`, use `error_message()` instead.")]]
+inline const std::string error_message(int error) noexcept;
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+} // namespace simdjson
+
+#endif // SIMDJSON_ERROR_H
+/* end file simdjson/error.h */
+/* skipped duplicate #include "simdjson/portability.h" */
+
+/**
+ * @brief The top level simdjson namespace, containing everything the library provides.
+ */
+namespace simdjson {
+
+SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
+
+/** The maximum document size supported by simdjson. */
+constexpr size_t SIMDJSON_MAXSIZE_BYTES = 0xFFFFFFFF;
+
+/**
+ * The amount of padding needed in a buffer to parse JSON.
+ *
+ * The input buf should be readable up to buf + SIMDJSON_PADDING
+ * this is a stopgap; there should be a better description of the
+ * main loop and its behavior that abstracts over this
+ * See https://github.com/simdjson/simdjson/issues/174
+ */
+constexpr size_t SIMDJSON_PADDING = 64;
+
+/**
+ * By default, simdjson supports this many nested objects and arrays.
+ *
+ * This is the default for parser::max_depth().
+ */
+constexpr size_t DEFAULT_MAX_DEPTH = 1024;
+
+SIMDJSON_POP_DISABLE_UNUSED_WARNINGS
+
+class implementation;
+struct padded_string;
+class padded_string_view;
+enum class stage1_mode;
+
+namespace internal {
+
+template
+class atomic_ptr;
+class dom_parser_implementation;
+class escape_json_string;
+class tape_ref;
+struct value128;
+enum class tape_type;
+
+} // namespace internal
+} // namespace simdjson
+
+#endif // SIMDJSON_BASE_H
+/* end file simdjson/base.h */
+
+#endif // SIMDJSON_SRC_BASE_H
+/* end file base.h */
+
+SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
+
+/* including to_chars.cpp: #include */
+/* begin file to_chars.cpp */
+#ifndef SIMDJSON_SRC_TO_CHARS_CPP
+#define SIMDJSON_SRC_TO_CHARS_CPP
+
+/* skipped duplicate #include */
+
+#include
+#include
+#include
+#include
+
+namespace simdjson {
+namespace internal {
+/*!
+implements the Grisu2 algorithm for binary to decimal floating-point
+conversion.
+Adapted from JSON for Modern C++
+
+This implementation is a slightly modified version of the reference
+implementation which may be obtained from
+http://florian.loitsch.com/publications (bench.tar.gz).
+The code is distributed under the MIT license, Copyright (c) 2009 Florian
+Loitsch. For a detailed description of the algorithm see: [1] Loitsch, "Printing
+Floating-Point Numbers Quickly and Accurately with Integers", Proceedings of the
+ACM SIGPLAN 2010 Conference on Programming Language Design and Implementation,
+PLDI 2010 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and
+Accurately", Proceedings of the ACM SIGPLAN 1996 Conference on Programming
+Language Design and Implementation, PLDI 1996
+*/
+namespace dtoa_impl {
+
+template
+Target reinterpret_bits(const Source source) {
+ static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
+
+ Target target;
+ std::memcpy(&target, &source, sizeof(Source));
+ return target;
+}
+
+struct diyfp // f * 2^e
+{
+ static constexpr int kPrecision = 64; // = q
+
+ std::uint64_t f = 0;
+ int e = 0;
+
+ constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
+
+ /*!
+ @brief returns x - y
+ @pre x.e == y.e and x.f >= y.f
+ */
+ static diyfp sub(const diyfp &x, const diyfp &y) noexcept {
+
+ return {x.f - y.f, x.e};
+ }
+
+ /*!
+ @brief returns x * y
+ @note The result is rounded. (Only the upper q bits are returned.)
+ */
+ static diyfp mul(const diyfp &x, const diyfp &y) noexcept {
+ static_assert(kPrecision == 64, "internal error");
+
+ // Computes:
+ // f = round((x.f * y.f) / 2^q)
+ // e = x.e + y.e + q
+
+ // Emulate the 64-bit * 64-bit multiplication:
+ //
+ // p = u * v
+ // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
+ // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) +
+ // 2^64 (u_hi v_hi ) = (p0 ) + 2^32 ((p1 ) + (p2 ))
+ // + 2^64 (p3 ) = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo +
+ // 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) =
+ // (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi +
+ // p2_hi + p3) = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) = (p0_lo ) +
+ // 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
+ //
+ // (Since Q might be larger than 2^32 - 1)
+ //
+ // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
+ //
+ // (Q_hi + H does not overflow a 64-bit int)
+ //
+ // = p_lo + 2^64 p_hi
+
+ const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
+ const std::uint64_t u_hi = x.f >> 32u;
+ const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
+ const std::uint64_t v_hi = y.f >> 32u;
+
+ const std::uint64_t p0 = u_lo * v_lo;
+ const std::uint64_t p1 = u_lo * v_hi;
+ const std::uint64_t p2 = u_hi * v_lo;
+ const std::uint64_t p3 = u_hi * v_hi;
+
+ const std::uint64_t p0_hi = p0 >> 32u;
+ const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
+ const std::uint64_t p1_hi = p1 >> 32u;
+ const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
+ const std::uint64_t p2_hi = p2 >> 32u;
+
+ std::uint64_t Q = p0_hi + p1_lo + p2_lo;
+
+ // The full product might now be computed as
+ //
+ // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
+ // p_lo = p0_lo + (Q << 32)
+ //
+ // But in this particular case here, the full p_lo is not required.
+ // Effectively we only need to add the highest bit in p_lo to p_hi (and
+ // Q_hi + 1 does not overflow).
+
+ Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
+
+ const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
+
+ return {h, x.e + y.e + 64};
+ }
+
+ /*!
+ @brief normalize x such that the significand is >= 2^(q-1)
+ @pre x.f != 0
+ */
+ static diyfp normalize(diyfp x) noexcept {
+
+ while ((x.f >> 63u) == 0) {
+ x.f <<= 1u;
+ x.e--;
+ }
+
+ return x;
+ }
+
+ /*!
+ @brief normalize x such that the result has the exponent E
+ @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
+ */
+ static diyfp normalize_to(const diyfp &x,
+ const int target_exponent) noexcept {
+ const int delta = x.e - target_exponent;
+
+ return {x.f << delta, target_exponent};
+ }
+};
+
+struct boundaries {
+ diyfp w;
+ diyfp minus;
+ diyfp plus;
+};
+
+/*!
+Compute the (normalized) diyfp representing the input number 'value' and its
+boundaries.
+@pre value must be finite and positive
+*/
+template boundaries compute_boundaries(FloatType value) {
+
+ // Convert the IEEE representation into a diyfp.
+ //
+ // If v is denormal:
+ // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
+ // If v is normalized:
+ // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
+
+ static_assert(std::numeric_limits::is_iec559,
+ "internal error: dtoa_short requires an IEEE-754 "
+ "floating-point implementation");
+
+ constexpr int kPrecision =
+ std::numeric_limits::digits; // = p (includes the hidden bit)
+ constexpr int kBias =
+ std::numeric_limits::max_exponent - 1 + (kPrecision - 1);
+ constexpr int kMinExp = 1 - kBias;
+ constexpr std::uint64_t kHiddenBit = std::uint64_t{1}
+ << (kPrecision - 1); // = 2^(p-1)
+
+ using bits_type = typename std::conditional::type;
+
+ const std::uint64_t bits = reinterpret_bits(value);
+ const std::uint64_t E = bits >> (kPrecision - 1);
+ const std::uint64_t F = bits & (kHiddenBit - 1);
+
+ const bool is_denormal = E == 0;
+ const diyfp v = is_denormal
+ ? diyfp(F, kMinExp)
+ : diyfp(F + kHiddenBit, static_cast(E) - kBias);
+
+ // Compute the boundaries m- and m+ of the floating-point value
+ // v = f * 2^e.
+ //
+ // Determine v- and v+, the floating-point predecessor and successor if v,
+ // respectively.
+ //
+ // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
+ // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
+ //
+ // v+ = v + 2^e
+ //
+ // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
+ // between m- and m+ round to v, regardless of how the input rounding
+ // algorithm breaks ties.
+ //
+ // ---+-------------+-------------+-------------+-------------+--- (A)
+ // v- m- v m+ v+
+ //
+ // -----------------+------+------+-------------+-------------+--- (B)
+ // v- m- v m+ v+
+
+ const bool lower_boundary_is_closer = F == 0 && E > 1;
+ const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
+ const diyfp m_minus = lower_boundary_is_closer
+ ? diyfp(4 * v.f - 1, v.e - 2) // (B)
+ : diyfp(2 * v.f - 1, v.e - 1); // (A)
+
+ // Determine the normalized w+ = m+.
+ const diyfp w_plus = diyfp::normalize(m_plus);
+
+ // Determine w- = m- such that e_(w-) = e_(w+).
+ const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
+
+ return {diyfp::normalize(v), w_minus, w_plus};
+}
+
+// Given normalized diyfp w, Grisu needs to find a (normalized) cached
+// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
+// within a certain range [alpha, gamma] (Definition 3.2 from [1])
+//
+// alpha <= e = e_c + e_w + q <= gamma
+//
+// or
+//
+// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
+// <= f_c * f_w * 2^gamma
+//
+// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
+//
+// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
+//
+// or
+//
+// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
+//
+// The choice of (alpha,gamma) determines the size of the table and the form of
+// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
+// in practice:
+//
+// The idea is to cut the number c * w = f * 2^e into two parts, which can be
+// processed independently: An integral part p1, and a fractional part p2:
+//
+// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
+// = (f div 2^-e) + (f mod 2^-e) * 2^e
+// = p1 + p2 * 2^e
+//
+// The conversion of p1 into decimal form requires a series of divisions and
+// modulos by (a power of) 10. These operations are faster for 32-bit than for
+// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
+// achieved by choosing
+//
+// -e >= 32 or e <= -32 := gamma
+//
+// In order to convert the fractional part
+//
+// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
+//
+// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
+// d[-i] are extracted in order:
+//
+// (10 * p2) div 2^-e = d[-1]
+// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
+//
+// The multiplication by 10 must not overflow. It is sufficient to choose
+//
+// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
+//
+// Since p2 = f mod 2^-e < 2^-e,
+//
+// -e <= 60 or e >= -60 := alpha
+
+constexpr int kAlpha = -60;
+constexpr int kGamma = -32;
+
+struct cached_power // c = f * 2^e ~= 10^k
+{
+ std::uint64_t f;
+ int e;
+ int k;
+};
+
+/*!
+For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
+power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
+satisfies (Definition 3.2 from [1])
+ alpha <= e_c + e + q <= gamma.
+*/
+inline cached_power get_cached_power_for_binary_exponent(int e) {
+ // Now
+ //
+ // alpha <= e_c + e + q <= gamma (1)
+ // ==> f_c * 2^alpha <= c * 2^e * 2^q
+ //
+ // and since the c's are normalized, 2^(q-1) <= f_c,
+ //
+ // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
+ // ==> 2^(alpha - e - 1) <= c
+ //
+ // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
+ //
+ // k = ceil( log_10( 2^(alpha - e - 1) ) )
+ // = ceil( (alpha - e - 1) * log_10(2) )
+ //
+ // From the paper:
+ // "In theory the result of the procedure could be wrong since c is rounded,
+ // and the computation itself is approximated [...]. In practice, however,
+ // this simple function is sufficient."
+ //
+ // For IEEE double precision floating-point numbers converted into
+ // normalized diyfp's w = f * 2^e, with q = 64,
+ //
+ // e >= -1022 (min IEEE exponent)
+ // -52 (p - 1)
+ // -52 (p - 1, possibly normalize denormal IEEE numbers)
+ // -11 (normalize the diyfp)
+ // = -1137
+ //
+ // and
+ //
+ // e <= +1023 (max IEEE exponent)
+ // -52 (p - 1)
+ // -11 (normalize the diyfp)
+ // = 960
+ //
+ // This binary exponent range [-1137,960] results in a decimal exponent
+ // range [-307,324]. One does not need to store a cached power for each
+ // k in this range. For each such k it suffices to find a cached power
+ // such that the exponent of the product lies in [alpha,gamma].
+ // This implies that the difference of the decimal exponents of adjacent
+ // table entries must be less than or equal to
+ //
+ // floor( (gamma - alpha) * log_10(2) ) = 8.
+ //
+ // (A smaller distance gamma-alpha would require a larger table.)
+
+ // NB:
+ // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
+
+ constexpr int kCachedPowersMinDecExp = -300;
+ constexpr int kCachedPowersDecStep = 8;
+
+ static constexpr std::array kCachedPowers = {{
+ {0xAB70FE17C79AC6CA, -1060, -300}, {0xFF77B1FCBEBCDC4F, -1034, -292},
+ {0xBE5691EF416BD60C, -1007, -284}, {0x8DD01FAD907FFC3C, -980, -276},
+ {0xD3515C2831559A83, -954, -268}, {0x9D71AC8FADA6C9B5, -927, -260},
+ {0xEA9C227723EE8BCB, -901, -252}, {0xAECC49914078536D, -874, -244},
+ {0x823C12795DB6CE57, -847, -236}, {0xC21094364DFB5637, -821, -228},
+ {0x9096EA6F3848984F, -794, -220}, {0xD77485CB25823AC7, -768, -212},
+ {0xA086CFCD97BF97F4, -741, -204}, {0xEF340A98172AACE5, -715, -196},
+ {0xB23867FB2A35B28E, -688, -188}, {0x84C8D4DFD2C63F3B, -661, -180},
+ {0xC5DD44271AD3CDBA, -635, -172}, {0x936B9FCEBB25C996, -608, -164},
+ {0xDBAC6C247D62A584, -582, -156}, {0xA3AB66580D5FDAF6, -555, -148},
+ {0xF3E2F893DEC3F126, -529, -140}, {0xB5B5ADA8AAFF80B8, -502, -132},
+ {0x87625F056C7C4A8B, -475, -124}, {0xC9BCFF6034C13053, -449, -116},
+ {0x964E858C91BA2655, -422, -108}, {0xDFF9772470297EBD, -396, -100},
+ {0xA6DFBD9FB8E5B88F, -369, -92}, {0xF8A95FCF88747D94, -343, -84},
+ {0xB94470938FA89BCF, -316, -76}, {0x8A08F0F8BF0F156B, -289, -68},
+ {0xCDB02555653131B6, -263, -60}, {0x993FE2C6D07B7FAC, -236, -52},
+ {0xE45C10C42A2B3B06, -210, -44}, {0xAA242499697392D3, -183, -36},
+ {0xFD87B5F28300CA0E, -157, -28}, {0xBCE5086492111AEB, -130, -20},
+ {0x8CBCCC096F5088CC, -103, -12}, {0xD1B71758E219652C, -77, -4},
+ {0x9C40000000000000, -50, 4}, {0xE8D4A51000000000, -24, 12},
+ {0xAD78EBC5AC620000, 3, 20}, {0x813F3978F8940984, 30, 28},
+ {0xC097CE7BC90715B3, 56, 36}, {0x8F7E32CE7BEA5C70, 83, 44},
+ {0xD5D238A4ABE98068, 109, 52}, {0x9F4F2726179A2245, 136, 60},
+ {0xED63A231D4C4FB27, 162, 68}, {0xB0DE65388CC8ADA8, 189, 76},
+ {0x83C7088E1AAB65DB, 216, 84}, {0xC45D1DF942711D9A, 242, 92},
+ {0x924D692CA61BE758, 269, 100}, {0xDA01EE641A708DEA, 295, 108},
+ {0xA26DA3999AEF774A, 322, 116}, {0xF209787BB47D6B85, 348, 124},
+ {0xB454E4A179DD1877, 375, 132}, {0x865B86925B9BC5C2, 402, 140},
+ {0xC83553C5C8965D3D, 428, 148}, {0x952AB45CFA97A0B3, 455, 156},
+ {0xDE469FBD99A05FE3, 481, 164}, {0xA59BC234DB398C25, 508, 172},
+ {0xF6C69A72A3989F5C, 534, 180}, {0xB7DCBF5354E9BECE, 561, 188},
+ {0x88FCF317F22241E2, 588, 196}, {0xCC20CE9BD35C78A5, 614, 204},
+ {0x98165AF37B2153DF, 641, 212}, {0xE2A0B5DC971F303A, 667, 220},
+ {0xA8D9D1535CE3B396, 694, 228}, {0xFB9B7CD9A4A7443C, 720, 236},
+ {0xBB764C4CA7A44410, 747, 244}, {0x8BAB8EEFB6409C1A, 774, 252},
+ {0xD01FEF10A657842C, 800, 260}, {0x9B10A4E5E9913129, 827, 268},
+ {0xE7109BFBA19C0C9D, 853, 276}, {0xAC2820D9623BF429, 880, 284},
+ {0x80444B5E7AA7CF85, 907, 292}, {0xBF21E44003ACDD2D, 933, 300},
+ {0x8E679C2F5E44FF8F, 960, 308}, {0xD433179D9C8CB841, 986, 316},
+ {0x9E19DB92B4E31BA9, 1013, 324},
+ }};
+
+ // This computation gives exactly the same results for k as
+ // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
+ // for |e| <= 1500, but doesn't require floating-point operations.
+ // NB: log_10(2) ~= 78913 / 2^18
+ const int f = kAlpha - e - 1;
+ const int k = (f * 78913) / (1 << 18) + static_cast(f > 0);
+
+ const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) /
+ kCachedPowersDecStep;
+
+ const cached_power cached = kCachedPowers[static_cast(index)];
+
+ return cached;
+}
+
+/*!
+For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
+For n == 0, returns 1 and sets pow10 := 1.
+*/
+inline int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10) {
+ // LCOV_EXCL_START
+ if (n >= 1000000000) {
+ pow10 = 1000000000;
+ return 10;
+ }
+ // LCOV_EXCL_STOP
+ else if (n >= 100000000) {
+ pow10 = 100000000;
+ return 9;
+ } else if (n >= 10000000) {
+ pow10 = 10000000;
+ return 8;
+ } else if (n >= 1000000) {
+ pow10 = 1000000;
+ return 7;
+ } else if (n >= 100000) {
+ pow10 = 100000;
+ return 6;
+ } else if (n >= 10000) {
+ pow10 = 10000;
+ return 5;
+ } else if (n >= 1000) {
+ pow10 = 1000;
+ return 4;
+ } else if (n >= 100) {
+ pow10 = 100;
+ return 3;
+ } else if (n >= 10) {
+ pow10 = 10;
+ return 2;
+ } else {
+ pow10 = 1;
+ return 1;
+ }
+}
+
+inline void grisu2_round(char *buf, int len, std::uint64_t dist,
+ std::uint64_t delta, std::uint64_t rest,
+ std::uint64_t ten_k) {
+
+ // <--------------------------- delta ---->
+ // <---- dist --------->
+ // --------------[------------------+-------------------]--------------
+ // M- w M+
+ //
+ // ten_k
+ // <------>
+ // <---- rest ---->
+ // --------------[------------------+----+--------------]--------------
+ // w V
+ // = buf * 10^k
+ //
+ // ten_k represents a unit-in-the-last-place in the decimal representation
+ // stored in buf.
+ // Decrement buf by ten_k while this takes buf closer to w.
+
+ // The tests are written in this order to avoid overflow in unsigned
+ // integer arithmetic.
+
+ while (rest < dist && delta - rest >= ten_k &&
+ (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) {
+ buf[len - 1]--;
+ rest += ten_k;
+ }
+}
+
+/*!
+Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
+M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
+*/
+inline void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent,
+ diyfp M_minus, diyfp w, diyfp M_plus) {
+ static_assert(kAlpha >= -60, "internal error");
+ static_assert(kGamma <= -32, "internal error");
+
+ // Generates the digits (and the exponent) of a decimal floating-point
+ // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
+ // w, M- and M+ share the same exponent e, which satisfies alpha <= e <=
+ // gamma.
+ //
+ // <--------------------------- delta ---->
+ // <---- dist --------->
+ // --------------[------------------+-------------------]--------------
+ // M- w M+
+ //
+ // Grisu2 generates the digits of M+ from left to right and stops as soon as
+ // V is in [M-,M+].
+
+ std::uint64_t delta =
+ diyfp::sub(M_plus, M_minus)
+ .f; // (significand of (M+ - M-), implicit exponent is e)
+ std::uint64_t dist =
+ diyfp::sub(M_plus, w)
+ .f; // (significand of (M+ - w ), implicit exponent is e)
+
+ // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
+ //
+ // M+ = f * 2^e
+ // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
+ // = ((p1 ) * 2^-e + (p2 )) * 2^e
+ // = p1 + p2 * 2^e
+
+ const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
+
+ auto p1 = static_cast(
+ M_plus.f >>
+ -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
+ std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
+
+ // 1)
+ //
+ // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
+
+ std::uint32_t pow10;
+ const int k = find_largest_pow10(p1, pow10);
+
+ // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
+ //
+ // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
+ // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
+ //
+ // M+ = p1 + p2 * 2^e
+ // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
+ // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
+ // = d[k-1] * 10^(k-1) + ( rest) * 2^e
+ //
+ // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
+ //
+ // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
+ //
+ // but stop as soon as
+ //
+ // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
+
+ int n = k;
+ while (n > 0) {
+ // Invariants:
+ // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
+ // pow10 = 10^(n-1) <= p1 < 10^n
+ //
+ const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
+ const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
+ //
+ // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
+ // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
+ //
+ buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d
+ //
+ // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
+ //
+ p1 = r;
+ n--;
+ //
+ // M+ = buffer * 10^n + (p1 + p2 * 2^e)
+ // pow10 = 10^n
+ //
+
+ // Now check if enough digits have been generated.
+ // Compute
+ //
+ // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
+ //
+ // Note:
+ // Since rest and delta share the same exponent e, it suffices to
+ // compare the significands.
+ const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
+ if (rest <= delta) {
+ // V = buffer * 10^n, with M- <= V <= M+.
+
+ decimal_exponent += n;
+
+ // We may now just stop. But instead look if the buffer could be
+ // decremented to bring V closer to w.
+ //
+ // pow10 = 10^n is now 1 ulp in the decimal representation V.
+ // The rounding procedure works with diyfp's with an implicit
+ // exponent of e.
+ //
+ // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
+ //
+ const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
+ grisu2_round(buffer, length, dist, delta, rest, ten_n);
+
+ return;
+ }
+
+ pow10 /= 10;
+ //
+ // pow10 = 10^(n-1) <= p1 < 10^n
+ // Invariants restored.
+ }
+
+ // 2)
+ //
+ // The digits of the integral part have been generated:
+ //
+ // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
+ // = buffer + p2 * 2^e
+ //
+ // Now generate the digits of the fractional part p2 * 2^e.
+ //
+ // Note:
+ // No decimal point is generated: the exponent is adjusted instead.
+ //
+ // p2 actually represents the fraction
+ //
+ // p2 * 2^e
+ // = p2 / 2^-e
+ // = d[-1] / 10^1 + d[-2] / 10^2 + ...
+ //
+ // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
+ //
+ // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
+ // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
+ //
+ // using
+ //
+ // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
+ // = ( d) * 2^-e + ( r)
+ //
+ // or
+ // 10^m * p2 * 2^e = d + r * 2^e
+ //
+ // i.e.
+ //
+ // M+ = buffer + p2 * 2^e
+ // = buffer + 10^-m * (d + r * 2^e)
+ // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
+ //
+ // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
+
+ int m = 0;
+ for (;;) {
+ // Invariant:
+ // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...)
+ // * 2^e
+ // = buffer * 10^-m + 10^-m * (p2 )
+ // * 2^e = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e =
+ // buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e +
+ // (10*p2 mod 2^-e)) * 2^e
+ //
+ p2 *= 10;
+ const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
+ const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
+ //
+ // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
+ // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
+ // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
+ //
+ buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d
+ //
+ // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
+ //
+ p2 = r;
+ m++;
+ //
+ // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
+ // Invariant restored.
+
+ // Check if enough digits have been generated.
+ //
+ // 10^-m * p2 * 2^e <= delta * 2^e
+ // p2 * 2^e <= 10^m * delta * 2^e
+ // p2 <= 10^m * delta
+ delta *= 10;
+ dist *= 10;
+ if (p2 <= delta) {
+ break;
+ }
+ }
+
+ // V = buffer * 10^-m, with M- <= V <= M+.
+
+ decimal_exponent -= m;
+
+ // 1 ulp in the decimal representation is now 10^-m.
+ // Since delta and dist are now scaled by 10^m, we need to do the
+ // same with ulp in order to keep the units in sync.
+ //
+ // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
+ //
+ const std::uint64_t ten_m = one.f;
+ grisu2_round(buffer, length, dist, delta, p2, ten_m);
+
+ // By construction this algorithm generates the shortest possible decimal
+ // number (Loitsch, Theorem 6.2) which rounds back to w.
+ // For an input number of precision p, at least
+ //
+ // N = 1 + ceil(p * log_10(2))
+ //
+ // decimal digits are sufficient to identify all binary floating-point
+ // numbers (Matula, "In-and-Out conversions").
+ // This implies that the algorithm does not produce more than N decimal
+ // digits.
+ //
+ // N = 17 for p = 53 (IEEE double precision)
+ // N = 9 for p = 24 (IEEE single precision)
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+inline void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus,
+ diyfp v, diyfp m_plus) {
+
+ // --------(-----------------------+-----------------------)-------- (A)
+ // m- v m+
+ //
+ // --------------------(-----------+-----------------------)-------- (B)
+ // m- v m+
+ //
+ // First scale v (and m- and m+) such that the exponent is in the range
+ // [alpha, gamma].
+
+ const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
+
+ const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
+
+ // The exponent of the products is = v.e + c_minus_k.e + q and is in the range
+ // [alpha,gamma]
+ const diyfp w = diyfp::mul(v, c_minus_k);
+ const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
+ const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
+
+ // ----(---+---)---------------(---+---)---------------(---+---)----
+ // w- w w+
+ // = c*m- = c*v = c*m+
+ //
+ // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
+ // w+ are now off by a small amount.
+ // In fact:
+ //
+ // w - v * 10^k < 1 ulp
+ //
+ // To account for this inaccuracy, add resp. subtract 1 ulp.
+ //
+ // --------+---[---------------(---+---)---------------]---+--------
+ // w- M- w M+ w+
+ //
+ // Now any number in [M-, M+] (bounds included) will round to w when input,
+ // regardless of how the input rounding algorithm breaks ties.
+ //
+ // And digit_gen generates the shortest possible such number in [M-, M+].
+ // Note that this does not mean that Grisu2 always generates the shortest
+ // possible number in the interval (m-, m+).
+ const diyfp M_minus(w_minus.f + 1, w_minus.e);
+ const diyfp M_plus(w_plus.f - 1, w_plus.e);
+
+ decimal_exponent = -cached.k; // = -(-k) = k
+
+ grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+template
+void grisu2(char *buf, int &len, int &decimal_exponent, FloatType value) {
+ static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3,
+ "internal error: not enough precision");
+
+ // If the neighbors (and boundaries) of 'value' are always computed for
+ // double-precision numbers, all float's can be recovered using strtod (and
+ // strtof). However, the resulting decimal representations are not exactly
+ // "short".
+ //
+ // The documentation for 'std::to_chars'
+ // (https://en.cppreference.com/w/cpp/utility/to_chars) says "value is
+ // converted to a string as if by std::sprintf in the default ("C") locale"
+ // and since sprintf promotes float's to double's, I think this is exactly
+ // what 'std::to_chars' does. On the other hand, the documentation for
+ // 'std::to_chars' requires that "parsing the representation using the
+ // corresponding std::from_chars function recovers value exactly". That
+ // indicates that single precision floating-point numbers should be recovered
+ // using 'std::strtof'.
+ //
+ // NB: If the neighbors are computed for single-precision numbers, there is a
+ // single float
+ // (7.0385307e-26f) which can't be recovered using strtod. The resulting
+ // double precision value is off by 1 ulp.
+#if 0
+ const boundaries w = compute_boundaries(static_cast(value));
+#else
+ const boundaries w = compute_boundaries(value);
+#endif
+
+ grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
+}
+
+/*!
+@brief appends a decimal representation of e to buf
+@return a pointer to the element following the exponent.
+@pre -1000 < e < 1000
+*/
+inline char *append_exponent(char *buf, int e) {
+
+ if (e < 0) {
+ e = -e;
+ *buf++ = '-';
+ } else {
+ *buf++ = '+';
+ }
+
+ auto k = static_cast(e);
+ if (k < 10) {
+ // Always print at least two digits in the exponent.
+ // This is for compatibility with printf("%g").
+ *buf++ = '0';
+ *buf++ = static_cast('0' + k);
+ } else if (k < 100) {
+ *buf++ = static_cast('0' + k / 10);
+ k %= 10;
+ *buf++ = static_cast('0' + k);
+ } else {
+ *buf++ = static_cast('0' + k / 100);
+ k %= 100;
+ *buf++ = static_cast('0' + k / 10);
+ k %= 10;
+ *buf++ = static_cast('0' + k);
+ }
+
+ return buf;
+}
+
+/*!
+@brief prettify v = buf * 10^decimal_exponent
+If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
+notation. Otherwise it will be printed in exponential notation.
+@pre min_exp < 0
+@pre max_exp > 0
+*/
+inline char *format_buffer(char *buf, int len, int decimal_exponent,
+ int min_exp, int max_exp) {
+
+ const int k = len;
+ const int n = len + decimal_exponent;
+
+ // v = buf * 10^(n-k)
+ // k is the length of the buffer (number of decimal digits)
+ // n is the position of the decimal point relative to the start of the buffer.
+
+ if (k <= n && n <= max_exp) {
+ // digits[000]
+ // len <= max_exp + 2
+
+ std::memset(buf + k, '0', static_cast(n) - static_cast(k));
+ // Make it look like a floating-point number (#362, #378)
+ buf[n + 0] = '.';
+ buf[n + 1] = '0';
+ return buf + (static_cast(n)) + 2;
+ }
+
+ if (0 < n && n <= max_exp) {
+ // dig.its
+ // len <= max_digits10 + 1
+ std::memmove(buf + (static_cast(n) + 1), buf + n,
+ static_cast(k) - static_cast(n));
+ buf[n] = '.';
+ return buf + (static_cast(k) + 1U);
+ }
+
+ if (min_exp < n && n <= 0) {
+ // 0.[000]digits
+ // len <= 2 + (-min_exp - 1) + max_digits10
+
+ std::memmove(buf + (2 + static_cast(-n)), buf,
+ static_cast(k));
+ buf[0] = '0';
+ buf[1] = '.';
+ std::memset(buf + 2, '0', static_cast(-n));
+ return buf + (2U + static_cast(-n) + static_cast(k));
+ }
+
+ if (k == 1) {
+ // dE+123
+ // len <= 1 + 5
+
+ buf += 1;
+ } else {
+ // d.igitsE+123
+ // len <= max_digits10 + 1 + 5
+
+ std::memmove(buf + 2, buf + 1, static_cast(k) - 1);
+ buf[1] = '.';
+ buf += 1 + static_cast(k);
+ }
+
+ *buf++ = 'e';
+ return append_exponent(buf, n - 1);
+}
+
+} // namespace dtoa_impl
+
+/*!
+The format of the resulting decimal representation is similar to printf's %g
+format. Returns an iterator pointing past-the-end of the decimal representation.
+@note The input number must be finite, i.e. NaN's and Inf's are not supported.
+@note The buffer must be large enough.
+@note The result is NOT null-terminated.
+*/
+char *to_chars(char *first, const char *last, double value) {
+ static_cast(last); // maybe unused - fix warning
+ bool negative = std::signbit(value);
+ if (negative) {
+ value = -value;
+ *first++ = '-';
+ }
+
+ if (value == 0) // +-0
+ {
+ *first++ = '0';
+ // Make it look like a floating-point number (#362, #378)
+ *first++ = '.';
+ *first++ = '0';
+ return first;
+ }
+ // Compute v = buffer * 10^decimal_exponent.
+ // The decimal digits are stored in the buffer, which needs to be interpreted
+ // as an unsigned decimal integer.
+ // len is the length of the buffer, i.e. the number of decimal digits.
+ int len = 0;
+ int decimal_exponent = 0;
+ dtoa_impl::grisu2(first, len, decimal_exponent, value);
+ // Format the buffer like printf("%.*g", prec, value)
+ constexpr int kMinExp = -4;
+ constexpr int kMaxExp = std::numeric_limits::digits10;
+
+ return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp,
+ kMaxExp);
+}
+} // namespace internal
+} // namespace simdjson
+
+#endif // SIMDJSON_SRC_TO_CHARS_CPP
+/* end file to_chars.cpp */
+/* including from_chars.cpp: #include */
+/* begin file from_chars.cpp */
+#ifndef SIMDJSON_SRC_FROM_CHARS_CPP
+#define SIMDJSON_SRC_FROM_CHARS_CPP
+
+/* skipped duplicate #include */
+
+#include
+#include
+#include
+
+namespace simdjson {
+namespace internal {
+
+/**
+ * The code in the internal::from_chars function is meant to handle the floating-point number parsing
+ * when we have more than 19 digits in the decimal mantissa. This should only be seen
+ * in adversarial scenarios: we do not expect production systems to even produce
+ * such floating-point numbers.
+ *
+ * The parser is based on work by Nigel Tao (at https://github.com/google/wuffs/)
+ * who credits Ken Thompson for the design (via a reference to the Go source
+ * code). See
+ * https://github.com/google/wuffs/blob/aa46859ea40c72516deffa1b146121952d6dfd3b/internal/cgen/base/floatconv-submodule-data.c
+ * https://github.com/google/wuffs/blob/46cd8105f47ca07ae2ba8e6a7818ef9c0df6c152/internal/cgen/base/floatconv-submodule-code.c
+ * It is probably not very fast but it is a fallback that should almost never be
+ * called in real life. Google Wuffs is published under APL 2.0.
+ **/
+
+namespace {
+constexpr uint32_t max_digits = 768;
+constexpr int32_t decimal_point_range = 2047;
+} // namespace
+
+struct adjusted_mantissa {
+ uint64_t mantissa;
+ int power2;
+ adjusted_mantissa() : mantissa(0), power2(0) {}
+};
+
+struct decimal {
+ uint32_t num_digits;
+ int32_t decimal_point;
+ bool negative;
+ bool truncated;
+ uint8_t digits[max_digits];
+};
+
+template struct binary_format {
+ static constexpr int mantissa_explicit_bits();
+ static constexpr int minimum_exponent();
+ static constexpr int infinite_power();
+ static constexpr int sign_index();
+};
+
+template <> constexpr int binary_format::mantissa_explicit_bits() {
+ return 52;
+}
+
+template <> constexpr int binary_format::minimum_exponent() {
+ return -1023;
+}
+template <> constexpr int binary_format::infinite_power() {
+ return 0x7FF;
+}
+
+template <> constexpr int binary_format::sign_index() { return 63; }
+
+bool is_integer(char c) noexcept { return (c >= '0' && c <= '9'); }
+
+// This should always succeed since it follows a call to parse_number.
+decimal parse_decimal(const char *&p) noexcept {
+ decimal answer;
+ answer.num_digits = 0;
+ answer.decimal_point = 0;
+ answer.truncated = false;
+ answer.negative = (*p == '-');
+ if ((*p == '-') || (*p == '+')) {
+ ++p;
+ }
+
+ while (*p == '0') {
+ ++p;
+ }
+ while (is_integer(*p)) {
+ if (answer.num_digits < max_digits) {
+ answer.digits[answer.num_digits] = uint8_t(*p - '0');
+ }
+ answer.num_digits++;
+ ++p;
+ }
+ if (*p == '.') {
+ ++p;
+ const char *first_after_period = p;
+ // if we have not yet encountered a zero, we have to skip it as well
+ if (answer.num_digits == 0) {
+ // skip zeros
+ while (*p == '0') {
+ ++p;
+ }
+ }
+ while (is_integer(*p)) {
+ if (answer.num_digits < max_digits) {
+ answer.digits[answer.num_digits] = uint8_t(*p - '0');
+ }
+ answer.num_digits++;
+ ++p;
+ }
+ answer.decimal_point = int32_t(first_after_period - p);
+ }
+ if(answer.num_digits > 0) {
+ const char *preverse = p - 1;
+ int32_t trailing_zeros = 0;
+ while ((*preverse == '0') || (*preverse == '.')) {
+ if(*preverse == '0') { trailing_zeros++; };
+ --preverse;
+ }
+ answer.decimal_point += int32_t(answer.num_digits);
+ answer.num_digits -= uint32_t(trailing_zeros);
+ }
+ if(answer.num_digits > max_digits ) {
+ answer.num_digits = max_digits;
+ answer.truncated = true;
+ }
+ if (('e' == *p) || ('E' == *p)) {
+ ++p;
+ bool neg_exp = false;
+ if ('-' == *p) {
+ neg_exp = true;
+ ++p;
+ } else if ('+' == *p) {
+ ++p;
+ }
+ int32_t exp_number = 0; // exponential part
+ while (is_integer(*p)) {
+ uint8_t digit = uint8_t(*p - '0');
+ if (exp_number < 0x10000) {
+ exp_number = 10 * exp_number + digit;
+ }
+ ++p;
+ }
+ answer.decimal_point += (neg_exp ? -exp_number : exp_number);
+ }
+ return answer;
+}
+
+// This should always succeed since it follows a call to parse_number.
+// Will not read at or beyond the "end" pointer.
+decimal parse_decimal(const char *&p, const char * end) noexcept {
+ decimal answer;
+ answer.num_digits = 0;
+ answer.decimal_point = 0;
+ answer.truncated = false;
+ if(p == end) { return answer; } // should never happen
+ answer.negative = (*p == '-');
+ if ((*p == '-') || (*p == '+')) {
+ ++p;
+ }
+
+ while ((p != end) && (*p == '0')) {
+ ++p;
+ }
+ while ((p != end) && is_integer(*p)) {
+ if (answer.num_digits < max_digits) {
+ answer.digits[answer.num_digits] = uint8_t(*p - '0');
+ }
+ answer.num_digits++;
+ ++p;
+ }
+ if ((p != end) && (*p == '.')) {
+ ++p;
+ if(p == end) { return answer; } // should never happen
+ const char *first_after_period = p;
+ // if we have not yet encountered a zero, we have to skip it as well
+ if (answer.num_digits == 0) {
+ // skip zeros
+ while (*p == '0') {
+ ++p;
+ }
+ }
+ while ((p != end) && is_integer(*p)) {
+ if (answer.num_digits < max_digits) {
+ answer.digits[answer.num_digits] = uint8_t(*p - '0');
+ }
+ answer.num_digits++;
+ ++p;
+ }
+ answer.decimal_point = int32_t(first_after_period - p);
+ }
+ if(answer.num_digits > 0) {
+ const char *preverse = p - 1;
+ int32_t trailing_zeros = 0;
+ while ((*preverse == '0') || (*preverse == '.')) {
+ if(*preverse == '0') { trailing_zeros++; };
+ --preverse;
+ }
+ answer.decimal_point += int32_t(answer.num_digits);
+ answer.num_digits -= uint32_t(trailing_zeros);
+ }
+ if(answer.num_digits > max_digits ) {
+ answer.num_digits = max_digits;
+ answer.truncated = true;
+ }
+ if ((p != end) && (('e' == *p) || ('E' == *p))) {
+ ++p;
+ if(p == end) { return answer; } // should never happen
+ bool neg_exp = false;
+ if ('-' == *p) {
+ neg_exp = true;
+ ++p;
+ } else if ('+' == *p) {
+ ++p;
+ }
+ int32_t exp_number = 0; // exponential part
+ while ((p != end) && is_integer(*p)) {
+ uint8_t digit = uint8_t(*p - '0');
+ if (exp_number < 0x10000) {
+ exp_number = 10 * exp_number + digit;
+ }
+ ++p;
+ }
+ answer.decimal_point += (neg_exp ? -exp_number : exp_number);
+ }
+ return answer;
+}
+
+namespace {
+
+// remove all final zeroes
+inline void trim(decimal &h) {
+ while ((h.num_digits > 0) && (h.digits[h.num_digits - 1] == 0)) {
+ h.num_digits--;
+ }
+}
+
+uint32_t number_of_digits_decimal_left_shift(decimal &h, uint32_t shift) {
+ shift &= 63;
+ const static uint16_t number_of_digits_decimal_left_shift_table[65] = {
+ 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817,
+ 0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067,
+ 0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF,
+ 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0,
+ 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA,
+ 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC,
+ 0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C,
+ 0x051C, 0x051C,
+ };
+ uint32_t x_a = number_of_digits_decimal_left_shift_table[shift];
+ uint32_t x_b = number_of_digits_decimal_left_shift_table[shift + 1];
+ uint32_t num_new_digits = x_a >> 11;
+ uint32_t pow5_a = 0x7FF & x_a;
+ uint32_t pow5_b = 0x7FF & x_b;
+ const static uint8_t
+ number_of_digits_decimal_left_shift_table_powers_of_5[0x051C] = {
+ 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5,
+ 3, 9, 0, 6, 2, 5, 1, 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8,
+ 2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, 1, 2, 2, 0, 7, 0, 3, 1, 2,
+ 5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, 5, 1,
+ 5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5,
+ 3, 8, 1, 4, 6, 9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2,
+ 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1, 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3,
+ 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9, 1, 0, 1, 5,
+ 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6,
+ 0, 4, 6, 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3,
+ 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7,
+ 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, 3, 8, 2, 8, 1, 2,
+ 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8,
+ 6, 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3,
+ 2, 2, 5, 7, 4, 6, 1, 5, 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1,
+ 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, 5, 2, 3, 2, 8, 3, 0, 6,
+ 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, 3,
+ 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6,
+ 6, 0, 9, 1, 3, 4, 6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3,
+ 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, 1, 3, 2, 8, 1, 2, 5, 1, 4, 5,
+ 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0, 6, 2, 5,
+ 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3,
+ 1, 2, 5, 3, 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6,
+ 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6,
+ 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, 7, 0, 1, 7, 7,
+ 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7,
+ 3, 5, 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5,
+ 2, 2, 7, 3, 7, 3, 6, 7, 5, 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5,
+ 9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, 7, 2, 1, 6, 1, 6, 0,
+ 2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8,
+ 8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5,
+ 2, 8, 4, 2, 1, 7, 0, 9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4,
+ 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0, 8, 5, 4, 7, 1, 5, 2, 0, 2,
+ 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1, 0, 5,
+ 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7,
+ 5, 7, 8, 1, 2, 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9,
+ 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5,
+ 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, 6, 6, 8, 9,
+ 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3,
+ 2, 3, 3, 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8,
+ 9, 2, 0, 9, 8, 5, 0, 0, 6, 2, 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2,
+ 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, 9, 2, 5, 0, 3, 1,
+ 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1,
+ 1, 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3,
+ 1, 6, 6, 8, 0, 9, 0, 8, 2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2,
+ 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, 8, 3, 4, 0, 4, 5, 4, 1,
+ 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1, 3,
+ 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1,
+ 3, 8, 7, 7, 7, 8, 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3,
+ 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, 6, 2, 5, 6, 9, 3, 8, 8, 9, 3,
+ 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, 5, 5, 6,
+ 7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3,
+ 6, 1, 4, 1, 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7,
+ 6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2, 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9,
+ 4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, 8, 2, 8, 1, 2,
+ 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9,
+ 6, 2, 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5,
+ };
+ const uint8_t *pow5 =
+ &number_of_digits_decimal_left_shift_table_powers_of_5[pow5_a];
+ uint32_t i = 0;
+ uint32_t n = pow5_b - pow5_a;
+ for (; i < n; i++) {
+ if (i >= h.num_digits) {
+ return num_new_digits - 1;
+ } else if (h.digits[i] == pow5[i]) {
+ continue;
+ } else if (h.digits[i] < pow5[i]) {
+ return num_new_digits - 1;
+ } else {
+ return num_new_digits;
+ }
+ }
+ return num_new_digits;
+}
+
+} // end of anonymous namespace
+
+uint64_t round(decimal &h) {
+ if ((h.num_digits == 0) || (h.decimal_point < 0)) {
+ return 0;
+ } else if (h.decimal_point > 18) {
+ return UINT64_MAX;
+ }
+ // at this point, we know that h.decimal_point >= 0
+ uint32_t dp = uint32_t(h.decimal_point);
+ uint64_t n = 0;
+ for (uint32_t i = 0; i < dp; i++) {
+ n = (10 * n) + ((i < h.num_digits) ? h.digits[i] : 0);
+ }
+ bool round_up = false;
+ if (dp < h.num_digits) {
+ round_up = h.digits[dp] >= 5; // normally, we round up
+ // but we may need to round to even!
+ if ((h.digits[dp] == 5) && (dp + 1 == h.num_digits)) {
+ round_up = h.truncated || ((dp > 0) && (1 & h.digits[dp - 1]));
+ }
+ }
+ if (round_up) {
+ n++;
+ }
+ return n;
+}
+
+// computes h * 2^-shift
+void decimal_left_shift(decimal &h, uint32_t shift) {
+ if (h.num_digits == 0) {
+ return;
+ }
+ uint32_t num_new_digits = number_of_digits_decimal_left_shift(h, shift);
+ int32_t read_index = int32_t(h.num_digits - 1);
+ uint32_t write_index = h.num_digits - 1 + num_new_digits;
+ uint64_t n = 0;
+
+ while (read_index >= 0) {
+ n += uint64_t(h.digits[read_index]) << shift;
+ uint64_t quotient = n / 10;
+ uint64_t remainder = n - (10 * quotient);
+ if (write_index < max_digits) {
+ h.digits[write_index] = uint8_t(remainder);
+ } else if (remainder > 0) {
+ h.truncated = true;
+ }
+ n = quotient;
+ write_index--;
+ read_index--;
+ }
+ while (n > 0) {
+ uint64_t quotient = n / 10;
+ uint64_t remainder = n - (10 * quotient);
+ if (write_index < max_digits) {
+ h.digits[write_index] = uint8_t(remainder);
+ } else if (remainder > 0) {
+ h.truncated = true;
+ }
+ n = quotient;
+ write_index--;
+ }
+ h.num_digits += num_new_digits;
+ if (h.num_digits > max_digits) {
+ h.num_digits = max_digits;
+ }
+ h.decimal_point += int32_t(num_new_digits);
+ trim(h);
+}
+
+// computes h * 2^shift
+void decimal_right_shift(decimal &h, uint32_t shift) {
+ uint32_t read_index = 0;
+ uint32_t write_index = 0;
+
+ uint64_t n = 0;
+
+ while ((n >> shift) == 0) {
+ if (read_index < h.num_digits) {
+ n = (10 * n) + h.digits[read_index++];
+ } else if (n == 0) {
+ return;
+ } else {
+ while ((n >> shift) == 0) {
+ n = 10 * n;
+ read_index++;
+ }
+ break;
+ }
+ }
+ h.decimal_point -= int32_t(read_index - 1);
+ if (h.decimal_point < -decimal_point_range) { // it is zero
+ h.num_digits = 0;
+ h.decimal_point = 0;
+ h.negative = false;
+ h.truncated = false;
+ return;
+ }
+ uint64_t mask = (uint64_t(1) << shift) - 1;
+ while (read_index < h.num_digits) {
+ uint8_t new_digit = uint8_t(n >> shift);
+ n = (10 * (n & mask)) + h.digits[read_index++];
+ h.digits[write_index++] = new_digit;
+ }
+ while (n > 0) {
+ uint8_t new_digit = uint8_t(n >> shift);
+ n = 10 * (n & mask);
+ if (write_index < max_digits) {
+ h.digits[write_index++] = new_digit;
+ } else if (new_digit > 0) {
+ h.truncated = true;
+ }
+ }
+ h.num_digits = write_index;
+ trim(h);
+}
+
+template adjusted_mantissa compute_float(decimal &d) {
+ adjusted_mantissa answer;
+ if (d.num_digits == 0) {
+ // should be zero
+ answer.power2 = 0;
+ answer.mantissa = 0;
+ return answer;
+ }
+ // At this point, going further, we can assume that d.num_digits > 0.
+ // We want to guard against excessive decimal point values because
+ // they can result in long running times. Indeed, we do
+ // shifts by at most 60 bits. We have that log(10**400)/log(2**60) ~= 22
+ // which is fine, but log(10**299995)/log(2**60) ~= 16609 which is not
+ // fine (runs for a long time).
+ //
+ if(d.decimal_point < -324) {
+ // We have something smaller than 1e-324 which is always zero
+ // in binary64 and binary32.
+ // It should be zero.
+ answer.power2 = 0;
+ answer.mantissa = 0;
+ return answer;
+ } else if(d.decimal_point >= 310) {
+ // We have something at least as large as 0.1e310 which is
+ // always infinite.
+ answer.power2 = binary::infinite_power();
+ answer.mantissa = 0;
+ return answer;
+ }
+
+ static const uint32_t max_shift = 60;
+ static const uint32_t num_powers = 19;
+ static const uint8_t powers[19] = {
+ 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, //
+ 33, 36, 39, 43, 46, 49, 53, 56, 59, //
+ };
+ int32_t exp2 = 0;
+ while (d.decimal_point > 0) {
+ uint32_t n = uint32_t(d.decimal_point);
+ uint32_t shift = (n < num_powers) ? powers[n] : max_shift;
+ decimal_right_shift(d, shift);
+ if (d.decimal_point < -decimal_point_range) {
+ // should be zero
+ answer.power2 = 0;
+ answer.mantissa = 0;
+ return answer;
+ }
+ exp2 += int32_t(shift);
+ }
+ // We shift left toward [1/2 ... 1].
+ while (d.decimal_point <= 0) {
+ uint32_t shift;
+ if (d.decimal_point == 0) {
+ if (d.digits[0] >= 5) {
+ break;
+ }
+ shift = (d.digits[0] < 2) ? 2 : 1;
+ } else {
+ uint32_t n = uint32_t(-d.decimal_point);
+ shift = (n < num_powers) ? powers[n] : max_shift;
+ }
+ decimal_left_shift(d, shift);
+ if (d.decimal_point > decimal_point_range) {
+ // we want to get infinity:
+ answer.power2 = 0xFF;
+ answer.mantissa = 0;
+ return answer;
+ }
+ exp2 -= int32_t(shift);
+ }
+ // We are now in the range [1/2 ... 1] but the binary format uses [1 ... 2].
+ exp2--;
+ constexpr int32_t minimum_exponent = binary::minimum_exponent();
+ while ((minimum_exponent + 1) > exp2) {
+ uint32_t n = uint32_t((minimum_exponent + 1) - exp2);
+ if (n > max_shift) {
+ n = max_shift;
+ }
+ decimal_right_shift(d, n);
+ exp2 += int32_t(n);
+ }
+ if ((exp2 - minimum_exponent) >= binary::infinite_power()) {
+ answer.power2 = binary::infinite_power();
+ answer.mantissa = 0;
+ return answer;
+ }
+
+ const int mantissa_size_in_bits = binary::mantissa_explicit_bits() + 1;
+ decimal_left_shift(d, mantissa_size_in_bits);
+
+ uint64_t mantissa = round(d);
+ // It is possible that we have an overflow, in which case we need
+ // to shift back.
+ if (mantissa >= (uint64_t(1) << mantissa_size_in_bits)) {
+ decimal_right_shift(d, 1);
+ exp2 += 1;
+ mantissa = round(d);
+ if ((exp2 - minimum_exponent) >= binary::infinite_power()) {
+ answer.power2 = binary::infinite_power();
+ answer.mantissa = 0;
+ return answer;
+ }
+ }
+ answer.power2 = exp2 - binary::minimum_exponent();
+ if (mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) {
+ answer.power2--;
+ }
+ answer.mantissa =
+ mantissa & ((uint64_t(1) << binary::mantissa_explicit_bits()) - 1);
+ return answer;
+}
+
+template
+adjusted_mantissa parse_long_mantissa(const char *first) {
+ decimal d = parse_decimal(first);
+ return compute_float(d);
+}
+
+template
+adjusted_mantissa parse_long_mantissa(const char *first, const char *end) {
+ decimal d = parse_decimal(first, end);
+ return compute_float(d);
+}
+
+double from_chars(const char *first) noexcept {
+ bool negative = first[0] == '-';
+ if (negative) {
+ first++;
+ }
+ adjusted_mantissa am = parse_long_mantissa>(first);
+ uint64_t word = am.mantissa;
+ word |= uint64_t(am.power2)
+ << binary_format::mantissa_explicit_bits();
+ word = negative ? word | (uint64_t(1) << binary_format::sign_index())
+ : word;
+ double value;
+ std::memcpy(&value, &word, sizeof(double));
+ return value;
+}
+
+
+double from_chars(const char *first, const char *end) noexcept {
+ bool negative = first[0] == '-';
+ if (negative) {
+ first++;
+ }
+ adjusted_mantissa am = parse_long_mantissa>(first, end);
+ uint64_t word = am.mantissa;
+ word |= uint64_t(am.power2)
+ << binary_format::mantissa_explicit_bits();
+ word = negative ? word | (uint64_t(1) << binary_format::sign_index())
+ : word;
+ double value;
+ std::memcpy(&value, &word, sizeof(double));
+ return value;
+}
+
+} // internal
+} // simdjson
+
+#endif // SIMDJSON_SRC_FROM_CHARS_CPP
+/* end file from_chars.cpp */
+/* including internal/error_tables.cpp: #include */
+/* begin file internal/error_tables.cpp */
+#ifndef SIMDJSON_SRC_ERROR_TABLES_CPP
+#define SIMDJSON_SRC_ERROR_TABLES_CPP
+
+/* including simdjson/internal/jsoncharutils_tables.h: #include */
+/* begin file simdjson/internal/jsoncharutils_tables.h */
+#ifndef SIMDJSON_INTERNAL_JSONCHARUTILS_TABLES_H
+#define SIMDJSON_INTERNAL_JSONCHARUTILS_TABLES_H
+
+/* skipped duplicate #include "simdjson/base.h" */
+
+#ifdef JSON_TEST_STRINGS
+void found_string(const uint8_t *buf, const uint8_t *parsed_begin,
+ const uint8_t *parsed_end);
+void found_bad_string(const uint8_t *buf);
+#endif
+
+namespace simdjson {
+namespace internal {
+// structural chars here are
+// they are { 0x7b } 0x7d : 0x3a [ 0x5b ] 0x5d , 0x2c (and NULL)
+// we are also interested in the four whitespace characters
+// space 0x20, linefeed 0x0a, horizontal tab 0x09 and carriage return 0x0d
+
+extern SIMDJSON_DLLIMPORTEXPORT const bool structural_or_whitespace_negated[256];
+extern SIMDJSON_DLLIMPORTEXPORT const bool structural_or_whitespace[256];
+extern SIMDJSON_DLLIMPORTEXPORT const uint32_t digit_to_val32[886];
+
+} // namespace internal
+} // namespace simdjson
+
+#endif // SIMDJSON_INTERNAL_JSONCHARUTILS_TABLES_H
+/* end file simdjson/internal/jsoncharutils_tables.h */
+/* including simdjson/error-inl.h: #include */
+/* begin file simdjson/error-inl.h */
+#ifndef SIMDJSON_ERROR_INL_H
+#define SIMDJSON_ERROR_INL_H
+
+/* skipped duplicate #include "simdjson/error.h" */
+
+#include
+
+namespace simdjson {
+namespace internal {
+ // We store the error code so we can validate the error message is associated with the right code
+ struct error_code_info {
+ error_code code;
+ const char* message; // do not use a fancy std::string where a simple C string will do (no alloc, no destructor)
+ };
+ // These MUST match the codes in error_code. We check this constraint in basictests.
+ extern SIMDJSON_DLLIMPORTEXPORT const error_code_info error_codes[];
+} // namespace internal
+
+
+inline const char *error_message(error_code error) noexcept {
+ // If you're using error_code, we're trusting you got it from the enum.
+ return internal::error_codes[int(error)].message;
+}
+
+// deprecated function
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+inline const std::string error_message(int error) noexcept {
+ if (error < 0 || error >= error_code::NUM_ERROR_CODES) {
+ return internal::error_codes[UNEXPECTED_ERROR].message;
+ }
+ return internal::error_codes[error].message;
+}
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+
+inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept {
+ return out << error_message(error);
+}
+
+namespace internal {
+
+//
+// internal::simdjson_result_base inline implementation
+//
+
+template
+simdjson_inline void simdjson_result_base::tie(T &value, error_code &error) && noexcept {
+ error = this->second;
+ if (!error) {
+ value = std::forward>(*this).first;
+ }
+}
+
+template
+simdjson_warn_unused simdjson_inline error_code simdjson_result_base::get(T &value) && noexcept {
+ error_code error;
+ std::forward>(*this).tie(value, error);
+ return error;
+}
+
+template
+simdjson_inline error_code simdjson_result_base::error() const noexcept {
+ return this->second;
+}
+
+#if SIMDJSON_EXCEPTIONS
+
+template
+simdjson_inline T& simdjson_result_base::value() & noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return this->first;
+}
+
+template
+simdjson_inline T&& simdjson_result_base::value() && noexcept(false) {
+ return std::forward>(*this).take_value();
+}
+
+template
+simdjson_inline T&& simdjson_result_base::take_value() && noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return std::forward(this->first);
+}
+
+template
+simdjson_inline simdjson_result_base::operator T&&() && noexcept(false) {
+ return std::forward>(*this).take_value();
+}
+
+#endif // SIMDJSON_EXCEPTIONS
+
+template
+simdjson_inline const T& simdjson_result_base::value_unsafe() const& noexcept {
+ return this->first;
+}
+
+template
+simdjson_inline T&& simdjson_result_base::value_unsafe() && noexcept {
+ return std::forward(this->first);
+}
+
+template
+simdjson_inline simdjson_result_base::simdjson_result_base(T &&value, error_code error) noexcept
+ : std::pair(std::forward(value), error) {}
+template
+simdjson_inline simdjson_result_base::simdjson_result_base(error_code error) noexcept
+ : simdjson_result_base(T{}, error) {}
+template
+simdjson_inline simdjson_result_base::simdjson_result_base(T &&value) noexcept
+ : simdjson_result_base(std::forward(value), SUCCESS) {}
+template |