Coverage Report

Created: 2025-07-04 09:33

/src/node/deps/simdjson/simdjson.h
Line
Count
Source (jump to first uncovered line)
1
/* auto-generated on 2024-03-10 13:24:07 -0400. Do not edit! */
2
/* including simdjson.h:  */
3
/* begin file simdjson.h */
4
#ifndef SIMDJSON_H
5
#define SIMDJSON_H
6
7
/**
8
 * @mainpage
9
 *
10
 * Check the [README.md](https://github.com/simdjson/simdjson/blob/master/README.md#simdjson--parsing-gigabytes-of-json-per-second).
11
 *
12
 * Sample code. See https://github.com/simdjson/simdjson/blob/master/doc/basics.md for more examples.
13
14
    #include "simdjson.h"
15
16
    int main(void) {
17
      // load from `twitter.json` file:
18
      simdjson::dom::parser parser;
19
      simdjson::dom::element tweets = parser.load("twitter.json");
20
      std::cout << tweets["search_metadata"]["count"] << " results." << std::endl;
21
22
      // Parse and iterate through an array of objects
23
      auto abstract_json = R"( [
24
        {  "12345" : {"a":12.34, "b":56.78, "c": 9998877}   },
25
        {  "12545" : {"a":11.44, "b":12.78, "c": 11111111}  }
26
        ] )"_padded;
27
28
      for (simdjson::dom::object obj : parser.parse(abstract_json)) {
29
        for(const auto key_value : obj) {
30
          cout << "key: " << key_value.key << " : ";
31
          simdjson::dom::object innerobj = key_value.value;
32
          cout << "a: " << double(innerobj["a"]) << ", ";
33
          cout << "b: " << double(innerobj["b"]) << ", ";
34
          cout << "c: " << int64_t(innerobj["c"]) << endl;
35
        }
36
      }
37
    }
38
 */
39
40
/* including simdjson/common_defs.h: #include "simdjson/common_defs.h" */
41
/* begin file simdjson/common_defs.h */
42
#ifndef SIMDJSON_COMMON_DEFS_H
43
#define SIMDJSON_COMMON_DEFS_H
44
45
#include <cassert>
46
/* including simdjson/compiler_check.h: #include "simdjson/compiler_check.h" */
47
/* begin file simdjson/compiler_check.h */
48
#ifndef SIMDJSON_COMPILER_CHECK_H
49
#define SIMDJSON_COMPILER_CHECK_H
50
51
#ifndef __cplusplus
52
#error simdjson requires a C++ compiler
53
#endif
54
55
#ifndef SIMDJSON_CPLUSPLUS
56
#if defined(_MSVC_LANG) && !defined(__clang__)
57
#define SIMDJSON_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
58
#else
59
#define SIMDJSON_CPLUSPLUS __cplusplus
60
#endif
61
#endif
62
63
// C++ 17
64
#if !defined(SIMDJSON_CPLUSPLUS17) && (SIMDJSON_CPLUSPLUS >= 201703L)
65
#define SIMDJSON_CPLUSPLUS17 1
66
#endif
67
68
// C++ 14
69
#if !defined(SIMDJSON_CPLUSPLUS14) && (SIMDJSON_CPLUSPLUS >= 201402L)
70
#define SIMDJSON_CPLUSPLUS14 1
71
#endif
72
73
// C++ 11
74
#if !defined(SIMDJSON_CPLUSPLUS11) && (SIMDJSON_CPLUSPLUS >= 201103L)
75
#define SIMDJSON_CPLUSPLUS11 1
76
#endif
77
78
#ifndef SIMDJSON_CPLUSPLUS11
79
#error simdjson requires a compiler compliant with the C++11 standard
80
#endif
81
82
#ifndef SIMDJSON_IF_CONSTEXPR
83
#if SIMDJSON_CPLUSPLUS17
84
#define SIMDJSON_IF_CONSTEXPR if constexpr
85
#else
86
#define SIMDJSON_IF_CONSTEXPR if
87
#endif
88
#endif
89
90
#endif // SIMDJSON_COMPILER_CHECK_H
91
/* end file simdjson/compiler_check.h */
92
/* including simdjson/portability.h: #include "simdjson/portability.h" */
93
/* begin file simdjson/portability.h */
94
#ifndef SIMDJSON_PORTABILITY_H
95
#define SIMDJSON_PORTABILITY_H
96
97
#include <cstddef>
98
#include <cstdint>
99
#include <cstdlib>
100
#include <cfloat>
101
#include <cassert>
102
#ifndef _WIN32
103
// strcasecmp, strncasecmp
104
#include <strings.h>
105
#endif
106
107
#ifdef _MSC_VER
108
#define SIMDJSON_VISUAL_STUDIO 1
109
/**
110
 * We want to differentiate carefully between
111
 * clang under visual studio and regular visual
112
 * studio.
113
 *
114
 * Under clang for Windows, we enable:
115
 *  * target pragmas so that part and only part of the
116
 *     code gets compiled for advanced instructions.
117
 *
118
 */
119
#ifdef __clang__
120
// clang under visual studio
121
#define SIMDJSON_CLANG_VISUAL_STUDIO 1
122
#else
123
// just regular visual studio (best guess)
124
#define SIMDJSON_REGULAR_VISUAL_STUDIO 1
125
#endif // __clang__
126
#endif // _MSC_VER
127
128
#if defined(__x86_64__) || defined(_M_AMD64)
129
#define SIMDJSON_IS_X86_64 1
130
#elif defined(__aarch64__) || defined(_M_ARM64)
131
#define SIMDJSON_IS_ARM64 1
132
#elif defined(__riscv) && __riscv_xlen == 64
133
#define SIMDJSON_IS_RISCV64 1
134
#elif defined(__loongarch_lp64)
135
#define SIMDJSON_IS_LOONGARCH64 1
136
#elif defined(__PPC64__) || defined(_M_PPC64)
137
#if defined(__ALTIVEC__)
138
#define SIMDJSON_IS_PPC64_VMX 1
139
#endif // defined(__ALTIVEC__)
140
#else
141
#define SIMDJSON_IS_32BITS 1
142
143
#if defined(_M_IX86) || defined(__i386__)
144
#define SIMDJSON_IS_X86_32BITS 1
145
#elif defined(__arm__) || defined(_M_ARM)
146
#define SIMDJSON_IS_ARM_32BITS 1
147
#elif defined(__PPC__) || defined(_M_PPC)
148
#define SIMDJSON_IS_PPC_32BITS 1
149
#endif
150
151
#endif // defined(__x86_64__) || defined(_M_AMD64)
152
#ifndef SIMDJSON_IS_32BITS
153
#define SIMDJSON_IS_32BITS 0
154
#endif
155
156
#if SIMDJSON_IS_32BITS
157
#ifndef SIMDJSON_NO_PORTABILITY_WARNING
158
// In the future, we should allow programmers
159
// to get warning.
160
#endif // SIMDJSON_NO_PORTABILITY_WARNING
161
#endif // SIMDJSON_IS_32BITS
162
163
#define SIMDJSON_CAT_IMPLEMENTATION_(a,...) a ## __VA_ARGS__
164
#define SIMDJSON_CAT(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
165
166
#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a,...) #a SIMDJSON_STRINGIFY(__VA_ARGS__)
167
#define SIMDJSON_STRINGIFY(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
168
169
// this is almost standard?
170
#undef SIMDJSON_STRINGIFY_IMPLEMENTATION_
171
#undef SIMDJSON_STRINGIFY
172
#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a) #a
173
#define SIMDJSON_STRINGIFY(a) SIMDJSON_STRINGIFY_IMPLEMENTATION_(a)
174
175
// Our fast kernels require 64-bit systems.
176
//
177
// On 32-bit x86, we lack 64-bit popcnt, lzcnt, blsr instructions.
178
// Furthermore, the number of SIMD registers is reduced.
179
//
180
// On 32-bit ARM, we would have smaller registers.
181
//
182
// The simdjson users should still have the fallback kernel. It is
183
// slower, but it should run everywhere.
184
185
//
186
// Enable valid runtime implementations, and select SIMDJSON_BUILTIN_IMPLEMENTATION
187
//
188
189
// We are going to use runtime dispatch.
190
#if SIMDJSON_IS_X86_64
191
#ifdef __clang__
192
// clang does not have GCC push pop
193
// warning: clang attribute push can't be used within a namespace in clang up
194
// til 8.0 so SIMDJSON_TARGET_REGION and SIMDJSON_UNTARGET_REGION must be *outside* of a
195
// namespace.
196
#define SIMDJSON_TARGET_REGION(T)                                                       \
197
  _Pragma(SIMDJSON_STRINGIFY(                                                           \
198
      clang attribute push(__attribute__((target(T))), apply_to = function)))
199
#define SIMDJSON_UNTARGET_REGION _Pragma("clang attribute pop")
200
#elif defined(__GNUC__)
201
// GCC is easier
202
#define SIMDJSON_TARGET_REGION(T)                                                       \
203
  _Pragma("GCC push_options") _Pragma(SIMDJSON_STRINGIFY(GCC target(T)))
204
#define SIMDJSON_UNTARGET_REGION _Pragma("GCC pop_options")
205
#endif // clang then gcc
206
207
#endif // x86
208
209
// Default target region macros don't do anything.
210
#ifndef SIMDJSON_TARGET_REGION
211
#define SIMDJSON_TARGET_REGION(T)
212
#define SIMDJSON_UNTARGET_REGION
213
#endif
214
215
// Is threading enabled?
216
#if defined(_REENTRANT) || defined(_MT)
217
#ifndef SIMDJSON_THREADS_ENABLED
218
#define SIMDJSON_THREADS_ENABLED
219
#endif
220
#endif
221
222
// workaround for large stack sizes under -O0.
223
// https://github.com/simdjson/simdjson/issues/691
224
#ifdef __APPLE__
225
#ifndef __OPTIMIZE__
226
// Apple systems have small stack sizes in secondary threads.
227
// Lack of compiler optimization may generate high stack usage.
228
// Users may want to disable threads for safety, but only when
229
// in debug mode which we detect by the fact that the __OPTIMIZE__
230
// macro is not defined.
231
#undef SIMDJSON_THREADS_ENABLED
232
#endif
233
#endif
234
235
236
#if defined(__clang__)
237
#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
238
#elif defined(__GNUC__)
239
#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
240
#else
241
#define SIMDJSON_NO_SANITIZE_UNDEFINED
242
#endif
243
244
245
#if defined(__clang__) || defined(__GNUC__)
246
#if defined(__has_feature)
247
#  if __has_feature(memory_sanitizer)
248
#define SIMDJSON_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
249
#  endif // if __has_feature(memory_sanitizer)
250
#endif // defined(__has_feature)
251
#endif
252
// make sure it is defined as 'nothing' if it is unapplicable.
253
#ifndef SIMDJSON_NO_SANITIZE_MEMORY
254
#define SIMDJSON_NO_SANITIZE_MEMORY
255
#endif
256
257
#if SIMDJSON_VISUAL_STUDIO
258
// This is one case where we do not distinguish between
259
// regular visual studio and clang under visual studio.
260
// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
261
#define simdjson_strcasecmp _stricmp
262
#define simdjson_strncasecmp _strnicmp
263
#else
264
// The strcasecmp, strncasecmp, and strcasestr functions do not work with multibyte strings (e.g. UTF-8).
265
// So they are only useful for ASCII in our context.
266
// https://www.gnu.org/software/libunistring/manual/libunistring.html#char-_002a-strings
267
#define simdjson_strcasecmp strcasecmp
268
#define simdjson_strncasecmp strncasecmp
269
#endif
270
271
#if defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
272
// If NDEBUG is set, or __OPTIMIZE__ is set, or we are under MSVC in release mode,
273
// then do away with asserts and use __assume.
274
#if SIMDJSON_VISUAL_STUDIO
275
#define SIMDJSON_UNREACHABLE() __assume(0)
276
#define SIMDJSON_ASSUME(COND) __assume(COND)
277
#else
278
#define SIMDJSON_UNREACHABLE() __builtin_unreachable();
279
0
#define SIMDJSON_ASSUME(COND) do { if (!(COND)) __builtin_unreachable(); } while (0)
280
#endif
281
282
#else // defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
283
// This should only ever be enabled in debug mode.
284
#define SIMDJSON_UNREACHABLE() assert(0);
285
#define SIMDJSON_ASSUME(COND) assert(COND)
286
287
#endif
288
289
#endif // SIMDJSON_PORTABILITY_H
290
/* end file simdjson/portability.h */
291
292
namespace simdjson {
293
namespace internal {
294
/**
295
 * @private
296
 * Our own implementation of the C++17 to_chars function.
297
 * Defined in src/to_chars
298
 */
299
char *to_chars(char *first, const char *last, double value);
300
/**
301
 * @private
302
 * A number parsing routine.
303
 * Defined in src/from_chars
304
 */
305
double from_chars(const char *first) noexcept;
306
double from_chars(const char *first, const char* end) noexcept;
307
}
308
309
#ifndef SIMDJSON_EXCEPTIONS
310
#if __cpp_exceptions
311
#define SIMDJSON_EXCEPTIONS 1
312
#else
313
#define SIMDJSON_EXCEPTIONS 0
314
#endif
315
#endif
316
317
} // namespace simdjson
318
319
#if defined(__GNUC__)
320
  // Marks a block with a name so that MCA analysis can see it.
321
  #define SIMDJSON_BEGIN_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-BEGIN " #name);
322
  #define SIMDJSON_END_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-END " #name);
323
  #define SIMDJSON_DEBUG_BLOCK(name, block) BEGIN_DEBUG_BLOCK(name); block; END_DEBUG_BLOCK(name);
324
#else
325
  #define SIMDJSON_BEGIN_DEBUG_BLOCK(name)
326
  #define SIMDJSON_END_DEBUG_BLOCK(name)
327
  #define SIMDJSON_DEBUG_BLOCK(name, block)
328
#endif
329
330
// Align to N-byte boundary
331
0
#define SIMDJSON_ROUNDUP_N(a, n) (((a) + ((n)-1)) & ~((n)-1))
332
#define SIMDJSON_ROUNDDOWN_N(a, n) ((a) & ~((n)-1))
333
334
#define SIMDJSON_ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n)-1)) == 0)
335
336
#if SIMDJSON_REGULAR_VISUAL_STUDIO
337
338
  #define simdjson_really_inline __forceinline
339
  #define simdjson_never_inline __declspec(noinline)
340
341
  #define simdjson_unused
342
  #define simdjson_warn_unused
343
344
  #ifndef simdjson_likely
345
  #define simdjson_likely(x) x
346
  #endif
347
  #ifndef simdjson_unlikely
348
  #define simdjson_unlikely(x) x
349
  #endif
350
351
  #define SIMDJSON_PUSH_DISABLE_WARNINGS __pragma(warning( push ))
352
  #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS __pragma(warning( push, 0 ))
353
  #define SIMDJSON_DISABLE_VS_WARNING(WARNING_NUMBER) __pragma(warning( disable : WARNING_NUMBER ))
354
  // Get rid of Intellisense-only warnings (Code Analysis)
355
  // Though __has_include is C++17, it is supported in Visual Studio 2017 or better (_MSC_VER>=1910).
356
  #ifdef __has_include
357
  #if __has_include(<CppCoreCheck\Warnings.h>)
358
  #include <CppCoreCheck\Warnings.h>
359
  #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS SIMDJSON_DISABLE_VS_WARNING(ALL_CPPCORECHECK_WARNINGS)
360
  #endif
361
  #endif
362
363
  #ifndef SIMDJSON_DISABLE_UNDESIRED_WARNINGS
364
  #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS
365
  #endif
366
367
  #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996)
368
  #define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
369
  #define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop ))
370
371
  #define SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
372
  #define SIMDJSON_POP_DISABLE_UNUSED_WARNINGS
373
374
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
375
376
  #define simdjson_really_inline inline __attribute__((always_inline))
377
  #define simdjson_never_inline inline __attribute__((noinline))
378
379
0
  #define simdjson_unused __attribute__((unused))
380
  #define simdjson_warn_unused __attribute__((warn_unused_result))
381
382
  #ifndef simdjson_likely
383
  #define simdjson_likely(x) __builtin_expect(!!(x), 1)
384
  #endif
385
  #ifndef simdjson_unlikely
386
0
  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
387
  #endif
388
389
  #define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push")
390
  // gcc doesn't seem to disable all warnings with all and extra, add warnings here as necessary
391
  // We do it separately for clang since it has different warnings.
392
  #ifdef __clang__
393
  // clang is missing -Wmaybe-uninitialized.
394
  #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
395
    SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \
396
    SIMDJSON_DISABLE_GCC_WARNING(-Wall) \
397
    SIMDJSON_DISABLE_GCC_WARNING(-Wconversion) \
398
    SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \
399
    SIMDJSON_DISABLE_GCC_WARNING(-Wattributes) \
400
    SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \
401
    SIMDJSON_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \
402
    SIMDJSON_DISABLE_GCC_WARNING(-Wreturn-type) \
403
    SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \
404
    SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \
405
    SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable)
406
  #else // __clang__
407
  #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
408
    SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \
409
    SIMDJSON_DISABLE_GCC_WARNING(-Wall) \
410
    SIMDJSON_DISABLE_GCC_WARNING(-Wconversion) \
411
    SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \
412
    SIMDJSON_DISABLE_GCC_WARNING(-Wattributes) \
413
    SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \
414
    SIMDJSON_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \
415
    SIMDJSON_DISABLE_GCC_WARNING(-Wreturn-type) \
416
    SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \
417
    SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \
418
    SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable) \
419
    SIMDJSON_DISABLE_GCC_WARNING(-Wmaybe-uninitialized) \
420
    SIMDJSON_DISABLE_GCC_WARNING(-Wformat-security)
421
  #endif // __clang__
422
423
  #define SIMDJSON_PRAGMA(P) _Pragma(#P)
424
  #define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING)
425
  #if SIMDJSON_CLANG_VISUAL_STUDIO
426
  #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS SIMDJSON_DISABLE_GCC_WARNING(-Wmicrosoft-include)
427
  #else
428
  #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS
429
  #endif
430
  #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations)
431
  #define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wstrict-overflow)
432
  #define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
433
434
  #define SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
435
    SIMDJSON_DISABLE_GCC_WARNING(-Wunused)
436
  #define SIMDJSON_POP_DISABLE_UNUSED_WARNINGS SIMDJSON_POP_DISABLE_WARNINGS
437
438
439
440
#endif // MSC_VER
441
442
#if defined(simdjson_inline)
443
  // Prefer the user's definition of simdjson_inline; don't define it ourselves.
444
#elif defined(__GNUC__) && !defined(__OPTIMIZE__)
445
  // If optimizations are disabled, forcing inlining can lead to significant
446
  // code bloat and high compile times. Don't use simdjson_really_inline for
447
  // unoptimized builds.
448
  #define simdjson_inline inline
449
#else
450
  // Force inlining for most simdjson functions.
451
  #define simdjson_inline simdjson_really_inline
452
#endif
453
454
#if SIMDJSON_VISUAL_STUDIO
455
    /**
456
     * Windows users need to do some extra work when building
457
     * or using a dynamic library (DLL). When building, we need
458
     * to set SIMDJSON_DLLIMPORTEXPORT to __declspec(dllexport).
459
     * When *using* the DLL, the user needs to set
460
     * SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport).
461
     *
462
     * Static libraries not need require such work.
463
     *
464
     * It does not matter here whether you are using
465
     * the regular visual studio or clang under visual
466
     * studio, you still need to handle these issues.
467
     *
468
     * Non-Windows systems do not have this complexity.
469
     */
470
    #if SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY
471
    // We set SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY when we build a DLL under Windows.
472
    // It should never happen that both SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY and
473
    // SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY are set.
474
    #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport)
475
    #elif SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY
476
    // Windows user who call a dynamic library should set SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY to 1.
477
    #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
478
    #else
479
    // We assume by default static linkage
480
    #define SIMDJSON_DLLIMPORTEXPORT
481
    #endif
482
483
/**
484
 * Workaround for the vcpkg package manager. Only vcpkg should
485
 * ever touch the next line. The SIMDJSON_USING_LIBRARY macro is otherwise unused.
486
 */
487
#if SIMDJSON_USING_LIBRARY
488
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
489
#endif
490
/**
491
 * End of workaround for the vcpkg package manager.
492
 */
493
#else
494
    #define SIMDJSON_DLLIMPORTEXPORT
495
#endif
496
497
// C++17 requires string_view.
498
#if SIMDJSON_CPLUSPLUS17
499
#define SIMDJSON_HAS_STRING_VIEW
500
#include <string_view> // by the standard, this has to be safe.
501
#endif
502
503
// This macro (__cpp_lib_string_view) has to be defined
504
// for C++17 and better, but if it is otherwise defined,
505
// we are going to assume that string_view is available
506
// even if we do not have C++17 support.
507
#ifdef __cpp_lib_string_view
508
#define SIMDJSON_HAS_STRING_VIEW
509
#endif
510
511
// Some systems have string_view even if we do not have C++17 support,
512
// and even if __cpp_lib_string_view is undefined, it is the case
513
// with Apple clang version 11.
514
// We must handle it. *This is important.*
515
#ifndef SIMDJSON_HAS_STRING_VIEW
516
#if defined __has_include
517
// do not combine the next #if with the previous one (unsafe)
518
#if __has_include (<string_view>)
519
// now it is safe to trigger the include
520
#include <string_view> // though the file is there, it does not follow that we got the implementation
521
#if defined(_LIBCPP_STRING_VIEW)
522
// Ah! So we under libc++ which under its Library Fundamentals Technical Specification, which preceded C++17,
523
// included string_view.
524
// This means that we have string_view *even though* we may not have C++17.
525
#define SIMDJSON_HAS_STRING_VIEW
526
#endif // _LIBCPP_STRING_VIEW
527
#endif // __has_include (<string_view>)
528
#endif // defined __has_include
529
#endif // def SIMDJSON_HAS_STRING_VIEW
530
// end of complicated but important routine to try to detect string_view.
531
532
//
533
// Backfill std::string_view using nonstd::string_view on systems where
534
// we expect that string_view is missing. Important: if we get this wrong,
535
// we will end up with two string_view definitions and potential trouble.
536
// That is why we work so hard above to avoid it.
537
//
538
#ifndef SIMDJSON_HAS_STRING_VIEW
539
SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
540
/* including simdjson/nonstd/string_view.hpp: #include "simdjson/nonstd/string_view.hpp" */
541
/* begin file simdjson/nonstd/string_view.hpp */
542
// Copyright 2017-2020 by Martin Moene
543
//
544
// string-view lite, a C++17-like string_view for C++98 and later.
545
// For more information see https://github.com/martinmoene/string-view-lite
546
//
547
// Distributed under the Boost Software License, Version 1.0.
548
// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
549
550
// #pragma once // We remove #pragma once here as it generates a warning in some cases. We rely on the include guard.
551
552
#ifndef NONSTD_SV_LITE_H_INCLUDED
553
#define NONSTD_SV_LITE_H_INCLUDED
554
555
#define string_view_lite_MAJOR  1
556
#define string_view_lite_MINOR  7
557
#define string_view_lite_PATCH  0
558
559
#define string_view_lite_VERSION  nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
560
561
#define nssv_STRINGIFY(  x )  nssv_STRINGIFY_( x )
562
#define nssv_STRINGIFY_( x )  #x
563
564
// string-view lite configuration:
565
566
#define nssv_STRING_VIEW_DEFAULT  0
567
#define nssv_STRING_VIEW_NONSTD   1
568
#define nssv_STRING_VIEW_STD      2
569
570
// tweak header support:
571
572
#ifdef __has_include
573
# if __has_include(<nonstd/string_view.tweak.hpp>)
574
#  include <nonstd/string_view.tweak.hpp>
575
# endif
576
#define nssv_HAVE_TWEAK_HEADER  1
577
#else
578
#define nssv_HAVE_TWEAK_HEADER  0
579
//# pragma message("string_view.hpp: Note: Tweak header not supported.")
580
#endif
581
582
// string_view selection and configuration:
583
584
#if !defined( nssv_CONFIG_SELECT_STRING_VIEW )
585
# define nssv_CONFIG_SELECT_STRING_VIEW  ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )
586
#endif
587
588
#ifndef  nssv_CONFIG_STD_SV_OPERATOR
589
# define nssv_CONFIG_STD_SV_OPERATOR  0
590
#endif
591
592
#ifndef  nssv_CONFIG_USR_SV_OPERATOR
593
# define nssv_CONFIG_USR_SV_OPERATOR  1
594
#endif
595
596
#ifdef   nssv_CONFIG_CONVERSION_STD_STRING
597
# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS   nssv_CONFIG_CONVERSION_STD_STRING
598
# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS  nssv_CONFIG_CONVERSION_STD_STRING
599
#endif
600
601
#ifndef  nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
602
# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS  1
603
#endif
604
605
#ifndef  nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
606
# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS  1
607
#endif
608
609
#ifndef  nssv_CONFIG_NO_STREAM_INSERTION
610
# define nssv_CONFIG_NO_STREAM_INSERTION  0
611
#endif
612
613
#ifndef  nssv_CONFIG_CONSTEXPR11_STD_SEARCH
614
# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH  1
615
#endif
616
617
// Control presence of exception handling (try and auto discover):
618
619
#ifndef nssv_CONFIG_NO_EXCEPTIONS
620
# if defined(_MSC_VER)
621
#  include <cstddef>    // for _HAS_EXCEPTIONS
622
# endif
623
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
624
#  define nssv_CONFIG_NO_EXCEPTIONS  0
625
# else
626
#  define nssv_CONFIG_NO_EXCEPTIONS  1
627
# endif
628
#endif
629
630
// C++ language version detection (C++23 is speculative):
631
// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
632
633
#ifndef   nssv_CPLUSPLUS
634
# if defined(_MSVC_LANG ) && !defined(__clang__)
635
#  define nssv_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
636
# else
637
#  define nssv_CPLUSPLUS  __cplusplus
638
# endif
639
#endif
640
641
#define nssv_CPP98_OR_GREATER  ( nssv_CPLUSPLUS >= 199711L )
642
#define nssv_CPP11_OR_GREATER  ( nssv_CPLUSPLUS >= 201103L )
643
#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L )
644
#define nssv_CPP14_OR_GREATER  ( nssv_CPLUSPLUS >= 201402L )
645
#define nssv_CPP17_OR_GREATER  ( nssv_CPLUSPLUS >= 201703L )
646
#define nssv_CPP20_OR_GREATER  ( nssv_CPLUSPLUS >= 202002L )
647
#define nssv_CPP23_OR_GREATER  ( nssv_CPLUSPLUS >= 202300L )
648
649
// use C++17 std::string_view if available and requested:
650
651
#if nssv_CPP17_OR_GREATER && defined(__has_include )
652
# if __has_include( <string_view> )
653
#  define nssv_HAVE_STD_STRING_VIEW  1
654
# else
655
#  define nssv_HAVE_STD_STRING_VIEW  0
656
# endif
657
#else
658
# define  nssv_HAVE_STD_STRING_VIEW  0
659
#endif
660
661
#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) )
662
663
#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW )
664
#define nssv_HAVE_ENDS_WITH     nssv_HAVE_STARTS_WITH
665
666
//
667
// Use C++17 std::string_view:
668
//
669
670
#if nssv_USES_STD_STRING_VIEW
671
672
#include <string_view>
673
674
// Extensions for std::string:
675
676
#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
677
678
namespace nonstd {
679
680
template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
681
std::basic_string<CharT, Traits, Allocator>
682
to_string( std::basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
683
{
684
    return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
685
}
686
687
template< class CharT, class Traits, class Allocator >
688
std::basic_string_view<CharT, Traits>
689
to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
690
{
691
    return std::basic_string_view<CharT, Traits>( s.data(), s.size() );
692
}
693
694
// Literal operators sv and _sv:
695
696
#if nssv_CONFIG_STD_SV_OPERATOR
697
698
using namespace std::literals::string_view_literals;
699
700
#endif
701
702
#if nssv_CONFIG_USR_SV_OPERATOR
703
704
inline namespace literals {
705
inline namespace string_view_literals {
706
707
708
constexpr std::string_view operator "" _sv( const char* str, size_t len ) noexcept  // (1)
709
{
710
    return std::string_view{ str, len };
711
}
712
713
constexpr std::u16string_view operator "" _sv( const char16_t* str, size_t len ) noexcept  // (2)
714
{
715
    return std::u16string_view{ str, len };
716
}
717
718
constexpr std::u32string_view operator "" _sv( const char32_t* str, size_t len ) noexcept  // (3)
719
{
720
    return std::u32string_view{ str, len };
721
}
722
723
constexpr std::wstring_view operator "" _sv( const wchar_t* str, size_t len ) noexcept  // (4)
724
{
725
    return std::wstring_view{ str, len };
726
}
727
728
}} // namespace literals::string_view_literals
729
730
#endif // nssv_CONFIG_USR_SV_OPERATOR
731
732
} // namespace nonstd
733
734
#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
735
736
namespace nonstd {
737
738
using std::string_view;
739
using std::wstring_view;
740
using std::u16string_view;
741
using std::u32string_view;
742
using std::basic_string_view;
743
744
// literal "sv" and "_sv", see above
745
746
using std::operator==;
747
using std::operator!=;
748
using std::operator<;
749
using std::operator<=;
750
using std::operator>;
751
using std::operator>=;
752
753
using std::operator<<;
754
755
} // namespace nonstd
756
757
#else // nssv_HAVE_STD_STRING_VIEW
758
759
//
760
// Before C++17: use string_view lite:
761
//
762
763
// Compiler versions:
764
//
765
// MSVC++  6.0  _MSC_VER == 1200  nssv_COMPILER_MSVC_VERSION ==  60  (Visual Studio 6.0)
766
// MSVC++  7.0  _MSC_VER == 1300  nssv_COMPILER_MSVC_VERSION ==  70  (Visual Studio .NET 2002)
767
// MSVC++  7.1  _MSC_VER == 1310  nssv_COMPILER_MSVC_VERSION ==  71  (Visual Studio .NET 2003)
768
// MSVC++  8.0  _MSC_VER == 1400  nssv_COMPILER_MSVC_VERSION ==  80  (Visual Studio 2005)
769
// MSVC++  9.0  _MSC_VER == 1500  nssv_COMPILER_MSVC_VERSION ==  90  (Visual Studio 2008)
770
// MSVC++ 10.0  _MSC_VER == 1600  nssv_COMPILER_MSVC_VERSION == 100  (Visual Studio 2010)
771
// MSVC++ 11.0  _MSC_VER == 1700  nssv_COMPILER_MSVC_VERSION == 110  (Visual Studio 2012)
772
// MSVC++ 12.0  _MSC_VER == 1800  nssv_COMPILER_MSVC_VERSION == 120  (Visual Studio 2013)
773
// MSVC++ 14.0  _MSC_VER == 1900  nssv_COMPILER_MSVC_VERSION == 140  (Visual Studio 2015)
774
// MSVC++ 14.1  _MSC_VER >= 1910  nssv_COMPILER_MSVC_VERSION == 141  (Visual Studio 2017)
775
// MSVC++ 14.2  _MSC_VER >= 1920  nssv_COMPILER_MSVC_VERSION == 142  (Visual Studio 2019)
776
777
#if defined(_MSC_VER ) && !defined(__clang__)
778
# define nssv_COMPILER_MSVC_VER      (_MSC_VER )
779
# define nssv_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
780
#else
781
# define nssv_COMPILER_MSVC_VER      0
782
# define nssv_COMPILER_MSVC_VERSION  0
783
#endif
784
785
#define nssv_COMPILER_VERSION( major, minor, patch )  ( 10 * ( 10 * (major) + (minor) ) + (patch) )
786
787
#if defined( __apple_build_version__ )
788
# define nssv_COMPILER_APPLECLANG_VERSION  nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
789
# define nssv_COMPILER_CLANG_VERSION       0
790
#elif defined( __clang__ )
791
# define nssv_COMPILER_APPLECLANG_VERSION  0
792
# define nssv_COMPILER_CLANG_VERSION       nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
793
#else
794
# define nssv_COMPILER_APPLECLANG_VERSION  0
795
# define nssv_COMPILER_CLANG_VERSION       0
796
#endif
797
798
#if defined(__GNUC__) && !defined(__clang__)
799
# define nssv_COMPILER_GNUC_VERSION  nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
800
#else
801
# define nssv_COMPILER_GNUC_VERSION  0
802
#endif
803
804
// half-open range [lo..hi):
805
#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
806
807
// Presence of language and library features:
808
809
#ifdef _HAS_CPP0X
810
# define nssv_HAS_CPP0X  _HAS_CPP0X
811
#else
812
# define nssv_HAS_CPP0X  0
813
#endif
814
815
// Unless defined otherwise below, consider VC14 as C++11 for string-view-lite:
816
817
#if nssv_COMPILER_MSVC_VER >= 1900
818
# undef  nssv_CPP11_OR_GREATER
819
# define nssv_CPP11_OR_GREATER  1
820
#endif
821
822
#define nssv_CPP11_90   (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
823
#define nssv_CPP11_100  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
824
#define nssv_CPP11_110  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
825
#define nssv_CPP11_120  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
826
#define nssv_CPP11_140  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
827
#define nssv_CPP11_141  (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
828
829
#define nssv_CPP14_000  (nssv_CPP14_OR_GREATER)
830
#define nssv_CPP17_000  (nssv_CPP17_OR_GREATER)
831
832
// Presence of C++11 language features:
833
834
#define nssv_HAVE_CONSTEXPR_11          nssv_CPP11_140
835
#define nssv_HAVE_EXPLICIT_CONVERSION   nssv_CPP11_140
836
#define nssv_HAVE_INLINE_NAMESPACE      nssv_CPP11_140
837
#define nssv_HAVE_IS_DEFAULT            nssv_CPP11_140
838
#define nssv_HAVE_IS_DELETE             nssv_CPP11_140
839
#define nssv_HAVE_NOEXCEPT              nssv_CPP11_140
840
#define nssv_HAVE_NULLPTR               nssv_CPP11_100
841
#define nssv_HAVE_REF_QUALIFIER         nssv_CPP11_140
842
#define nssv_HAVE_UNICODE_LITERALS      nssv_CPP11_140
843
#define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
844
#define nssv_HAVE_WCHAR16_T             nssv_CPP11_100
845
#define nssv_HAVE_WCHAR32_T             nssv_CPP11_100
846
847
#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
848
# define nssv_HAVE_STD_DEFINED_LITERALS  nssv_CPP11_140
849
#else
850
# define nssv_HAVE_STD_DEFINED_LITERALS  0
851
#endif
852
853
// Presence of C++14 language features:
854
855
#define nssv_HAVE_CONSTEXPR_14          nssv_CPP14_000
856
857
// Presence of C++17 language features:
858
859
#define nssv_HAVE_NODISCARD             nssv_CPP17_000
860
861
// Presence of C++ library features:
862
863
#define nssv_HAVE_STD_HASH              nssv_CPP11_120
864
865
// Presence of compiler intrinsics:
866
867
// Providing char-type specializations for compare() and length() that
868
// use compiler intrinsics can improve compile- and run-time performance.
869
//
870
// The challenge is in using the right combinations of builtin availability
871
// and its constexpr-ness.
872
//
873
// | compiler | __builtin_memcmp (constexpr) | memcmp  (constexpr) |
874
// |----------|------------------------------|---------------------|
875
// | clang    | 4.0              (>= 4.0   ) | any     (?        ) |
876
// | clang-a  | 9.0              (>= 9.0   ) | any     (?        ) |
877
// | gcc      | any              (constexpr) | any     (?        ) |
878
// | msvc     | >= 14.2 C++17    (>= 14.2  ) | any     (?        ) |
879
880
#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 )
881
#define nssv_HAVE_BUILTIN_CE      (  nssv_HAVE_BUILTIN_VER )
882
883
#define nssv_HAVE_BUILTIN_MEMCMP  ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 )
884
#define nssv_HAVE_BUILTIN_STRLEN  ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 )
885
886
#ifdef __has_builtin
887
# define nssv_HAVE_BUILTIN( x )  __has_builtin( x )
888
#else
889
# define nssv_HAVE_BUILTIN( x )  0
890
#endif
891
892
#if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER
893
# define nssv_BUILTIN_MEMCMP  __builtin_memcmp
894
#else
895
# define nssv_BUILTIN_MEMCMP  memcmp
896
#endif
897
898
#if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER
899
# define nssv_BUILTIN_STRLEN  __builtin_strlen
900
#else
901
# define nssv_BUILTIN_STRLEN  strlen
902
#endif
903
904
// C++ feature usage:
905
906
#if nssv_HAVE_CONSTEXPR_11
907
# define nssv_constexpr  constexpr
908
#else
909
# define nssv_constexpr  /*constexpr*/
910
#endif
911
912
#if  nssv_HAVE_CONSTEXPR_14
913
# define nssv_constexpr14  constexpr
914
#else
915
# define nssv_constexpr14  /*constexpr*/
916
#endif
917
918
#if nssv_HAVE_EXPLICIT_CONVERSION
919
# define nssv_explicit  explicit
920
#else
921
# define nssv_explicit  /*explicit*/
922
#endif
923
924
#if nssv_HAVE_INLINE_NAMESPACE
925
# define nssv_inline_ns  inline
926
#else
927
# define nssv_inline_ns  /*inline*/
928
#endif
929
930
#if nssv_HAVE_NOEXCEPT
931
# define nssv_noexcept  noexcept
932
#else
933
# define nssv_noexcept  /*noexcept*/
934
#endif
935
936
//#if nssv_HAVE_REF_QUALIFIER
937
//# define nssv_ref_qual  &
938
//# define nssv_refref_qual  &&
939
//#else
940
//# define nssv_ref_qual  /*&*/
941
//# define nssv_refref_qual  /*&&*/
942
//#endif
943
944
#if nssv_HAVE_NULLPTR
945
# define nssv_nullptr  nullptr
946
#else
947
# define nssv_nullptr  NULL
948
#endif
949
950
#if nssv_HAVE_NODISCARD
951
# define nssv_nodiscard  [[nodiscard]]
952
#else
953
# define nssv_nodiscard  /*[[nodiscard]]*/
954
#endif
955
956
// Additional includes:
957
958
#include <algorithm>
959
#include <cassert>
960
#include <iterator>
961
#include <limits>
962
#include <string>   // std::char_traits<>
963
964
#if ! nssv_CONFIG_NO_STREAM_INSERTION
965
# include <ostream>
966
#endif
967
968
#if ! nssv_CONFIG_NO_EXCEPTIONS
969
# include <stdexcept>
970
#endif
971
972
#if nssv_CPP11_OR_GREATER
973
# include <type_traits>
974
#endif
975
976
// Clang, GNUC, MSVC warning suppression macros:
977
978
#if defined(__clang__)
979
# pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
980
# pragma clang diagnostic push
981
# pragma clang diagnostic ignored "-Wuser-defined-literals"
982
#elif nssv_COMPILER_GNUC_VERSION >= 480
983
#  pragma  GCC  diagnostic push
984
#  pragma  GCC  diagnostic ignored "-Wliteral-suffix"
985
#endif // __clang__
986
987
#if nssv_COMPILER_MSVC_VERSION >= 140
988
# define nssv_SUPPRESS_MSGSL_WARNING(expr)        [[gsl::suppress(expr)]]
989
# define nssv_SUPPRESS_MSVC_WARNING(code, descr)  __pragma(warning(suppress: code) )
990
# define nssv_DISABLE_MSVC_WARNINGS(codes)        __pragma(warning(push))  __pragma(warning(disable: codes))
991
#else
992
# define nssv_SUPPRESS_MSGSL_WARNING(expr)
993
# define nssv_SUPPRESS_MSVC_WARNING(code, descr)
994
# define nssv_DISABLE_MSVC_WARNINGS(codes)
995
#endif
996
997
#if defined(__clang__)
998
# define nssv_RESTORE_WARNINGS()  _Pragma("clang diagnostic pop")
999
#elif nssv_COMPILER_GNUC_VERSION >= 480
1000
#  define nssv_RESTORE_WARNINGS()  _Pragma("GCC diagnostic pop")
1001
#elif nssv_COMPILER_MSVC_VERSION >= 140
1002
# define nssv_RESTORE_WARNINGS()  __pragma(warning(pop ))
1003
#else
1004
# define nssv_RESTORE_WARNINGS()
1005
#endif
1006
1007
// Suppress the following MSVC (GSL) warnings:
1008
// - C4455, non-gsl   : 'operator ""sv': literal suffix identifiers that do not
1009
//                      start with an underscore are reserved
1010
// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
1011
//                      use brace initialization, gsl::narrow_cast or gsl::narow
1012
// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
1013
1014
nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
1015
//nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
1016
//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
1017
1018
namespace nonstd { namespace sv_lite {
1019
1020
//
1021
// basic_string_view declaration:
1022
//
1023
1024
template
1025
<
1026
    class CharT,
1027
    class Traits = std::char_traits<CharT>
1028
>
1029
class basic_string_view;
1030
1031
namespace detail {
1032
1033
// support constexpr comparison in C++14;
1034
// for C++17 and later, use provided traits:
1035
1036
template< typename CharT >
1037
inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count )
1038
{
1039
    while ( count-- != 0 )
1040
    {
1041
        if ( *s1 < *s2 ) return -1;
1042
        if ( *s1 > *s2 ) return +1;
1043
        ++s1; ++s2;
1044
    }
1045
    return 0;
1046
}
1047
1048
#if nssv_HAVE_BUILTIN_MEMCMP
1049
1050
// specialization of compare() for char, see also generic compare() above:
1051
1052
inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count )
1053
{
1054
    return nssv_BUILTIN_MEMCMP( s1, s2, count );
1055
}
1056
1057
#endif
1058
1059
#if nssv_HAVE_BUILTIN_STRLEN
1060
1061
// specialization of length() for char, see also generic length() further below:
1062
1063
inline nssv_constexpr std::size_t length( char const * s )
1064
{
1065
    return nssv_BUILTIN_STRLEN( s );
1066
}
1067
1068
#endif
1069
1070
#if defined(__OPTIMIZE__)
1071
1072
// gcc, clang provide __OPTIMIZE__
1073
// Expect tail call optimization to make length() non-recursive:
1074
1075
template< typename CharT >
1076
inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 )
1077
{
1078
    return *s == '\0' ? result : length( s + 1, result + 1 );
1079
}
1080
1081
#else // OPTIMIZE
1082
1083
// non-recursive:
1084
1085
template< typename CharT >
1086
inline nssv_constexpr14 std::size_t length( CharT * s )
1087
{
1088
    std::size_t result = 0;
1089
    while ( *s++ != '\0' )
1090
    {
1091
       ++result;
1092
    }
1093
    return result;
1094
}
1095
1096
#endif // OPTIMIZE
1097
1098
#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
1099
#if defined(__OPTIMIZE__)
1100
1101
// gcc, clang provide __OPTIMIZE__
1102
// Expect tail call optimization to make search() non-recursive:
1103
1104
template< class CharT, class Traits = std::char_traits<CharT> >
1105
constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
1106
{
1107
    return haystack.starts_with( needle ) ? haystack.begin() :
1108
        haystack.empty() ? haystack.end() : search( haystack.substr(1), needle );
1109
}
1110
1111
#else // OPTIMIZE
1112
1113
// non-recursive:
1114
1115
#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH
1116
1117
template< class CharT, class Traits = std::char_traits<CharT> >
1118
constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
1119
{
1120
    return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
1121
}
1122
1123
#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
1124
1125
template< class CharT, class Traits = std::char_traits<CharT> >
1126
nssv_constexpr14 const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
1127
{
1128
    while ( needle.size() <= haystack.size() )
1129
    {
1130
        if  ( haystack.starts_with(needle) )
1131
        {
1132
            return haystack.cbegin();
1133
        }
1134
        haystack = basic_string_view<CharT, Traits>{ haystack.begin() + 1, haystack.size() - 1U };
1135
    }
1136
    return haystack.cend();
1137
}
1138
#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
1139
1140
#endif // OPTIMIZE
1141
#endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
1142
1143
} // namespace detail
1144
1145
//
1146
// basic_string_view:
1147
//
1148
1149
template
1150
<
1151
    class CharT,
1152
    class Traits /* = std::char_traits<CharT> */
1153
>
1154
class basic_string_view
1155
{
1156
public:
1157
    // Member types:
1158
1159
    typedef Traits traits_type;
1160
    typedef CharT  value_type;
1161
1162
    typedef CharT       * pointer;
1163
    typedef CharT const * const_pointer;
1164
    typedef CharT       & reference;
1165
    typedef CharT const & const_reference;
1166
1167
    typedef const_pointer iterator;
1168
    typedef const_pointer const_iterator;
1169
    typedef std::reverse_iterator< const_iterator > reverse_iterator;
1170
    typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
1171
1172
    typedef std::size_t     size_type;
1173
    typedef std::ptrdiff_t  difference_type;
1174
1175
    // 24.4.2.1 Construction and assignment:
1176
1177
    nssv_constexpr basic_string_view() nssv_noexcept
1178
        : data_( nssv_nullptr )
1179
        , size_( 0 )
1180
    {}
1181
1182
#if nssv_CPP11_OR_GREATER
1183
    nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default;
1184
#else
1185
    nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept
1186
        : data_( other.data_)
1187
        , size_( other.size_)
1188
    {}
1189
#endif
1190
1191
    nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept
1192
        : data_( s )
1193
        , size_( count )
1194
    {}
1195
1196
    nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept
1197
        : data_( s )
1198
#if nssv_CPP17_OR_GREATER
1199
        , size_( Traits::length(s) )
1200
#elif nssv_CPP11_OR_GREATER
1201
        , size_( detail::length(s) )
1202
#else
1203
        , size_( Traits::length(s) )
1204
#endif
1205
    {}
1206
1207
#if  nssv_HAVE_NULLPTR
1208
# if nssv_HAVE_IS_DELETE
1209
    nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept = delete;
1210
# else
1211
    private: nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept; public:
1212
# endif
1213
#endif
1214
1215
    // Assignment:
1216
1217
#if nssv_CPP11_OR_GREATER
1218
    nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default;
1219
#else
1220
    nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept
1221
    {
1222
        data_ = other.data_;
1223
        size_ = other.size_;
1224
        return *this;
1225
    }
1226
#endif
1227
1228
    // 24.4.2.2 Iterator support:
1229
1230
    nssv_constexpr const_iterator begin()  const nssv_noexcept { return data_;         }
1231
    nssv_constexpr const_iterator end()    const nssv_noexcept { return data_ + size_; }
1232
1233
    nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }
1234
    nssv_constexpr const_iterator cend()   const nssv_noexcept { return end();   }
1235
1236
    nssv_constexpr const_reverse_iterator rbegin()  const nssv_noexcept { return const_reverse_iterator( end() );   }
1237
    nssv_constexpr const_reverse_iterator rend()    const nssv_noexcept { return const_reverse_iterator( begin() ); }
1238
1239
    nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }
1240
    nssv_constexpr const_reverse_iterator crend()   const nssv_noexcept { return rend();   }
1241
1242
    // 24.4.2.3 Capacity:
1243
1244
    nssv_constexpr size_type size()     const nssv_noexcept { return size_; }
1245
    nssv_constexpr size_type length()   const nssv_noexcept { return size_; }
1246
    nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); }
1247
1248
    // since C++20
1249
    nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept
1250
    {
1251
        return 0 == size_;
1252
    }
1253
1254
    // 24.4.2.4 Element access:
1255
1256
    nssv_constexpr const_reference operator[]( size_type pos ) const
1257
    {
1258
        return data_at( pos );
1259
    }
1260
1261
    nssv_constexpr14 const_reference at( size_type pos ) const
1262
    {
1263
#if nssv_CONFIG_NO_EXCEPTIONS
1264
        assert( pos < size() );
1265
#else
1266
        if ( pos >= size() )
1267
        {
1268
            throw std::out_of_range("nonstd::string_view::at()");
1269
        }
1270
#endif
1271
        return data_at( pos );
1272
    }
1273
1274
    nssv_constexpr const_reference front() const { return data_at( 0 );          }
1275
    nssv_constexpr const_reference back()  const { return data_at( size() - 1 ); }
1276
1277
    nssv_constexpr const_pointer   data()  const nssv_noexcept { return data_; }
1278
1279
    // 24.4.2.5 Modifiers:
1280
1281
    nssv_constexpr14 void remove_prefix( size_type n )
1282
    {
1283
        assert( n <= size() );
1284
        data_ += n;
1285
        size_ -= n;
1286
    }
1287
1288
    nssv_constexpr14 void remove_suffix( size_type n )
1289
    {
1290
        assert( n <= size() );
1291
        size_ -= n;
1292
    }
1293
1294
    nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept
1295
    {
1296
        const basic_string_view tmp(other);
1297
        other = *this;
1298
        *this = tmp;
1299
    }
1300
1301
    // 24.4.2.6 String operations:
1302
1303
    size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const
1304
    {
1305
#if nssv_CONFIG_NO_EXCEPTIONS
1306
        assert( pos <= size() );
1307
#else
1308
        if ( pos > size() )
1309
        {
1310
            throw std::out_of_range("nonstd::string_view::copy()");
1311
        }
1312
#endif
1313
        const size_type rlen = (std::min)( n, size() - pos );
1314
1315
        (void) Traits::copy( dest, data() + pos, rlen );
1316
1317
        return rlen;
1318
    }
1319
1320
    nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const
1321
    {
1322
#if nssv_CONFIG_NO_EXCEPTIONS
1323
        assert( pos <= size() );
1324
#else
1325
        if ( pos > size() )
1326
        {
1327
            throw std::out_of_range("nonstd::string_view::substr()");
1328
        }
1329
#endif
1330
        return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );
1331
    }
1332
1333
    // compare(), 6x:
1334
1335
    nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
1336
    {
1337
#if nssv_CPP17_OR_GREATER
1338
        if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
1339
#else
1340
        if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
1341
#endif
1342
        {
1343
            return result;
1344
        }
1345
1346
        return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
1347
    }
1348
1349
    nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2)
1350
    {
1351
        return substr( pos1, n1 ).compare( other );
1352
    }
1353
1354
    nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3)
1355
    {
1356
        return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) );
1357
    }
1358
1359
    nssv_constexpr int compare( CharT const * s ) const // (4)
1360
    {
1361
        return compare( basic_string_view( s ) );
1362
    }
1363
1364
    nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5)
1365
    {
1366
        return substr( pos1, n1 ).compare( basic_string_view( s ) );
1367
    }
1368
1369
    nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6)
1370
    {
1371
        return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );
1372
    }
1373
1374
    // 24.4.2.7 Searching:
1375
1376
    // starts_with(), 3x, since C++20:
1377
1378
    nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept  // (1)
1379
    {
1380
        return size() >= v.size() && compare( 0, v.size(), v ) == 0;
1381
    }
1382
1383
    nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept  // (2)
1384
    {
1385
        return starts_with( basic_string_view( &c, 1 ) );
1386
    }
1387
1388
    nssv_constexpr bool starts_with( CharT const * s ) const  // (3)
1389
    {
1390
        return starts_with( basic_string_view( s ) );
1391
    }
1392
1393
    // ends_with(), 3x, since C++20:
1394
1395
    nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept  // (1)
1396
    {
1397
        return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0;
1398
    }
1399
1400
    nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept  // (2)
1401
    {
1402
        return ends_with( basic_string_view( &c, 1 ) );
1403
    }
1404
1405
    nssv_constexpr bool ends_with( CharT const * s ) const  // (3)
1406
    {
1407
        return ends_with( basic_string_view( s ) );
1408
    }
1409
1410
    // find(), 4x:
1411
1412
    nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept  // (1)
1413
    {
1414
        return assert( v.size() == 0 || v.data() != nssv_nullptr )
1415
            , pos >= size()
1416
            ? npos : to_pos(
1417
#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
1418
                detail::search( substr(pos), v )
1419
#else
1420
                std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq )
1421
#endif
1422
            );
1423
    }
1424
1425
    nssv_constexpr size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept  // (2)
1426
    {
1427
        return find( basic_string_view( &c, 1 ), pos );
1428
    }
1429
1430
    nssv_constexpr size_type find( CharT const * s, size_type pos, size_type n ) const  // (3)
1431
    {
1432
        return find( basic_string_view( s, n ), pos );
1433
    }
1434
1435
    nssv_constexpr size_type find( CharT const * s, size_type pos = 0 ) const  // (4)
1436
    {
1437
        return find( basic_string_view( s ), pos );
1438
    }
1439
1440
    // rfind(), 4x:
1441
1442
    nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept  // (1)
1443
    {
1444
        if ( size() < v.size() )
1445
        {
1446
            return npos;
1447
        }
1448
1449
        if ( v.empty() )
1450
        {
1451
            return (std::min)( size(), pos );
1452
        }
1453
1454
        const_iterator last   = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();
1455
        const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );
1456
1457
        return result != last ? size_type( result - cbegin() ) : npos;
1458
    }
1459
1460
    nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept  // (2)
1461
    {
1462
        return rfind( basic_string_view( &c, 1 ), pos );
1463
    }
1464
1465
    nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const  // (3)
1466
    {
1467
        return rfind( basic_string_view( s, n ), pos );
1468
    }
1469
1470
    nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const  // (4)
1471
    {
1472
        return rfind( basic_string_view( s ), pos );
1473
    }
1474
1475
    // find_first_of(), 4x:
1476
1477
    nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept  // (1)
1478
    {
1479
        return pos >= size()
1480
            ? npos
1481
            : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );
1482
    }
1483
1484
    nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept  // (2)
1485
    {
1486
        return find_first_of( basic_string_view( &c, 1 ), pos );
1487
    }
1488
1489
    nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const  // (3)
1490
    {
1491
        return find_first_of( basic_string_view( s, n ), pos );
1492
    }
1493
1494
    nssv_constexpr size_type find_first_of(  CharT const * s, size_type pos = 0 ) const  // (4)
1495
    {
1496
        return find_first_of( basic_string_view( s ), pos );
1497
    }
1498
1499
    // find_last_of(), 4x:
1500
1501
    nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept  // (1)
1502
    {
1503
        return empty()
1504
            ? npos
1505
            : pos >= size()
1506
            ? find_last_of( v, size() - 1 )
1507
            : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) );
1508
    }
1509
1510
    nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept  // (2)
1511
    {
1512
        return find_last_of( basic_string_view( &c, 1 ), pos );
1513
    }
1514
1515
    nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const  // (3)
1516
    {
1517
        return find_last_of( basic_string_view( s, count ), pos );
1518
    }
1519
1520
    nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const  // (4)
1521
    {
1522
        return find_last_of( basic_string_view( s ), pos );
1523
    }
1524
1525
    // find_first_not_of(), 4x:
1526
1527
    nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept  // (1)
1528
    {
1529
        return pos >= size()
1530
            ? npos
1531
            : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) );
1532
    }
1533
1534
    nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept  // (2)
1535
    {
1536
        return find_first_not_of( basic_string_view( &c, 1 ), pos );
1537
    }
1538
1539
    nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const  // (3)
1540
    {
1541
        return find_first_not_of( basic_string_view( s, count ), pos );
1542
    }
1543
1544
    nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const  // (4)
1545
    {
1546
        return find_first_not_of( basic_string_view( s ), pos );
1547
    }
1548
1549
    // find_last_not_of(), 4x:
1550
1551
    nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept  // (1)
1552
    {
1553
        return empty()
1554
            ? npos
1555
            : pos >= size()
1556
            ? find_last_not_of( v, size() - 1 )
1557
            : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) );
1558
    }
1559
1560
    nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept  // (2)
1561
    {
1562
        return find_last_not_of( basic_string_view( &c, 1 ), pos );
1563
    }
1564
1565
    nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const  // (3)
1566
    {
1567
        return find_last_not_of( basic_string_view( s, count ), pos );
1568
    }
1569
1570
    nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const  // (4)
1571
    {
1572
        return find_last_not_of( basic_string_view( s ), pos );
1573
    }
1574
1575
    // Constants:
1576
1577
#if nssv_CPP17_OR_GREATER
1578
    static nssv_constexpr size_type npos = size_type(-1);
1579
#elif nssv_CPP11_OR_GREATER
1580
    enum : size_type { npos = size_type(-1) };
1581
#else
1582
    enum { npos = size_type(-1) };
1583
#endif
1584
1585
private:
1586
    struct not_in_view
1587
    {
1588
        const basic_string_view v;
1589
1590
        nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {}
1591
1592
        nssv_constexpr bool operator()( CharT c ) const
1593
        {
1594
            return npos == v.find_first_of( c );
1595
        }
1596
    };
1597
1598
    nssv_constexpr size_type to_pos( const_iterator it ) const
1599
    {
1600
        return it == cend() ? npos : size_type( it - cbegin() );
1601
    }
1602
1603
    nssv_constexpr size_type to_pos( const_reverse_iterator it ) const
1604
    {
1605
        return it == crend() ? npos : size_type( crend() - it - 1 );
1606
    }
1607
1608
    nssv_constexpr const_reference data_at( size_type pos ) const
1609
    {
1610
#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 )
1611
        return data_[pos];
1612
#else
1613
        return assert( pos < size() ), data_[pos];
1614
#endif
1615
    }
1616
1617
private:
1618
    const_pointer data_;
1619
    size_type     size_;
1620
1621
public:
1622
#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
1623
1624
    template< class Allocator >
1625
    basic_string_view( std::basic_string<CharT, Traits, Allocator> const & s ) nssv_noexcept
1626
        : data_( s.data() )
1627
        , size_( s.size() )
1628
    {}
1629
1630
#if nssv_HAVE_EXPLICIT_CONVERSION
1631
1632
    template< class Allocator >
1633
    explicit operator std::basic_string<CharT, Traits, Allocator>() const
1634
    {
1635
        return to_string( Allocator() );
1636
    }
1637
1638
#endif // nssv_HAVE_EXPLICIT_CONVERSION
1639
1640
#if nssv_CPP11_OR_GREATER
1641
1642
    template< class Allocator = std::allocator<CharT> >
1643
    std::basic_string<CharT, Traits, Allocator>
1644
    to_string( Allocator const & a = Allocator() ) const
1645
    {
1646
        return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
1647
    }
1648
1649
#else
1650
1651
    std::basic_string<CharT, Traits>
1652
    to_string() const
1653
    {
1654
        return std::basic_string<CharT, Traits>( begin(), end() );
1655
    }
1656
1657
    template< class Allocator >
1658
    std::basic_string<CharT, Traits, Allocator>
1659
    to_string( Allocator const & a ) const
1660
    {
1661
        return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
1662
    }
1663
1664
#endif // nssv_CPP11_OR_GREATER
1665
1666
#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
1667
};
1668
1669
//
1670
// Non-member functions:
1671
//
1672
1673
// 24.4.3 Non-member comparison functions:
1674
// lexicographically compare two string views (function template):
1675
1676
template< class CharT, class Traits >
1677
nssv_constexpr bool operator== (
1678
    basic_string_view <CharT, Traits> lhs,
1679
    basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1680
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1681
1682
template< class CharT, class Traits >
1683
nssv_constexpr bool operator!= (
1684
    basic_string_view <CharT, Traits> lhs,
1685
    basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1686
{ return !( lhs == rhs ); }
1687
1688
template< class CharT, class Traits >
1689
nssv_constexpr bool operator< (
1690
    basic_string_view <CharT, Traits> lhs,
1691
    basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1692
{ return lhs.compare( rhs ) < 0; }
1693
1694
template< class CharT, class Traits >
1695
nssv_constexpr bool operator<= (
1696
    basic_string_view <CharT, Traits> lhs,
1697
    basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1698
{ return lhs.compare( rhs ) <= 0; }
1699
1700
template< class CharT, class Traits >
1701
nssv_constexpr bool operator> (
1702
    basic_string_view <CharT, Traits> lhs,
1703
    basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1704
{ return lhs.compare( rhs ) > 0; }
1705
1706
template< class CharT, class Traits >
1707
nssv_constexpr bool operator>= (
1708
    basic_string_view <CharT, Traits> lhs,
1709
    basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1710
{ return lhs.compare( rhs ) >= 0; }
1711
1712
// Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.
1713
// Implementations shall provide sufficient additional overloads marked
1714
// constexpr and noexcept so that an object t with an implicit conversion
1715
// to S can be compared according to Table 67.
1716
1717
#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
1718
1719
// accommodate for older compilers:
1720
1721
// ==
1722
1723
template< class CharT, class Traits>
1724
nssv_constexpr bool operator==(
1725
    basic_string_view<CharT, Traits> lhs,
1726
    CharT const * rhs ) nssv_noexcept
1727
{ return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; }
1728
1729
template< class CharT, class Traits>
1730
nssv_constexpr bool operator==(
1731
    CharT const * lhs,
1732
    basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1733
{ return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; }
1734
1735
template< class CharT, class Traits>
1736
nssv_constexpr bool operator==(
1737
    basic_string_view<CharT, Traits> lhs,
1738
    std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1739
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1740
1741
template< class CharT, class Traits>
1742
nssv_constexpr bool operator==(
1743
    std::basic_string<CharT, Traits> rhs,
1744
    basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1745
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1746
1747
// !=
1748
1749
template< class CharT, class Traits>
1750
nssv_constexpr bool operator!=(
1751
    basic_string_view<CharT, Traits> lhs,
1752
    CharT const * rhs ) nssv_noexcept
1753
{ return !( lhs == rhs ); }
1754
1755
template< class CharT, class Traits>
1756
nssv_constexpr bool operator!=(
1757
    CharT const * lhs,
1758
    basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1759
{ return !( lhs == rhs ); }
1760
1761
template< class CharT, class Traits>
1762
nssv_constexpr bool operator!=(
1763
    basic_string_view<CharT, Traits> lhs,
1764
    std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1765
{ return !( lhs == rhs ); }
1766
1767
template< class CharT, class Traits>
1768
nssv_constexpr bool operator!=(
1769
    std::basic_string<CharT, Traits> rhs,
1770
    basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1771
{ return !( lhs == rhs ); }
1772
1773
// <
1774
1775
template< class CharT, class Traits>
1776
nssv_constexpr bool operator<(
1777
    basic_string_view<CharT, Traits> lhs,
1778
    CharT const * rhs ) nssv_noexcept
1779
{ return lhs.compare( rhs ) < 0; }
1780
1781
template< class CharT, class Traits>
1782
nssv_constexpr bool operator<(
1783
    CharT const * lhs,
1784
    basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1785
{ return rhs.compare( lhs ) > 0; }
1786
1787
template< class CharT, class Traits>
1788
nssv_constexpr bool operator<(
1789
    basic_string_view<CharT, Traits> lhs,
1790
    std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1791
{ return lhs.compare( rhs ) < 0; }
1792
1793
template< class CharT, class Traits>
1794
nssv_constexpr bool operator<(
1795
    std::basic_string<CharT, Traits> rhs,
1796
    basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1797
{ return rhs.compare( lhs ) > 0; }
1798
1799
// <=
1800
1801
template< class CharT, class Traits>
1802
nssv_constexpr bool operator<=(
1803
    basic_string_view<CharT, Traits> lhs,
1804
    CharT const * rhs ) nssv_noexcept
1805
{ return lhs.compare( rhs ) <= 0; }
1806
1807
template< class CharT, class Traits>
1808
nssv_constexpr bool operator<=(
1809
    CharT const * lhs,
1810
    basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1811
{ return rhs.compare( lhs ) >= 0; }
1812
1813
template< class CharT, class Traits>
1814
nssv_constexpr bool operator<=(
1815
    basic_string_view<CharT, Traits> lhs,
1816
    std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1817
{ return lhs.compare( rhs ) <= 0; }
1818
1819
template< class CharT, class Traits>
1820
nssv_constexpr bool operator<=(
1821
    std::basic_string<CharT, Traits> rhs,
1822
    basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1823
{ return rhs.compare( lhs ) >= 0; }
1824
1825
// >
1826
1827
template< class CharT, class Traits>
1828
nssv_constexpr bool operator>(
1829
    basic_string_view<CharT, Traits> lhs,
1830
    CharT const * rhs ) nssv_noexcept
1831
{ return lhs.compare( rhs ) > 0; }
1832
1833
template< class CharT, class Traits>
1834
nssv_constexpr bool operator>(
1835
    CharT const * lhs,
1836
    basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1837
{ return rhs.compare( lhs ) < 0; }
1838
1839
template< class CharT, class Traits>
1840
nssv_constexpr bool operator>(
1841
    basic_string_view<CharT, Traits> lhs,
1842
    std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1843
{ return lhs.compare( rhs ) > 0; }
1844
1845
template< class CharT, class Traits>
1846
nssv_constexpr bool operator>(
1847
    std::basic_string<CharT, Traits> rhs,
1848
    basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1849
{ return rhs.compare( lhs ) < 0; }
1850
1851
// >=
1852
1853
template< class CharT, class Traits>
1854
nssv_constexpr bool operator>=(
1855
    basic_string_view<CharT, Traits> lhs,
1856
    CharT const * rhs ) nssv_noexcept
1857
{ return lhs.compare( rhs ) >= 0; }
1858
1859
template< class CharT, class Traits>
1860
nssv_constexpr bool operator>=(
1861
    CharT const * lhs,
1862
    basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1863
{ return rhs.compare( lhs ) <= 0; }
1864
1865
template< class CharT, class Traits>
1866
nssv_constexpr bool operator>=(
1867
    basic_string_view<CharT, Traits> lhs,
1868
    std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1869
{ return lhs.compare( rhs ) >= 0; }
1870
1871
template< class CharT, class Traits>
1872
nssv_constexpr bool operator>=(
1873
    std::basic_string<CharT, Traits> rhs,
1874
    basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1875
{ return rhs.compare( lhs ) <= 0; }
1876
1877
#else // newer compilers:
1878
1879
#define nssv_BASIC_STRING_VIEW_I(T,U)  typename std::decay< basic_string_view<T,U> >::type
1880
1881
#if defined(_MSC_VER)       // issue 40
1882
# define nssv_MSVC_ORDER(x)  , int=x
1883
#else
1884
# define nssv_MSVC_ORDER(x)  /*, int=x*/
1885
#endif
1886
1887
// ==
1888
1889
template< class CharT, class Traits  nssv_MSVC_ORDER(1) >
1890
nssv_constexpr bool operator==(
1891
         basic_string_view  <CharT, Traits> lhs,
1892
    nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept
1893
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1894
1895
template< class CharT, class Traits  nssv_MSVC_ORDER(2) >
1896
nssv_constexpr bool operator==(
1897
    nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
1898
         basic_string_view  <CharT, Traits> rhs ) nssv_noexcept
1899
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1900
1901
// !=
1902
1903
template< class CharT, class Traits  nssv_MSVC_ORDER(1) >
1904
nssv_constexpr bool operator!= (
1905
         basic_string_view  < CharT, Traits > lhs,
1906
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1907
{ return !( lhs == rhs ); }
1908
1909
template< class CharT, class Traits  nssv_MSVC_ORDER(2) >
1910
nssv_constexpr bool operator!= (
1911
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1912
         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept
1913
{ return !( lhs == rhs ); }
1914
1915
// <
1916
1917
template< class CharT, class Traits  nssv_MSVC_ORDER(1) >
1918
nssv_constexpr bool operator< (
1919
         basic_string_view  < CharT, Traits > lhs,
1920
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1921
{ return lhs.compare( rhs ) < 0; }
1922
1923
template< class CharT, class Traits  nssv_MSVC_ORDER(2) >
1924
nssv_constexpr bool operator< (
1925
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1926
         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept
1927
{ return lhs.compare( rhs ) < 0; }
1928
1929
// <=
1930
1931
template< class CharT, class Traits  nssv_MSVC_ORDER(1) >
1932
nssv_constexpr bool operator<= (
1933
         basic_string_view  < CharT, Traits > lhs,
1934
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1935
{ return lhs.compare( rhs ) <= 0; }
1936
1937
template< class CharT, class Traits  nssv_MSVC_ORDER(2) >
1938
nssv_constexpr bool operator<= (
1939
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1940
         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept
1941
{ return lhs.compare( rhs ) <= 0; }
1942
1943
// >
1944
1945
template< class CharT, class Traits  nssv_MSVC_ORDER(1) >
1946
nssv_constexpr bool operator> (
1947
         basic_string_view  < CharT, Traits > lhs,
1948
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1949
{ return lhs.compare( rhs ) > 0; }
1950
1951
template< class CharT, class Traits  nssv_MSVC_ORDER(2) >
1952
nssv_constexpr bool operator> (
1953
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1954
         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept
1955
{ return lhs.compare( rhs ) > 0; }
1956
1957
// >=
1958
1959
template< class CharT, class Traits  nssv_MSVC_ORDER(1) >
1960
nssv_constexpr bool operator>= (
1961
         basic_string_view  < CharT, Traits > lhs,
1962
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1963
{ return lhs.compare( rhs ) >= 0; }
1964
1965
template< class CharT, class Traits  nssv_MSVC_ORDER(2) >
1966
nssv_constexpr bool operator>= (
1967
    nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1968
         basic_string_view  < CharT, Traits > rhs ) nssv_noexcept
1969
{ return lhs.compare( rhs ) >= 0; }
1970
1971
#undef nssv_MSVC_ORDER
1972
#undef nssv_BASIC_STRING_VIEW_I
1973
1974
#endif // compiler-dependent approach to comparisons
1975
1976
// 24.4.4 Inserters and extractors:
1977
1978
#if ! nssv_CONFIG_NO_STREAM_INSERTION
1979
1980
namespace detail {
1981
1982
template< class Stream >
1983
void write_padding( Stream & os, std::streamsize n )
1984
{
1985
    for ( std::streamsize i = 0; i < n; ++i )
1986
        os.rdbuf()->sputc( os.fill() );
1987
}
1988
1989
template< class Stream, class View >
1990
Stream & write_to_stream( Stream & os, View const & sv )
1991
{
1992
    typename Stream::sentry sentry( os );
1993
1994
    if ( !sentry )
1995
        return os;
1996
1997
    const std::streamsize length = static_cast<std::streamsize>( sv.length() );
1998
1999
    // Whether, and how, to pad:
2000
    const bool      pad = ( length < os.width() );
2001
    const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;
2002
2003
    if ( left_pad )
2004
        write_padding( os, os.width() - length );
2005
2006
    // Write span characters:
2007
    os.rdbuf()->sputn( sv.begin(), length );
2008
2009
    if ( pad && !left_pad )
2010
        write_padding( os, os.width() - length );
2011
2012
    // Reset output stream width:
2013
    os.width( 0 );
2014
2015
    return os;
2016
}
2017
2018
} // namespace detail
2019
2020
template< class CharT, class Traits >
2021
std::basic_ostream<CharT, Traits> &
2022
operator<<(
2023
    std::basic_ostream<CharT, Traits>& os,
2024
    basic_string_view <CharT, Traits> sv )
2025
{
2026
    return detail::write_to_stream( os, sv );
2027
}
2028
2029
#endif // nssv_CONFIG_NO_STREAM_INSERTION
2030
2031
// Several typedefs for common character types are provided:
2032
2033
typedef basic_string_view<char>      string_view;
2034
typedef basic_string_view<wchar_t>   wstring_view;
2035
#if nssv_HAVE_WCHAR16_T
2036
typedef basic_string_view<char16_t>  u16string_view;
2037
typedef basic_string_view<char32_t>  u32string_view;
2038
#endif
2039
2040
}} // namespace nonstd::sv_lite
2041
2042
//
2043
// 24.4.6 Suffix for basic_string_view literals:
2044
//
2045
2046
#if nssv_HAVE_USER_DEFINED_LITERALS
2047
2048
namespace nonstd {
2049
nssv_inline_ns namespace literals {
2050
nssv_inline_ns namespace string_view_literals {
2051
2052
#if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
2053
2054
nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept  // (1)
2055
{
2056
    return nonstd::sv_lite::string_view{ str, len };
2057
}
2058
2059
nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept  // (2)
2060
{
2061
    return nonstd::sv_lite::u16string_view{ str, len };
2062
}
2063
2064
nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept  // (3)
2065
{
2066
    return nonstd::sv_lite::u32string_view{ str, len };
2067
}
2068
2069
nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept  // (4)
2070
{
2071
    return nonstd::sv_lite::wstring_view{ str, len };
2072
}
2073
2074
#endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
2075
2076
#if nssv_CONFIG_USR_SV_OPERATOR
2077
2078
nssv_constexpr nonstd::sv_lite::string_view operator "" _sv( const char* str, size_t len ) nssv_noexcept  // (1)
2079
{
2080
    return nonstd::sv_lite::string_view{ str, len };
2081
}
2082
2083
nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv( const char16_t* str, size_t len ) nssv_noexcept  // (2)
2084
{
2085
    return nonstd::sv_lite::u16string_view{ str, len };
2086
}
2087
2088
nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv( const char32_t* str, size_t len ) nssv_noexcept  // (3)
2089
{
2090
    return nonstd::sv_lite::u32string_view{ str, len };
2091
}
2092
2093
nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv( const wchar_t* str, size_t len ) nssv_noexcept  // (4)
2094
{
2095
    return nonstd::sv_lite::wstring_view{ str, len };
2096
}
2097
2098
#endif // nssv_CONFIG_USR_SV_OPERATOR
2099
2100
}}} // namespace nonstd::literals::string_view_literals
2101
2102
#endif
2103
2104
//
2105
// Extensions for std::string:
2106
//
2107
2108
#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
2109
2110
namespace nonstd {
2111
namespace sv_lite {
2112
2113
// Exclude MSVC 14 (19.00): it yields ambiguous to_string():
2114
2115
#if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
2116
2117
template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
2118
std::basic_string<CharT, Traits, Allocator>
2119
to_string( basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
2120
{
2121
    return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
2122
}
2123
2124
#else
2125
2126
template< class CharT, class Traits >
2127
std::basic_string<CharT, Traits>
2128
to_string( basic_string_view<CharT, Traits> v )
2129
{
2130
    return std::basic_string<CharT, Traits>( v.begin(), v.end() );
2131
}
2132
2133
template< class CharT, class Traits, class Allocator >
2134
std::basic_string<CharT, Traits, Allocator>
2135
to_string( basic_string_view<CharT, Traits> v, Allocator const & a )
2136
{
2137
    return std::basic_string<CharT, Traits, Allocator>( v.begin(), v.end(), a );
2138
}
2139
2140
#endif // nssv_CPP11_OR_GREATER
2141
2142
template< class CharT, class Traits, class Allocator >
2143
basic_string_view<CharT, Traits>
2144
to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
2145
{
2146
    return basic_string_view<CharT, Traits>( s.data(), s.size() );
2147
}
2148
2149
}} // namespace nonstd::sv_lite
2150
2151
#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
2152
2153
//
2154
// make types and algorithms available in namespace nonstd:
2155
//
2156
2157
namespace nonstd {
2158
2159
using sv_lite::basic_string_view;
2160
using sv_lite::string_view;
2161
using sv_lite::wstring_view;
2162
2163
#if nssv_HAVE_WCHAR16_T
2164
using sv_lite::u16string_view;
2165
#endif
2166
#if nssv_HAVE_WCHAR32_T
2167
using sv_lite::u32string_view;
2168
#endif
2169
2170
// literal "sv"
2171
2172
using sv_lite::operator==;
2173
using sv_lite::operator!=;
2174
using sv_lite::operator<;
2175
using sv_lite::operator<=;
2176
using sv_lite::operator>;
2177
using sv_lite::operator>=;
2178
2179
#if ! nssv_CONFIG_NO_STREAM_INSERTION
2180
using sv_lite::operator<<;
2181
#endif
2182
2183
#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
2184
using sv_lite::to_string;
2185
using sv_lite::to_string_view;
2186
#endif
2187
2188
} // namespace nonstd
2189
2190
// 24.4.5 Hash support (C++11):
2191
2192
// Note: The hash value of a string view object is equal to the hash value of
2193
// the corresponding string object.
2194
2195
#if nssv_HAVE_STD_HASH
2196
2197
#include <functional>
2198
2199
namespace std {
2200
2201
template<>
2202
struct hash< nonstd::string_view >
2203
{
2204
public:
2205
    std::size_t operator()( nonstd::string_view v ) const nssv_noexcept
2206
    {
2207
        return std::hash<std::string>()( std::string( v.data(), v.size() ) );
2208
    }
2209
};
2210
2211
template<>
2212
struct hash< nonstd::wstring_view >
2213
{
2214
public:
2215
    std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept
2216
    {
2217
        return std::hash<std::wstring>()( std::wstring( v.data(), v.size() ) );
2218
    }
2219
};
2220
2221
template<>
2222
struct hash< nonstd::u16string_view >
2223
{
2224
public:
2225
    std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept
2226
    {
2227
        return std::hash<std::u16string>()( std::u16string( v.data(), v.size() ) );
2228
    }
2229
};
2230
2231
template<>
2232
struct hash< nonstd::u32string_view >
2233
{
2234
public:
2235
    std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept
2236
    {
2237
        return std::hash<std::u32string>()( std::u32string( v.data(), v.size() ) );
2238
    }
2239
};
2240
2241
} // namespace std
2242
2243
#endif // nssv_HAVE_STD_HASH
2244
2245
nssv_RESTORE_WARNINGS()
2246
2247
#endif // nssv_HAVE_STD_STRING_VIEW
2248
#endif // NONSTD_SV_LITE_H_INCLUDED
2249
/* end file simdjson/nonstd/string_view.hpp */
2250
SIMDJSON_POP_DISABLE_WARNINGS
2251
2252
namespace std {
2253
  using string_view = nonstd::string_view;
2254
}
2255
#endif // SIMDJSON_HAS_STRING_VIEW
2256
#undef SIMDJSON_HAS_STRING_VIEW // We are not going to need this macro anymore.
2257
2258
/// If EXPR is an error, returns it.
2259
0
#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
2260
2261
// Unless the programmer has already set SIMDJSON_DEVELOPMENT_CHECKS,
2262
// we want to set it under debug builds. We detect a debug build
2263
// under Visual Studio when the _DEBUG macro is set. Under the other
2264
// compilers, we use the fact that they define __OPTIMIZE__ whenever
2265
// they allow optimizations.
2266
// It is possible that this could miss some cases where SIMDJSON_DEVELOPMENT_CHECKS
2267
// is helpful, but the programmer can set the macro SIMDJSON_DEVELOPMENT_CHECKS.
2268
// It could also wrongly set SIMDJSON_DEVELOPMENT_CHECKS (e.g., if the programmer
2269
// sets _DEBUG in a release build under Visual Studio, or if some compiler fails to
2270
// set the __OPTIMIZE__ macro).
2271
#ifndef SIMDJSON_DEVELOPMENT_CHECKS
2272
#ifdef _MSC_VER
2273
// Visual Studio seems to set _DEBUG for debug builds.
2274
#ifdef _DEBUG
2275
#define SIMDJSON_DEVELOPMENT_CHECKS 1
2276
#endif // _DEBUG
2277
#else // _MSC_VER
2278
// All other compilers appear to set __OPTIMIZE__ to a positive integer
2279
// when the compiler is optimizing.
2280
#ifndef __OPTIMIZE__
2281
#define SIMDJSON_DEVELOPMENT_CHECKS 1
2282
#endif // __OPTIMIZE__
2283
#endif // _MSC_VER
2284
#endif // SIMDJSON_DEVELOPMENT_CHECKS
2285
2286
// The SIMDJSON_CHECK_EOF macro is a feature flag for the "don't require padding"
2287
// feature.
2288
2289
#if SIMDJSON_CPLUSPLUS17
2290
// if we have C++, then fallthrough is a default attribute
2291
0
# define simdjson_fallthrough [[fallthrough]]
2292
// check if we have __attribute__ support
2293
#elif defined(__has_attribute)
2294
// check if we have the __fallthrough__ attribute
2295
#if __has_attribute(__fallthrough__)
2296
// we are good to go:
2297
# define simdjson_fallthrough                    __attribute__((__fallthrough__))
2298
#endif // __has_attribute(__fallthrough__)
2299
#endif // SIMDJSON_CPLUSPLUS17
2300
// on some systems, we simply do not have support for fallthrough, so use a default:
2301
#ifndef simdjson_fallthrough
2302
# define simdjson_fallthrough do {} while (0)  /* fallthrough */
2303
#endif // simdjson_fallthrough
2304
2305
#if SIMDJSON_DEVELOPMENT_CHECKS
2306
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0)
2307
#else
2308
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
2309
#endif
2310
2311
#ifndef SIMDJSON_UTF8VALIDATION
2312
#define SIMDJSON_UTF8VALIDATION 1
2313
#endif
2314
2315
#ifdef __has_include
2316
// How do we detect that a compiler supports vbmi2?
2317
// For sure if the following header is found, we are ok?
2318
#if __has_include(<avx512vbmi2intrin.h>)
2319
#define SIMDJSON_COMPILER_SUPPORTS_VBMI2 1
2320
#endif
2321
#endif
2322
2323
#ifdef _MSC_VER
2324
#if _MSC_VER >= 1920
2325
// Visual Studio 2019 and up support VBMI2 under x64 even if the header
2326
// avx512vbmi2intrin.h is not found.
2327
#define SIMDJSON_COMPILER_SUPPORTS_VBMI2 1
2328
#endif
2329
#endif
2330
2331
// By default, we allow AVX512.
2332
#ifndef SIMDJSON_AVX512_ALLOWED
2333
#define SIMDJSON_AVX512_ALLOWED 1
2334
#endif
2335
2336
#endif // SIMDJSON_COMMON_DEFS_H
2337
/* end file simdjson/common_defs.h */
2338
2339
// This provides the public API for simdjson.
2340
// DOM and ondemand are amalgamated separately, in simdjson.h
2341
/* including simdjson/simdjson_version.h: #include "simdjson/simdjson_version.h" */
2342
/* begin file simdjson/simdjson_version.h */
2343
// /include/simdjson/simdjson_version.h automatically generated by release.py,
2344
// do not change by hand
2345
#ifndef SIMDJSON_SIMDJSON_VERSION_H
2346
#define SIMDJSON_SIMDJSON_VERSION_H
2347
2348
/** The version of simdjson being used (major.minor.revision) */
2349
132k
#define SIMDJSON_VERSION "3.8.0"
2350
2351
namespace simdjson {
2352
enum {
2353
  /**
2354
   * The major version (MAJOR.minor.revision) of simdjson being used.
2355
   */
2356
  SIMDJSON_VERSION_MAJOR = 3,
2357
  /**
2358
   * The minor version (major.MINOR.revision) of simdjson being used.
2359
   */
2360
  SIMDJSON_VERSION_MINOR = 8,
2361
  /**
2362
   * The revision (major.minor.REVISION) of simdjson being used.
2363
   */
2364
  SIMDJSON_VERSION_REVISION = 0
2365
};
2366
} // namespace simdjson
2367
2368
#endif // SIMDJSON_SIMDJSON_VERSION_H
2369
/* end file simdjson/simdjson_version.h */
2370
2371
/* including simdjson/base.h: #include "simdjson/base.h" */
2372
/* begin file simdjson/base.h */
2373
/**
2374
 * @file Base declarations for all simdjson headers
2375
 * @private
2376
 */
2377
#ifndef SIMDJSON_BASE_H
2378
#define SIMDJSON_BASE_H
2379
2380
/* skipped duplicate #include "simdjson/common_defs.h" */
2381
/* skipped duplicate #include "simdjson/compiler_check.h" */
2382
/* including simdjson/error.h: #include "simdjson/error.h" */
2383
/* begin file simdjson/error.h */
2384
#ifndef SIMDJSON_ERROR_H
2385
#define SIMDJSON_ERROR_H
2386
2387
/* skipped duplicate #include "simdjson/base.h" */
2388
2389
#include <string>
2390
#include <ostream>
2391
2392
namespace simdjson {
2393
2394
/**
2395
 * All possible errors returned by simdjson. These error codes are subject to change
2396
 * and not all simdjson kernel returns the same error code given the same input: it is not
2397
 * well defined which error a given input should produce.
2398
 *
2399
 * Only SUCCESS evaluates to false as a Boolean. All other error codes will evaluate
2400
 * to true as a Boolean.
2401
 */
2402
enum error_code {
2403
  SUCCESS = 0,                ///< No error
2404
  CAPACITY,                   ///< This parser can't support a document that big
2405
  MEMALLOC,                   ///< Error allocating memory, most likely out of memory
2406
  TAPE_ERROR,                 ///< Something went wrong, this is a generic error
2407
  DEPTH_ERROR,                ///< Your document exceeds the user-specified depth limitation
2408
  STRING_ERROR,               ///< Problem while parsing a string
2409
  T_ATOM_ERROR,               ///< Problem while parsing an atom starting with the letter 't'
2410
  F_ATOM_ERROR,               ///< Problem while parsing an atom starting with the letter 'f'
2411
  N_ATOM_ERROR,               ///< Problem while parsing an atom starting with the letter 'n'
2412
  NUMBER_ERROR,               ///< Problem while parsing a number
2413
  BIGINT_ERROR,               ///< The integer value exceeds 64 bits
2414
  UTF8_ERROR,                 ///< the input is not valid UTF-8
2415
  UNINITIALIZED,              ///< unknown error, or uninitialized document
2416
  EMPTY,                      ///< no structural element found
2417
  UNESCAPED_CHARS,            ///< found unescaped characters in a string.
2418
  UNCLOSED_STRING,            ///< missing quote at the end
2419
  UNSUPPORTED_ARCHITECTURE,   ///< unsupported architecture
2420
  INCORRECT_TYPE,             ///< JSON element has a different type than user expected
2421
  NUMBER_OUT_OF_RANGE,        ///< JSON number does not fit in 64 bits
2422
  INDEX_OUT_OF_BOUNDS,        ///< JSON array index too large
2423
  NO_SUCH_FIELD,              ///< JSON field not found in object
2424
  IO_ERROR,                   ///< Error reading a file
2425
  INVALID_JSON_POINTER,       ///< Invalid JSON pointer reference
2426
  INVALID_URI_FRAGMENT,       ///< Invalid URI fragment
2427
  UNEXPECTED_ERROR,           ///< indicative of a bug in simdjson
2428
  PARSER_IN_USE,              ///< parser is already in use.
2429
  OUT_OF_ORDER_ITERATION,     ///< tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1)
2430
  INSUFFICIENT_PADDING,       ///< The JSON doesn't have enough padding for simdjson to safely parse it.
2431
  INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
2432
  SCALAR_DOCUMENT_AS_VALUE,   ///< A scalar document is treated as a value.
2433
  OUT_OF_BOUNDS,              ///< Attempted to access location outside of document.
2434
  TRAILING_CONTENT,           ///< Unexpected trailing content in the JSON input
2435
  NUM_ERROR_CODES
2436
};
2437
2438
/**
2439
 * It is the convention throughout the code that  the macro SIMDJSON_DEVELOPMENT_CHECKS determines whether
2440
 * we check for OUT_OF_ORDER_ITERATION. The logic behind it is that these errors only occurs when the code
2441
 * that was written while breaking some simdjson::ondemand requirement. They should not occur in released
2442
 * code after these issues were fixed.
2443
 */
2444
2445
/**
2446
 * Get the error message for the given error code.
2447
 *
2448
 *   dom::parser parser;
2449
 *   dom::element doc;
2450
 *   auto error = parser.parse("foo",3).get(doc);
2451
 *   if (error) { printf("Error: %s\n", error_message(error)); }
2452
 *
2453
 * @return The error message.
2454
 */
2455
inline const char *error_message(error_code error) noexcept;
2456
2457
/**
2458
 * Write the error message to the output stream
2459
 */
2460
inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept;
2461
2462
/**
2463
 * Exception thrown when an exception-supporting simdjson method is called
2464
 */
2465
struct simdjson_error : public std::exception {
2466
  /**
2467
   * Create an exception from a simdjson error code.
2468
   * @param error The error code
2469
   */
2470
0
  simdjson_error(error_code error) noexcept : _error{error} { }
2471
  /** The error message */
2472
0
  const char *what() const noexcept { return error_message(error()); }
2473
  /** The error code */
2474
0
  error_code error() const noexcept { return _error; }
2475
private:
2476
  /** The error code that was used */
2477
  error_code _error;
2478
};
2479
2480
namespace internal {
2481
2482
/**
2483
 * The result of a simdjson operation that could fail.
2484
 *
2485
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
2486
 *
2487
 * This is a base class for implementations that want to add functions to the result type for
2488
 * chaining.
2489
 *
2490
 * Override like:
2491
 *
2492
 *   struct simdjson_result<T> : public internal::simdjson_result_base<T> {
2493
 *     simdjson_result() noexcept : internal::simdjson_result_base<T>() {}
2494
 *     simdjson_result(error_code error) noexcept : internal::simdjson_result_base<T>(error) {}
2495
 *     simdjson_result(T &&value) noexcept : internal::simdjson_result_base<T>(std::forward(value)) {}
2496
 *     simdjson_result(T &&value, error_code error) noexcept : internal::simdjson_result_base<T>(value, error) {}
2497
 *     // Your extra methods here
2498
 *   }
2499
 *
2500
 * Then any method returning simdjson_result<T> will be chainable with your methods.
2501
 */
2502
template<typename T>
2503
struct simdjson_result_base : protected std::pair<T, error_code> {
2504
2505
  /**
2506
   * Create a new empty result with error = UNINITIALIZED.
2507
   */
2508
  simdjson_inline simdjson_result_base() noexcept;
2509
2510
  /**
2511
   * Create a new error result.
2512
   */
2513
  simdjson_inline simdjson_result_base(error_code error) noexcept;
2514
2515
  /**
2516
   * Create a new successful result.
2517
   */
2518
  simdjson_inline simdjson_result_base(T &&value) noexcept;
2519
2520
  /**
2521
   * Create a new result with both things (use if you don't want to branch when creating the result).
2522
   */
2523
  simdjson_inline simdjson_result_base(T &&value, error_code error) noexcept;
2524
2525
  /**
2526
   * Move the value and the error to the provided variables.
2527
   *
2528
   * @param value The variable to assign the value to. May not be set if there is an error.
2529
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
2530
   */
2531
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
2532
2533
  /**
2534
   * Move the value to the provided variable.
2535
   *
2536
   * @param value The variable to assign the value to. May not be set if there is an error.
2537
   */
2538
  simdjson_inline error_code get(T &value) && noexcept;
2539
2540
  /**
2541
   * The error.
2542
   */
2543
  simdjson_inline error_code error() const noexcept;
2544
2545
#if SIMDJSON_EXCEPTIONS
2546
2547
  /**
2548
   * Get the result value.
2549
   *
2550
   * @throw simdjson_error if there was an error.
2551
   */
2552
  simdjson_inline T& value() & noexcept(false);
2553
2554
  /**
2555
   * Take the result value (move it).
2556
   *
2557
   * @throw simdjson_error if there was an error.
2558
   */
2559
  simdjson_inline T&& value() && noexcept(false);
2560
2561
  /**
2562
   * Take the result value (move it).
2563
   *
2564
   * @throw simdjson_error if there was an error.
2565
   */
2566
  simdjson_inline T&& take_value() && noexcept(false);
2567
2568
  /**
2569
   * Cast to the value (will throw on error).
2570
   *
2571
   * @throw simdjson_error if there was an error.
2572
   */
2573
  simdjson_inline operator T&&() && noexcept(false);
2574
#endif // SIMDJSON_EXCEPTIONS
2575
2576
  /**
2577
   * Get the result value. This function is safe if and only
2578
   * the error() method returns a value that evaluates to false.
2579
   */
2580
  simdjson_inline const T& value_unsafe() const& noexcept;
2581
2582
  /**
2583
   * Take the result value (move it). This function is safe if and only
2584
   * the error() method returns a value that evaluates to false.
2585
   */
2586
  simdjson_inline T&& value_unsafe() && noexcept;
2587
2588
}; // struct simdjson_result_base
2589
2590
} // namespace internal
2591
2592
/**
2593
 * The result of a simdjson operation that could fail.
2594
 *
2595
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
2596
 */
2597
template<typename T>
2598
struct simdjson_result : public internal::simdjson_result_base<T> {
2599
  /**
2600
   * @private Create a new empty result with error = UNINITIALIZED.
2601
   */
2602
  simdjson_inline simdjson_result() noexcept;
2603
  /**
2604
   * @private Create a new successful result.
2605
   */
2606
  simdjson_inline simdjson_result(T &&value) noexcept;
2607
  /**
2608
   * @private Create a new error result.
2609
   */
2610
  simdjson_inline simdjson_result(error_code error_code) noexcept;
2611
  /**
2612
   * @private Create a new result with both things (use if you don't want to branch when creating the result).
2613
   */
2614
  simdjson_inline simdjson_result(T &&value, error_code error) noexcept;
2615
2616
  /**
2617
   * Move the value and the error to the provided variables.
2618
   *
2619
   * @param value The variable to assign the value to. May not be set if there is an error.
2620
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
2621
   */
2622
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
2623
2624
  /**
2625
   * Move the value to the provided variable.
2626
   *
2627
   * @param value The variable to assign the value to. May not be set if there is an error.
2628
   */
2629
  simdjson_warn_unused simdjson_inline error_code get(T &value) && noexcept;
2630
2631
  /**
2632
   * The error.
2633
   */
2634
  simdjson_inline error_code error() const noexcept;
2635
2636
#if SIMDJSON_EXCEPTIONS
2637
2638
  /**
2639
   * Get the result value.
2640
   *
2641
   * @throw simdjson_error if there was an error.
2642
   */
2643
  simdjson_inline T& value() & noexcept(false);
2644
2645
  /**
2646
   * Take the result value (move it).
2647
   *
2648
   * @throw simdjson_error if there was an error.
2649
   */
2650
  simdjson_inline T&& value() && noexcept(false);
2651
2652
  /**
2653
   * Take the result value (move it).
2654
   *
2655
   * @throw simdjson_error if there was an error.
2656
   */
2657
  simdjson_inline T&& take_value() && noexcept(false);
2658
2659
  /**
2660
   * Cast to the value (will throw on error).
2661
   *
2662
   * @throw simdjson_error if there was an error.
2663
   */
2664
  simdjson_inline operator T&&() && noexcept(false);
2665
#endif // SIMDJSON_EXCEPTIONS
2666
2667
  /**
2668
   * Get the result value. This function is safe if and only
2669
   * the error() method returns a value that evaluates to false.
2670
   */
2671
  simdjson_inline const T& value_unsafe() const& noexcept;
2672
2673
  /**
2674
   * Take the result value (move it). This function is safe if and only
2675
   * the error() method returns a value that evaluates to false.
2676
   */
2677
  simdjson_inline T&& value_unsafe() && noexcept;
2678
2679
}; // struct simdjson_result
2680
2681
#if SIMDJSON_EXCEPTIONS
2682
2683
template<typename T>
2684
inline std::ostream& operator<<(std::ostream& out, simdjson_result<T> value) { return out << value.value(); }
2685
#endif // SIMDJSON_EXCEPTIONS
2686
2687
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
2688
/**
2689
 * @deprecated This is an alias and will be removed, use error_code instead
2690
 */
2691
using ErrorValues [[deprecated("This is an alias and will be removed, use error_code instead")]] = error_code;
2692
2693
/**
2694
 * @deprecated Error codes should be stored and returned as `error_code`, use `error_message()` instead.
2695
 */
2696
[[deprecated("Error codes should be stored and returned as `error_code`, use `error_message()` instead.")]]
2697
inline const std::string error_message(int error) noexcept;
2698
#endif // SIMDJSON_DISABLE_DEPRECATED_API
2699
} // namespace simdjson
2700
2701
#endif // SIMDJSON_ERROR_H
2702
/* end file simdjson/error.h */
2703
/* skipped duplicate #include "simdjson/portability.h" */
2704
2705
/**
2706
 * @brief The top level simdjson namespace, containing everything the library provides.
2707
 */
2708
namespace simdjson {
2709
2710
SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
2711
2712
/** The maximum document size supported by simdjson. */
2713
constexpr size_t SIMDJSON_MAXSIZE_BYTES = 0xFFFFFFFF;
2714
2715
/**
2716
 * The amount of padding needed in a buffer to parse JSON.
2717
 *
2718
 * The input buf should be readable up to buf + SIMDJSON_PADDING
2719
 * this is a stopgap; there should be a better description of the
2720
 * main loop and its behavior that abstracts over this
2721
 * See https://github.com/simdjson/simdjson/issues/174
2722
 */
2723
constexpr size_t SIMDJSON_PADDING = 64;
2724
2725
/**
2726
 * By default, simdjson supports this many nested objects and arrays.
2727
 *
2728
 * This is the default for parser::max_depth().
2729
 */
2730
constexpr size_t DEFAULT_MAX_DEPTH = 1024;
2731
2732
SIMDJSON_POP_DISABLE_UNUSED_WARNINGS
2733
2734
class implementation;
2735
struct padded_string;
2736
class padded_string_view;
2737
enum class stage1_mode;
2738
2739
namespace internal {
2740
2741
template<typename T>
2742
class atomic_ptr;
2743
class dom_parser_implementation;
2744
class escape_json_string;
2745
class tape_ref;
2746
struct value128;
2747
enum class tape_type;
2748
2749
} // namespace internal
2750
} // namespace simdjson
2751
2752
#endif // SIMDJSON_BASE_H
2753
/* end file simdjson/base.h */
2754
2755
/* skipped duplicate #include "simdjson/error.h" */
2756
/* including simdjson/error-inl.h: #include "simdjson/error-inl.h" */
2757
/* begin file simdjson/error-inl.h */
2758
#ifndef SIMDJSON_ERROR_INL_H
2759
#define SIMDJSON_ERROR_INL_H
2760
2761
/* skipped duplicate #include "simdjson/error.h" */
2762
2763
#include <iostream>
2764
2765
namespace simdjson {
2766
namespace internal {
2767
  // We store the error code so we can validate the error message is associated with the right code
2768
  struct error_code_info {
2769
    error_code code;
2770
    const char* message; // do not use a fancy std::string where a simple C string will do (no alloc, no destructor)
2771
  };
2772
  // These MUST match the codes in error_code. We check this constraint in basictests.
2773
  extern SIMDJSON_DLLIMPORTEXPORT const error_code_info error_codes[];
2774
} // namespace internal
2775
2776
2777
0
inline const char *error_message(error_code error) noexcept {
2778
0
  // If you're using error_code, we're trusting you got it from the enum.
2779
0
  return internal::error_codes[int(error)].message;
2780
0
}
2781
2782
// deprecated function
2783
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
2784
0
inline const std::string error_message(int error) noexcept {
2785
0
  if (error < 0 || error >= error_code::NUM_ERROR_CODES) {
2786
0
    return internal::error_codes[UNEXPECTED_ERROR].message;
2787
0
  }
2788
0
  return internal::error_codes[error].message;
2789
0
}
2790
#endif // SIMDJSON_DISABLE_DEPRECATED_API
2791
2792
0
inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept {
2793
0
  return out << error_message(error);
2794
0
}
2795
2796
namespace internal {
2797
2798
//
2799
// internal::simdjson_result_base<T> inline implementation
2800
//
2801
2802
template<typename T>
2803
0
simdjson_inline void simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
2804
0
  error = this->second;
2805
0
  if (!error) {
2806
0
    value = std::forward<simdjson_result_base<T>>(*this).first;
2807
0
  }
2808
0
}
Unexecuted instantiation: simdjson::internal::simdjson_result_base<unsigned long>::tie(unsigned long&, simdjson::error_code&) &&
Unexecuted instantiation: simdjson::internal::simdjson_result_base<bool>::tie(bool&, simdjson::error_code&) &&
Unexecuted instantiation: simdjson::internal::simdjson_result_base<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::tie(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, simdjson::error_code&) &&
2809
2810
template<typename T>
2811
0
simdjson_warn_unused simdjson_inline error_code simdjson_result_base<T>::get(T &value) && noexcept {
2812
0
  error_code error;
2813
0
  std::forward<simdjson_result_base<T>>(*this).tie(value, error);
2814
0
  return error;
2815
0
}
Unexecuted instantiation: simdjson::internal::simdjson_result_base<unsigned long>::get(unsigned long&) &&
Unexecuted instantiation: simdjson::internal::simdjson_result_base<bool>::get(bool&) &&
Unexecuted instantiation: simdjson::internal::simdjson_result_base<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::get(std::__1::basic_string_view<char, std::__1::char_traits<char> >&) &&
2816
2817
template<typename T>
2818
0
simdjson_inline error_code simdjson_result_base<T>::error() const noexcept {
2819
0
  return this->second;
2820
0
}
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::dom::array>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::dom::element>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::dom::object>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::dom::document_stream>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<bool>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<unsigned long>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::padded_string_view>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::padded_string>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<long>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<double>::error() const
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::fallback::number_type>::error() const
2821
2822
#if SIMDJSON_EXCEPTIONS
2823
2824
template<typename T>
2825
simdjson_inline T& simdjson_result_base<T>::value() & noexcept(false) {
2826
  if (error()) { throw simdjson_error(error()); }
2827
  return this->first;
2828
}
2829
2830
template<typename T>
2831
simdjson_inline T&& simdjson_result_base<T>::value() && noexcept(false) {
2832
  return std::forward<simdjson_result_base<T>>(*this).take_value();
2833
}
2834
2835
template<typename T>
2836
simdjson_inline T&& simdjson_result_base<T>::take_value() && noexcept(false) {
2837
  if (error()) { throw simdjson_error(error()); }
2838
  return std::forward<T>(this->first);
2839
}
2840
2841
template<typename T>
2842
simdjson_inline simdjson_result_base<T>::operator T&&() && noexcept(false) {
2843
  return std::forward<simdjson_result_base<T>>(*this).take_value();
2844
}
2845
2846
#endif // SIMDJSON_EXCEPTIONS
2847
2848
template<typename T>
2849
0
simdjson_inline const T& simdjson_result_base<T>::value_unsafe() const& noexcept {
2850
0
  return this->first;
2851
0
}
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::padded_string_view>::value_unsafe() const &
Unexecuted instantiation: simdjson::internal::simdjson_result_base<simdjson::padded_string>::value_unsafe() const &
2852
2853
template<typename T>
2854
simdjson_inline T&& simdjson_result_base<T>::value_unsafe() && noexcept {
2855
  return std::forward<T>(this->first);
2856
}
2857
2858
template<typename T>
2859
simdjson_inline simdjson_result_base<T>::simdjson_result_base(T &&value, error_code error) noexcept
2860
0
    : std::pair<T, error_code>(std::forward<T>(value), error) {}
Unexecuted instantiation: simdjson::internal::simdjson_result_base<bool>::simdjson_result_base(bool&&, simdjson::error_code)
Unexecuted instantiation: simdjson::internal::simdjson_result_base<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::simdjson_result_base(std::__1::basic_string_view<char, std::__1::char_traits<char> >&&, simdjson::error_code)
2861
template<typename T>
2862
simdjson_inline simdjson_result_base<T>::simdjson_result_base(error_code error) noexcept
2863
0
    : simdjson_result_base(T{}, error) {}
Unexecuted instantiation: simdjson::internal::simdjson_result_base<bool>::simdjson_result_base(simdjson::error_code)
Unexecuted instantiation: simdjson::internal::simdjson_result_base<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::simdjson_result_base(simdjson::error_code)
2864
template<typename T>
2865
simdjson_inline simdjson_result_base<T>::simdjson_result_base(T &&value) noexcept
2866
0
    : simdjson_result_base(std::forward<T>(value), SUCCESS) {}
Unexecuted instantiation: simdjson::internal::simdjson_result_base<bool>::simdjson_result_base(bool&&)
Unexecuted instantiation: simdjson::internal::simdjson_result_base<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::simdjson_result_base(std::__1::basic_string_view<char, std::__1::char_traits<char> >&&)
2867
template<typename T>
2868
simdjson_inline simdjson_result_base<T>::simdjson_result_base() noexcept
2869
    : simdjson_result_base(T{}, UNINITIALIZED) {}
2870
2871
} // namespace internal
2872
2873
///
2874
/// simdjson_result<T> inline implementation
2875
///
2876
2877
template<typename T>
2878
simdjson_inline void simdjson_result<T>::tie(T &value, error_code &error) && noexcept {
2879
  std::forward<internal::simdjson_result_base<T>>(*this).tie(value, error);
2880
}
2881
2882
template<typename T>
2883
0
simdjson_warn_unused simdjson_inline error_code simdjson_result<T>::get(T &value) && noexcept {
2884
0
  return std::forward<internal::simdjson_result_base<T>>(*this).get(value);
2885
0
}
Unexecuted instantiation: simdjson::simdjson_result<unsigned long>::get(unsigned long&) &&
Unexecuted instantiation: simdjson::simdjson_result<bool>::get(bool&) &&
Unexecuted instantiation: simdjson::simdjson_result<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::get(std::__1::basic_string_view<char, std::__1::char_traits<char> >&) &&
2886
2887
template<typename T>
2888
0
simdjson_inline error_code simdjson_result<T>::error() const noexcept {
2889
0
  return internal::simdjson_result_base<T>::error();
2890
0
}
Unexecuted instantiation: simdjson::simdjson_result<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::error() const
Unexecuted instantiation: simdjson::simdjson_result<bool>::error() const
Unexecuted instantiation: simdjson::simdjson_result<unsigned long>::error() const
Unexecuted instantiation: simdjson::simdjson_result<simdjson::padded_string_view>::error() const
Unexecuted instantiation: simdjson::simdjson_result<simdjson::padded_string>::error() const
Unexecuted instantiation: simdjson::simdjson_result<long>::error() const
Unexecuted instantiation: simdjson::simdjson_result<double>::error() const
Unexecuted instantiation: simdjson::simdjson_result<simdjson::fallback::number_type>::error() const
2891
2892
#if SIMDJSON_EXCEPTIONS
2893
2894
template<typename T>
2895
simdjson_inline T& simdjson_result<T>::value() & noexcept(false) {
2896
  return internal::simdjson_result_base<T>::value();
2897
}
2898
2899
template<typename T>
2900
simdjson_inline T&& simdjson_result<T>::value() && noexcept(false) {
2901
  return std::forward<internal::simdjson_result_base<T>>(*this).value();
2902
}
2903
2904
template<typename T>
2905
simdjson_inline T&& simdjson_result<T>::take_value() && noexcept(false) {
2906
  return std::forward<internal::simdjson_result_base<T>>(*this).take_value();
2907
}
2908
2909
template<typename T>
2910
simdjson_inline simdjson_result<T>::operator T&&() && noexcept(false) {
2911
  return std::forward<internal::simdjson_result_base<T>>(*this).take_value();
2912
}
2913
2914
#endif // SIMDJSON_EXCEPTIONS
2915
2916
template<typename T>
2917
0
simdjson_inline const T& simdjson_result<T>::value_unsafe() const& noexcept {
2918
0
  return internal::simdjson_result_base<T>::value_unsafe();
2919
0
}
Unexecuted instantiation: simdjson::simdjson_result<simdjson::padded_string_view>::value_unsafe() const &
Unexecuted instantiation: simdjson::simdjson_result<simdjson::padded_string>::value_unsafe() const &
2920
2921
template<typename T>
2922
simdjson_inline T&& simdjson_result<T>::value_unsafe() && noexcept {
2923
  return std::forward<internal::simdjson_result_base<T>>(*this).value_unsafe();
2924
}
2925
2926
template<typename T>
2927
simdjson_inline simdjson_result<T>::simdjson_result(T &&value, error_code error) noexcept
2928
    : internal::simdjson_result_base<T>(std::forward<T>(value), error) {}
2929
template<typename T>
2930
simdjson_inline simdjson_result<T>::simdjson_result(error_code error) noexcept
2931
0
    : internal::simdjson_result_base<T>(error) {}
Unexecuted instantiation: simdjson::simdjson_result<bool>::simdjson_result(simdjson::error_code)
Unexecuted instantiation: simdjson::simdjson_result<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::simdjson_result(simdjson::error_code)
2932
template<typename T>
2933
simdjson_inline simdjson_result<T>::simdjson_result(T &&value) noexcept
2934
0
    : internal::simdjson_result_base<T>(std::forward<T>(value)) {}
Unexecuted instantiation: simdjson::simdjson_result<bool>::simdjson_result(bool&&)
Unexecuted instantiation: simdjson::simdjson_result<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::simdjson_result(std::__1::basic_string_view<char, std::__1::char_traits<char> >&&)
2935
template<typename T>
2936
simdjson_inline simdjson_result<T>::simdjson_result() noexcept
2937
    : internal::simdjson_result_base<T>() {}
2938
2939
} // namespace simdjson
2940
2941
#endif // SIMDJSON_ERROR_INL_H
2942
/* end file simdjson/error-inl.h */
2943
/* including simdjson/implementation.h: #include "simdjson/implementation.h" */
2944
/* begin file simdjson/implementation.h */
2945
#ifndef SIMDJSON_IMPLEMENTATION_H
2946
#define SIMDJSON_IMPLEMENTATION_H
2947
2948
/* including simdjson/internal/atomic_ptr.h: #include "simdjson/internal/atomic_ptr.h" */
2949
/* begin file simdjson/internal/atomic_ptr.h */
2950
#ifndef SIMDJSON_INTERNAL_ATOMIC_PTR_H
2951
#define SIMDJSON_INTERNAL_ATOMIC_PTR_H
2952
2953
/* skipped duplicate #include "simdjson/base.h" */
2954
#include <atomic>
2955
2956
namespace simdjson {
2957
namespace internal {
2958
2959
template<typename T>
2960
class atomic_ptr {
2961
public:
2962
  atomic_ptr(T *_ptr) : ptr{_ptr} {}
2963
2964
  operator const T*() const { return ptr.load(); }
2965
  const T& operator*() const { return *ptr; }
2966
  const T* operator->() const { return ptr.load(); }
2967
2968
  operator T*() { return ptr.load(); }
2969
  T& operator*() { return *ptr; }
2970
0
  T* operator->() { return ptr.load(); }
2971
  atomic_ptr& operator=(T *_ptr) { ptr = _ptr; return *this; }
2972
2973
private:
2974
  std::atomic<T*> ptr;
2975
};
2976
2977
} // namespace internal
2978
} // namespace simdjson
2979
2980
#endif // SIMDJSON_INTERNAL_ATOMIC_PTR_H
2981
/* end file simdjson/internal/atomic_ptr.h */
2982
/* including simdjson/internal/dom_parser_implementation.h: #include "simdjson/internal/dom_parser_implementation.h" */
2983
/* begin file simdjson/internal/dom_parser_implementation.h */
2984
#ifndef SIMDJSON_INTERNAL_DOM_PARSER_IMPLEMENTATION_H
2985
#define SIMDJSON_INTERNAL_DOM_PARSER_IMPLEMENTATION_H
2986
2987
/* skipped duplicate #include "simdjson/base.h" */
2988
/* skipped duplicate #include "simdjson/error.h" */
2989
#include <memory>
2990
2991
namespace simdjson {
2992
2993
namespace dom {
2994
class document;
2995
} // namespace dom
2996
2997
/**
2998
* This enum is used with the dom_parser_implementation::stage1 function.
2999
* 1) The regular mode expects a fully formed JSON document.
3000
* 2) The streaming_partial mode expects a possibly truncated
3001
* input within a stream on JSON documents.
3002
* 3) The stream_final mode allows us to truncate final
3003
* unterminated strings. It is useful in conjunction with streaming_partial.
3004
*/
3005
enum class stage1_mode { regular, streaming_partial, streaming_final};
3006
3007
/**
3008
 * Returns true if mode == streaming_partial or mode == streaming_final
3009
 */
3010
0
inline bool is_streaming(stage1_mode mode) {
3011
0
  // performance note: it is probably faster to check that mode is different
3012
0
  // from regular than checking that it is either streaming_partial or streaming_final.
3013
0
  return (mode != stage1_mode::regular);
3014
0
  // return (mode == stage1_mode::streaming_partial || mode == stage1_mode::streaming_final);
3015
0
}
3016
3017
3018
namespace internal {
3019
3020
3021
/**
3022
 * An implementation of simdjson's DOM parser for a particular CPU architecture.
3023
 *
3024
 * This class is expected to be accessed only by pointer, and never move in memory (though the
3025
 * pointer can move).
3026
 */
3027
class dom_parser_implementation {
3028
public:
3029
3030
  /**
3031
   * @private For internal implementation use
3032
   *
3033
   * Run a full JSON parse on a single document (stage1 + stage2).
3034
   *
3035
   * Guaranteed only to be called when capacity > document length.
3036
   *
3037
   * Overridden by each implementation.
3038
   *
3039
   * @param buf The json document to parse. *MUST* be allocated up to len + SIMDJSON_PADDING bytes.
3040
   * @param len The length of the json document.
3041
   * @return The error code, or SUCCESS if there was no error.
3042
   */
3043
  simdjson_warn_unused virtual error_code parse(const uint8_t *buf, size_t len, dom::document &doc) noexcept = 0;
3044
3045
  /**
3046
   * @private For internal implementation use
3047
   *
3048
   * Stage 1 of the document parser.
3049
   *
3050
   * Guaranteed only to be called when capacity > document length.
3051
   *
3052
   * Overridden by each implementation.
3053
   *
3054
   * @param buf The json document to parse.
3055
   * @param len The length of the json document.
3056
   * @param streaming Whether this is being called by parser::parse_many.
3057
   * @return The error code, or SUCCESS if there was no error.
3058
   */
3059
  simdjson_warn_unused virtual error_code stage1(const uint8_t *buf, size_t len, stage1_mode streaming) noexcept = 0;
3060
3061
  /**
3062
   * @private For internal implementation use
3063
   *
3064
   * Stage 2 of the document parser.
3065
   *
3066
   * Called after stage1().
3067
   *
3068
   * Overridden by each implementation.
3069
   *
3070
   * @param doc The document to output to.
3071
   * @return The error code, or SUCCESS if there was no error.
3072
   */
3073
  simdjson_warn_unused virtual error_code stage2(dom::document &doc) noexcept = 0;
3074
3075
  /**
3076
   * @private For internal implementation use
3077
   *
3078
   * Stage 2 of the document parser for parser::parse_many.
3079
   *
3080
   * Guaranteed only to be called after stage1().
3081
   * Overridden by each implementation.
3082
   *
3083
   * @param doc The document to output to.
3084
   * @return The error code, SUCCESS if there was no error, or EMPTY if all documents have been parsed.
3085
   */
3086
  simdjson_warn_unused virtual error_code stage2_next(dom::document &doc) noexcept = 0;
3087
3088
  /**
3089
   * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There
3090
   * must be an unescaped quote terminating the string. It returns the final output
3091
   * position as pointer. In case of error (e.g., the string has bad escaped codes),
3092
   * then null_nullptrptr is returned. It is assumed that the output buffer is large
3093
   * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes +
3094
   * SIMDJSON_PADDING bytes.
3095
   *
3096
   * Overridden by each implementation.
3097
   *
3098
   * @param str pointer to the beginning of a valid UTF-8 JSON string, must end with an unescaped quote.
3099
   * @param dst pointer to a destination buffer, it must point a region in memory of sufficient size.
3100
   * @param allow_replacement whether we allow a replacement character when the UTF-8 contains unmatched surrogate pairs.
3101
   * @return end of the of the written region (exclusive) or nullptr in case of error.
3102
   */
3103
  simdjson_warn_unused virtual uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept = 0;
3104
3105
  /**
3106
   * Unescape a NON-valid UTF-8 string from src to dst, stopping at a final unescaped quote. There
3107
   * must be an unescaped quote terminating the string. It returns the final output
3108
   * position as pointer. In case of error (e.g., the string has bad escaped codes),
3109
   * then null_nullptrptr is returned. It is assumed that the output buffer is large
3110
   * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes +
3111
   * SIMDJSON_PADDING bytes.
3112
   *
3113
   * Overridden by each implementation.
3114
   *
3115
   * @param str pointer to the beginning of a possibly invalid UTF-8 JSON string, must end with an unescaped quote.
3116
   * @param dst pointer to a destination buffer, it must point a region in memory of sufficient size.
3117
   * @return end of the of the written region (exclusive) or nullptr in case of error.
3118
   */
3119
  simdjson_warn_unused virtual uint8_t *parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept = 0;
3120
3121
  /**
3122
   * Change the capacity of this parser.
3123
   *
3124
   * The capacity can never exceed SIMDJSON_MAXSIZE_BYTES (e.g., 4 GB)
3125
   * and an CAPACITY error is returned if it is attempted.
3126
   *
3127
   * Generally used for reallocation.
3128
   *
3129
   * @param capacity The new capacity.
3130
   * @param max_depth The new max_depth.
3131
   * @return The error code, or SUCCESS if there was no error.
3132
   */
3133
  virtual error_code set_capacity(size_t capacity) noexcept = 0;
3134
3135
  /**
3136
   * Change the max depth of this parser.
3137
   *
3138
   * Generally used for reallocation.
3139
   *
3140
   * @param capacity The new capacity.
3141
   * @param max_depth The new max_depth.
3142
   * @return The error code, or SUCCESS if there was no error.
3143
   */
3144
  virtual error_code set_max_depth(size_t max_depth) noexcept = 0;
3145
3146
  /**
3147
   * Deallocate this parser.
3148
   */
3149
  virtual ~dom_parser_implementation() = default;
3150
3151
  /** Number of structural indices passed from stage 1 to stage 2 */
3152
  uint32_t n_structural_indexes{0};
3153
  /** Structural indices passed from stage 1 to stage 2 */
3154
  std::unique_ptr<uint32_t[]> structural_indexes{};
3155
  /** Next structural index to parse */
3156
  uint32_t next_structural_index{0};
3157
3158
  /**
3159
   * The largest document this parser can support without reallocating.
3160
   *
3161
   * @return Current capacity, in bytes.
3162
   */
3163
  simdjson_inline size_t capacity() const noexcept;
3164
3165
  /**
3166
   * The maximum level of nested object and arrays supported by this parser.
3167
   *
3168
   * @return Maximum depth, in bytes.
3169
   */
3170
  simdjson_inline size_t max_depth() const noexcept;
3171
3172
  /**
3173
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
3174
   * and `max_depth` depth.
3175
   *
3176
   * @param capacity The new capacity.
3177
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
3178
   * @return The error, if there is one.
3179
   */
3180
  simdjson_warn_unused inline error_code allocate(size_t capacity, size_t max_depth) noexcept;
3181
3182
3183
protected:
3184
  /**
3185
   * The maximum document length this parser supports.
3186
   *
3187
   * Buffers are large enough to handle any document up to this length.
3188
   */
3189
  size_t _capacity{0};
3190
3191
  /**
3192
   * The maximum depth (number of nested objects and arrays) supported by this parser.
3193
   *
3194
   * Defaults to DEFAULT_MAX_DEPTH.
3195
   */
3196
  size_t _max_depth{0};
3197
3198
  // Declaring these so that subclasses can use them to implement their constructors.
3199
  simdjson_inline dom_parser_implementation() noexcept;
3200
  simdjson_inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
3201
  simdjson_inline dom_parser_implementation &operator=(dom_parser_implementation &&other) noexcept;
3202
3203
  simdjson_inline dom_parser_implementation(const dom_parser_implementation &) noexcept = delete;
3204
  simdjson_inline dom_parser_implementation &operator=(const dom_parser_implementation &other) noexcept = delete;
3205
}; // class dom_parser_implementation
3206
3207
simdjson_inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
3208
simdjson_inline dom_parser_implementation::dom_parser_implementation(dom_parser_implementation &&other) noexcept = default;
3209
0
simdjson_inline dom_parser_implementation &dom_parser_implementation::operator=(dom_parser_implementation &&other) noexcept = default;
3210
3211
0
simdjson_inline size_t dom_parser_implementation::capacity() const noexcept {
3212
0
  return _capacity;
3213
0
}
3214
3215
0
simdjson_inline size_t dom_parser_implementation::max_depth() const noexcept {
3216
0
  return _max_depth;
3217
0
}
3218
3219
simdjson_warn_unused
3220
0
inline error_code dom_parser_implementation::allocate(size_t capacity, size_t max_depth) noexcept {
3221
0
  if (this->max_depth() != max_depth) {
3222
0
    error_code err = set_max_depth(max_depth);
3223
0
    if (err) { return err; }
3224
0
  }
3225
0
  if (_capacity != capacity) {
3226
0
    error_code err = set_capacity(capacity);
3227
0
    if (err) { return err; }
3228
0
  }
3229
0
  return SUCCESS;
3230
0
}
3231
3232
} // namespace internal
3233
} // namespace simdjson
3234
3235
#endif // SIMDJSON_INTERNAL_DOM_PARSER_IMPLEMENTATION_H
3236
/* end file simdjson/internal/dom_parser_implementation.h */
3237
3238
#include <memory>
3239
3240
namespace simdjson {
3241
3242
/**
3243
 * Validate the UTF-8 string.
3244
 *
3245
 * @param buf the string to validate.
3246
 * @param len the length of the string in bytes.
3247
 * @return true if the string is valid UTF-8.
3248
 */
3249
simdjson_warn_unused bool validate_utf8(const char * buf, size_t len) noexcept;
3250
/**
3251
 * Validate the UTF-8 string.
3252
 *
3253
 * @param sv the string_view to validate.
3254
 * @return true if the string is valid UTF-8.
3255
 */
3256
0
simdjson_inline simdjson_warn_unused bool validate_utf8(const std::string_view sv) noexcept {
3257
0
  return validate_utf8(sv.data(), sv.size());
3258
0
}
3259
3260
/**
3261
 * Validate the UTF-8 string.
3262
 *
3263
 * @param p the string to validate.
3264
 * @return true if the string is valid UTF-8.
3265
 */
3266
0
simdjson_inline simdjson_warn_unused bool validate_utf8(const std::string& s) noexcept {
3267
0
  return validate_utf8(s.data(), s.size());
3268
0
}
3269
3270
/**
3271
 * An implementation of simdjson for a particular CPU architecture.
3272
 *
3273
 * Also used to maintain the currently active implementation. The active implementation is
3274
 * automatically initialized on first use to the most advanced implementation supported by the host.
3275
 */
3276
class implementation {
3277
public:
3278
3279
  /**
3280
   * The name of this implementation.
3281
   *
3282
   *     const implementation *impl = simdjson::get_active_implementation();
3283
   *     cout << "simdjson is optimized for " << impl->name() << "(" << impl->description() << ")" << endl;
3284
   *
3285
   * @return the name of the implementation, e.g. "haswell", "westmere", "arm64".
3286
   */
3287
0
  virtual const std::string &name() const { return _name; }
3288
3289
  /**
3290
   * The description of this implementation.
3291
   *
3292
   *     const implementation *impl = simdjson::get_active_implementation();
3293
   *     cout << "simdjson is optimized for " << impl->name() << "(" << impl->description() << ")" << endl;
3294
   *
3295
   * @return the description of the implementation, e.g. "Intel/AMD AVX2", "Intel/AMD SSE4.2", "ARM NEON".
3296
   */
3297
0
  virtual const std::string &description() const { return _description; }
3298
3299
  /**
3300
   * The instruction sets this implementation is compiled against
3301
   * and the current CPU match. This function may poll the current CPU/system
3302
   * and should therefore not be called too often if performance is a concern.
3303
   *
3304
   * @return true if the implementation can be safely used on the current system (determined at runtime).
3305
   */
3306
  bool supported_by_runtime_system() const;
3307
3308
  /**
3309
   * @private For internal implementation use
3310
   *
3311
   * The instruction sets this implementation is compiled against.
3312
   *
3313
   * @return a mask of all required `internal::instruction_set::` values.
3314
   */
3315
0
  virtual uint32_t required_instruction_sets() const { return _required_instruction_sets; }
3316
3317
  /**
3318
   * @private For internal implementation use
3319
   *
3320
   *     const implementation *impl = simdjson::get_active_implementation();
3321
   *     cout << "simdjson is optimized for " << impl->name() << "(" << impl->description() << ")" << endl;
3322
   *
3323
   * @param capacity The largest document that will be passed to the parser.
3324
   * @param max_depth The maximum JSON object/array nesting this parser is expected to handle.
3325
   * @param dst The place to put the resulting parser implementation.
3326
   * @return the error code, or SUCCESS if there was no error.
3327
   */
3328
  virtual error_code create_dom_parser_implementation(
3329
    size_t capacity,
3330
    size_t max_depth,
3331
    std::unique_ptr<internal::dom_parser_implementation> &dst
3332
  ) const noexcept = 0;
3333
3334
  /**
3335
   * @private For internal implementation use
3336
   *
3337
   * Minify the input string assuming that it represents a JSON string, does not parse or validate.
3338
   *
3339
   * Overridden by each implementation.
3340
   *
3341
   * @param buf the json document to minify.
3342
   * @param len the length of the json document.
3343
   * @param dst the buffer to write the minified document to. *MUST* be allocated up to len + SIMDJSON_PADDING bytes.
3344
   * @param dst_len the number of bytes written. Output only.
3345
   * @return the error code, or SUCCESS if there was no error.
3346
   */
3347
  simdjson_warn_unused virtual error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept = 0;
3348
3349
3350
  /**
3351
   * Validate the UTF-8 string.
3352
   *
3353
   * Overridden by each implementation.
3354
   *
3355
   * @param buf the string to validate.
3356
   * @param len the length of the string in bytes.
3357
   * @return true if and only if the string is valid UTF-8.
3358
   */
3359
  simdjson_warn_unused virtual bool validate_utf8(const char *buf, size_t len) const noexcept = 0;
3360
3361
protected:
3362
  /** @private Construct an implementation with the given name and description. For subclasses. */
3363
  simdjson_inline implementation(
3364
    std::string_view name,
3365
    std::string_view description,
3366
    uint32_t required_instruction_sets
3367
  ) :
3368
    _name(name),
3369
    _description(description),
3370
    _required_instruction_sets(required_instruction_sets)
3371
0
  {
3372
0
  }
3373
  virtual ~implementation()=default;
3374
3375
private:
3376
  /**
3377
   * The name of this implementation.
3378
   */
3379
  const std::string _name;
3380
3381
  /**
3382
   * The description of this implementation.
3383
   */
3384
  const std::string _description;
3385
3386
  /**
3387
   * Instruction sets required for this implementation.
3388
   */
3389
  const uint32_t _required_instruction_sets;
3390
};
3391
3392
/** @private */
3393
namespace internal {
3394
3395
/**
3396
 * The list of available implementations compiled into simdjson.
3397
 */
3398
class available_implementation_list {
3399
public:
3400
  /** Get the list of available implementations compiled into simdjson */
3401
0
  simdjson_inline available_implementation_list() {}
3402
  /** Number of implementations */
3403
  size_t size() const noexcept;
3404
  /** STL const begin() iterator */
3405
  const implementation * const *begin() const noexcept;
3406
  /** STL const end() iterator */
3407
  const implementation * const *end() const noexcept;
3408
3409
  /**
3410
   * Get the implementation with the given name.
3411
   *
3412
   * Case sensitive.
3413
   *
3414
   *     const implementation *impl = simdjson::get_available_implementations()["westmere"];
3415
   *     if (!impl) { exit(1); }
3416
   *     if (!imp->supported_by_runtime_system()) { exit(1); }
3417
   *     simdjson::get_active_implementation() = impl;
3418
   *
3419
   * @param name the implementation to find, e.g. "westmere", "haswell", "arm64"
3420
   * @return the implementation, or nullptr if the parse failed.
3421
   */
3422
0
  const implementation * operator[](const std::string_view &name) const noexcept {
3423
0
    for (const implementation * impl : *this) {
3424
0
      if (impl->name() == name) { return impl; }
3425
0
    }
3426
0
    return nullptr;
3427
0
  }
3428
3429
  /**
3430
   * Detect the most advanced implementation supported by the current host.
3431
   *
3432
   * This is used to initialize the implementation on startup.
3433
   *
3434
   *     const implementation *impl = simdjson::available_implementation::detect_best_supported();
3435
   *     simdjson::get_active_implementation() = impl;
3436
   *
3437
   * @return the most advanced supported implementation for the current host, or an
3438
   *         implementation that returns UNSUPPORTED_ARCHITECTURE if there is no supported
3439
   *         implementation. Will never return nullptr.
3440
   */
3441
  const implementation *detect_best_supported() const noexcept;
3442
};
3443
3444
} // namespace internal
3445
3446
/**
3447
 * The list of available implementations compiled into simdjson.
3448
 */
3449
extern SIMDJSON_DLLIMPORTEXPORT const internal::available_implementation_list& get_available_implementations();
3450
3451
/**
3452
  * The active implementation.
3453
  *
3454
  * Automatically initialized on first use to the most advanced implementation supported by this hardware.
3455
  */
3456
extern SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr<const implementation>& get_active_implementation();
3457
3458
} // namespace simdjson
3459
3460
#endif // SIMDJSON_IMPLEMENTATION_H
3461
/* end file simdjson/implementation.h */
3462
/* including simdjson/minify.h: #include "simdjson/minify.h" */
3463
/* begin file simdjson/minify.h */
3464
#ifndef SIMDJSON_MINIFY_H
3465
#define SIMDJSON_MINIFY_H
3466
3467
/* skipped duplicate #include "simdjson/base.h" */
3468
/* including simdjson/padded_string.h: #include "simdjson/padded_string.h" */
3469
/* begin file simdjson/padded_string.h */
3470
#ifndef SIMDJSON_PADDED_STRING_H
3471
#define SIMDJSON_PADDED_STRING_H
3472
3473
/* skipped duplicate #include "simdjson/base.h" */
3474
/* skipped duplicate #include "simdjson/error.h" */
3475
3476
/* skipped duplicate #include "simdjson/error-inl.h" */
3477
3478
#include <cstring>
3479
#include <memory>
3480
#include <string>
3481
#include <ostream>
3482
3483
namespace simdjson {
3484
3485
class padded_string_view;
3486
3487
/**
3488
 * String with extra allocation for ease of use with parser::parse()
3489
 *
3490
 * This is a move-only class, it cannot be copied.
3491
 */
3492
struct padded_string final {
3493
3494
  /**
3495
   * Create a new, empty padded string.
3496
   */
3497
  explicit inline padded_string() noexcept;
3498
  /**
3499
   * Create a new padded string buffer.
3500
   *
3501
   * @param length the size of the string.
3502
   */
3503
  explicit inline padded_string(size_t length) noexcept;
3504
  /**
3505
   * Create a new padded string by copying the given input.
3506
   *
3507
   * @param data the buffer to copy
3508
   * @param length the number of bytes to copy
3509
   */
3510
  explicit inline padded_string(const char *data, size_t length) noexcept;
3511
#ifdef __cpp_char8_t
3512
  explicit inline padded_string(const char8_t *data, size_t length) noexcept;
3513
#endif
3514
  /**
3515
   * Create a new padded string by copying the given input.
3516
   *
3517
   * @param str_ the string to copy
3518
   */
3519
  inline padded_string(const std::string & str_ ) noexcept;
3520
  /**
3521
   * Create a new padded string by copying the given input.
3522
   *
3523
   * @param sv_ the string to copy
3524
   */
3525
  inline padded_string(std::string_view sv_) noexcept;
3526
  /**
3527
   * Move one padded string into another.
3528
   *
3529
   * The original padded string will be reduced to zero capacity.
3530
   *
3531
   * @param o the string to move.
3532
   */
3533
  inline padded_string(padded_string &&o) noexcept;
3534
  /**
3535
   * Move one padded string into another.
3536
   *
3537
   * The original padded string will be reduced to zero capacity.
3538
   *
3539
   * @param o the string to move.
3540
   */
3541
  inline padded_string &operator=(padded_string &&o) noexcept;
3542
  inline void swap(padded_string &o) noexcept;
3543
  ~padded_string() noexcept;
3544
3545
  /**
3546
   * The length of the string.
3547
   *
3548
   * Does not include padding.
3549
   */
3550
  size_t size() const noexcept;
3551
3552
  /**
3553
   * The length of the string.
3554
   *
3555
   * Does not include padding.
3556
   */
3557
  size_t length() const noexcept;
3558
3559
  /**
3560
   * The string data.
3561
   **/
3562
  const char *data() const noexcept;
3563
0
  const uint8_t *u8data() const noexcept { return static_cast<const uint8_t*>(static_cast<const void*>(data_ptr));}
3564
3565
  /**
3566
   * The string data.
3567
   **/
3568
  char *data() noexcept;
3569
3570
  /**
3571
   * Create a std::string_view with the same content.
3572
   */
3573
  operator std::string_view() const;
3574
3575
  /**
3576
   * Create a padded_string_view with the same content.
3577
   */
3578
  operator padded_string_view() const noexcept;
3579
3580
  /**
3581
   * Load this padded string from a file.
3582
   *
3583
   * @return IO_ERROR on error. Be mindful that on some 32-bit systems,
3584
   * the file size might be limited to 2 GB.
3585
   *
3586
   * @param path the path to the file.
3587
   **/
3588
  inline static simdjson_result<padded_string> load(std::string_view path) noexcept;
3589
3590
private:
3591
  padded_string &operator=(const padded_string &o) = delete;
3592
  padded_string(const padded_string &o) = delete;
3593
3594
  size_t viable_size{0};
3595
  char *data_ptr{nullptr};
3596
3597
}; // padded_string
3598
3599
/**
3600
 * Send padded_string instance to an output stream.
3601
 *
3602
 * @param out The output stream.
3603
 * @param s The padded_string instance.
3604
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
3605
 */
3606
0
inline std::ostream& operator<<(std::ostream& out, const padded_string& s) { return out << s.data(); }
3607
3608
#if SIMDJSON_EXCEPTIONS
3609
/**
3610
 * Send padded_string instance to an output stream.
3611
 *
3612
 * @param out The output stream.
3613
 * @param s The padded_string instance.
3614
  * @throw simdjson_error if the result being printed has an error. If there is an error with the
3615
 *        underlying output stream, that error will be propagated (simdjson_error will not be
3616
 *        thrown).
3617
 */
3618
inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string> &s) noexcept(false) { return out << s.value(); }
3619
#endif
3620
3621
} // namespace simdjson
3622
3623
// This is deliberately outside of simdjson so that people get it without having to use the namespace
3624
inline simdjson::padded_string operator "" _padded(const char *str, size_t len);
3625
#ifdef __cpp_char8_t
3626
inline simdjson::padded_string operator "" _padded(const char8_t *str, size_t len);
3627
#endif
3628
3629
namespace simdjson {
3630
namespace internal {
3631
3632
// The allocate_padded_buffer function is a low-level function to allocate memory
3633
// with padding so we can read past the "length" bytes safely. It is used by
3634
// the padded_string class automatically. It returns nullptr in case
3635
// of error: the caller should check for a null pointer.
3636
// The length parameter is the maximum size in bytes of the string.
3637
// The caller is responsible to free the memory (e.g., delete[] (...)).
3638
inline char *allocate_padded_buffer(size_t length) noexcept;
3639
3640
} // namespace internal
3641
} // namespace simdjson
3642
3643
#endif // SIMDJSON_PADDED_STRING_H
3644
/* end file simdjson/padded_string.h */
3645
#include <string>
3646
#include <ostream>
3647
#include <sstream>
3648
3649
namespace simdjson {
3650
3651
/**
3652
 *
3653
 * Minify the input string assuming that it represents a JSON string, does not parse or validate.
3654
 * This function is much faster than parsing a JSON string and then writing a minified version of it.
3655
 * However, it does not validate the input. It will merely return an error in simple cases (e.g., if
3656
 * there is a string that was never terminated).
3657
 *
3658
 *
3659
 * @param buf the json document to minify.
3660
 * @param len the length of the json document.
3661
 * @param dst the buffer to write the minified document to. *MUST* be allocated up to len bytes.
3662
 * @param dst_len the number of bytes written. Output only.
3663
 * @return the error code, or SUCCESS if there was no error.
3664
 */
3665
simdjson_warn_unused error_code minify(const char *buf, size_t len, char *dst, size_t &dst_len) noexcept;
3666
3667
} // namespace simdjson
3668
3669
#endif // SIMDJSON_MINIFY_H
3670
/* end file simdjson/minify.h */
3671
/* skipped duplicate #include "simdjson/padded_string.h" */
3672
/* including simdjson/padded_string-inl.h: #include "simdjson/padded_string-inl.h" */
3673
/* begin file simdjson/padded_string-inl.h */
3674
#ifndef SIMDJSON_PADDED_STRING_INL_H
3675
#define SIMDJSON_PADDED_STRING_INL_H
3676
3677
/* skipped duplicate #include "simdjson/padded_string.h" */
3678
/* including simdjson/padded_string_view.h: #include "simdjson/padded_string_view.h" */
3679
/* begin file simdjson/padded_string_view.h */
3680
#ifndef SIMDJSON_PADDED_STRING_VIEW_H
3681
#define SIMDJSON_PADDED_STRING_VIEW_H
3682
3683
/* skipped duplicate #include "simdjson/portability.h" */
3684
/* skipped duplicate #include "simdjson/base.h" // for SIMDJSON_PADDING */
3685
/* skipped duplicate #include "simdjson/error.h" */
3686
3687
#include <cstring>
3688
#include <memory>
3689
#include <string>
3690
#include <ostream>
3691
3692
namespace simdjson {
3693
3694
/**
3695
 * User-provided string that promises it has extra padded bytes at the end for use with parser::parse().
3696
 */
3697
class padded_string_view : public std::string_view {
3698
private:
3699
  size_t _capacity;
3700
3701
public:
3702
  /** Create an empty padded_string_view. */
3703
  inline padded_string_view() noexcept = default;
3704
3705
  /**
3706
   * Promise the given buffer has at least SIMDJSON_PADDING extra bytes allocated to it.
3707
   *
3708
   * @param s The string.
3709
   * @param len The length of the string (not including padding).
3710
   * @param capacity The allocated length of the string, including padding. If the capacity is less
3711
   *       than the length, the capacity will be set to the length.
3712
   */
3713
  explicit inline padded_string_view(const char* s, size_t len, size_t capacity) noexcept;
3714
  /** overload explicit inline padded_string_view(const char* s, size_t len) noexcept */
3715
  explicit inline padded_string_view(const uint8_t* s, size_t len, size_t capacity) noexcept;
3716
#ifdef __cpp_char8_t
3717
  explicit inline padded_string_view(const char8_t* s, size_t len, size_t capacity) noexcept;
3718
#endif
3719
  /**
3720
   * Promise the given string has at least SIMDJSON_PADDING extra bytes allocated to it.
3721
   *
3722
   * The capacity of the string will be used to determine its padding.
3723
   *
3724
   * @param s The string.
3725
   */
3726
  explicit inline padded_string_view(const std::string &s) noexcept;
3727
3728
  /**
3729
   * Promise the given string_view has at least SIMDJSON_PADDING extra bytes allocated to it.
3730
   *
3731
   * @param s The string.
3732
   * @param capacity The allocated length of the string, including padding. If the capacity is less
3733
   *      than the length, the capacity will be set to the length.
3734
   */
3735
  explicit inline padded_string_view(std::string_view s, size_t capacity) noexcept;
3736
3737
  /** The number of allocated bytes. */
3738
  inline size_t capacity() const noexcept;
3739
3740
  /**
3741
   * Remove the UTF-8 Byte Order Mark (BOM) if it exists.
3742
   *
3743
   * @return whether a BOM was found and removed
3744
   */
3745
  inline bool remove_utf8_bom() noexcept;
3746
3747
  /** The amount of padding on the string (capacity() - length()) */
3748
  inline size_t padding() const noexcept;
3749
3750
}; // padded_string_view
3751
3752
#if SIMDJSON_EXCEPTIONS
3753
/**
3754
 * Send padded_string instance to an output stream.
3755
 *
3756
 * @param out The output stream.
3757
 * @param s The padded_string_view.
3758
 * @throw simdjson_error if the result being printed has an error. If there is an error with the
3759
 *        underlying output stream, that error will be propagated (simdjson_error will not be
3760
 *        thrown).
3761
 */
3762
inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string_view> &s) noexcept(false);
3763
#endif
3764
3765
} // namespace simdjson
3766
3767
#endif // SIMDJSON_PADDED_STRING_VIEW_H
3768
/* end file simdjson/padded_string_view.h */
3769
3770
/* skipped duplicate #include "simdjson/error-inl.h" */
3771
/* including simdjson/padded_string_view-inl.h: #include "simdjson/padded_string_view-inl.h" */
3772
/* begin file simdjson/padded_string_view-inl.h */
3773
#ifndef SIMDJSON_PADDED_STRING_VIEW_INL_H
3774
#define SIMDJSON_PADDED_STRING_VIEW_INL_H
3775
3776
/* skipped duplicate #include "simdjson/padded_string_view.h" */
3777
/* skipped duplicate #include "simdjson/error-inl.h" */
3778
3779
#include <cstring> /* memcmp */
3780
3781
namespace simdjson {
3782
3783
inline padded_string_view::padded_string_view(const char* s, size_t len, size_t capacity) noexcept
3784
  : std::string_view(s, len), _capacity(capacity)
3785
{
3786
  if(_capacity < len) { _capacity = len; }
3787
}
3788
3789
inline padded_string_view::padded_string_view(const uint8_t* s, size_t len, size_t capacity) noexcept
3790
  : padded_string_view(reinterpret_cast<const char*>(s), len, capacity)
3791
{
3792
}
3793
#ifdef __cpp_char8_t
3794
inline padded_string_view::padded_string_view(const char8_t* s, size_t len, size_t capacity) noexcept
3795
  : padded_string_view(reinterpret_cast<const char*>(s), len, capacity)
3796
{
3797
}
3798
#endif
3799
inline padded_string_view::padded_string_view(const std::string &s) noexcept
3800
0
  : std::string_view(s), _capacity(s.capacity())
3801
0
{
3802
0
}
3803
3804
inline padded_string_view::padded_string_view(std::string_view s, size_t capacity) noexcept
3805
  : std::string_view(s), _capacity(capacity)
3806
{
3807
  if(_capacity < s.length()) { _capacity = s.length(); }
3808
}
3809
3810
0
inline size_t padded_string_view::capacity() const noexcept { return _capacity; }
3811
3812
0
inline size_t padded_string_view::padding() const noexcept { return capacity() - length(); }
3813
3814
0
inline bool padded_string_view::remove_utf8_bom() noexcept {
3815
0
  if(length() < 3) { return false; }
3816
0
  if (std::memcmp(data(), "\xEF\xBB\xBF", 3) == 0) {
3817
0
    remove_prefix(3);
3818
0
    _capacity -= 3;
3819
0
    return true;
3820
0
  }
3821
0
  return false;
3822
0
}
3823
3824
#if SIMDJSON_EXCEPTIONS
3825
inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string_view> &s) noexcept(false) { return out << s.value(); }
3826
#endif
3827
3828
} // namespace simdjson
3829
3830
3831
#endif // SIMDJSON_PADDED_STRING_VIEW_INL_H
3832
/* end file simdjson/padded_string_view-inl.h */
3833
3834
#include <climits>
3835
3836
namespace simdjson {
3837
namespace internal {
3838
3839
// The allocate_padded_buffer function is a low-level function to allocate memory
3840
// with padding so we can read past the "length" bytes safely. It is used by
3841
// the padded_string class automatically. It returns nullptr in case
3842
// of error: the caller should check for a null pointer.
3843
// The length parameter is the maximum size in bytes of the string.
3844
// The caller is responsible to free the memory (e.g., delete[] (...)).
3845
0
inline char *allocate_padded_buffer(size_t length) noexcept {
3846
0
  const size_t totalpaddedlength = length + SIMDJSON_PADDING;
3847
0
  if(totalpaddedlength<length) {
3848
0
    // overflow
3849
0
    return nullptr;
3850
0
  }
3851
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3852
0
  // avoid getting out of memory
3853
0
  if (totalpaddedlength>(1UL<<20)) {
3854
0
    return nullptr;
3855
0
  }
3856
0
#endif
3857
0
3858
0
  char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
3859
0
  if (padded_buffer == nullptr) {
3860
0
    return nullptr;
3861
0
  }
3862
0
  // We write nulls in the padded region to avoid having uninitialized
3863
0
  // content which may trigger warning for some sanitizers
3864
0
  std::memset(padded_buffer + length, 0, totalpaddedlength - length);
3865
0
  return padded_buffer;
3866
0
} // allocate_padded_buffer()
3867
3868
} // namespace internal
3869
3870
3871
inline padded_string::padded_string() noexcept = default;
3872
inline padded_string::padded_string(size_t length) noexcept
3873
    : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
3874
}
3875
inline padded_string::padded_string(const char *data, size_t length) noexcept
3876
    : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
3877
  if ((data != nullptr) && (data_ptr != nullptr)) {
3878
    std::memcpy(data_ptr, data, length);
3879
  }
3880
}
3881
#ifdef __cpp_char8_t
3882
inline padded_string::padded_string(const char8_t *data, size_t length) noexcept
3883
    : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
3884
  if ((data != nullptr) && (data_ptr != nullptr)) {
3885
    std::memcpy(data_ptr, reinterpret_cast<const char *>(data), length);
3886
  }
3887
}
3888
#endif
3889
// note: do not pass std::string arguments by value
3890
inline padded_string::padded_string(const std::string & str_ ) noexcept
3891
    : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) {
3892
  if (data_ptr != nullptr) {
3893
    std::memcpy(data_ptr, str_.data(), str_.size());
3894
  }
3895
}
3896
// note: do pass std::string_view arguments by value
3897
inline padded_string::padded_string(std::string_view sv_) noexcept
3898
    : viable_size(sv_.size()), data_ptr(internal::allocate_padded_buffer(sv_.size())) {
3899
  if(simdjson_unlikely(!data_ptr)) {
3900
    //allocation failed or zero size
3901
    viable_size = 0;
3902
    return;
3903
  }
3904
  if (sv_.size()) {
3905
    std::memcpy(data_ptr, sv_.data(), sv_.size());
3906
  }
3907
}
3908
inline padded_string::padded_string(padded_string &&o) noexcept
3909
    : viable_size(o.viable_size), data_ptr(o.data_ptr) {
3910
  o.data_ptr = nullptr; // we take ownership
3911
}
3912
3913
0
inline padded_string &padded_string::operator=(padded_string &&o) noexcept {
3914
0
  delete[] data_ptr;
3915
0
  data_ptr = o.data_ptr;
3916
0
  viable_size = o.viable_size;
3917
0
  o.data_ptr = nullptr; // we take ownership
3918
0
  o.viable_size = 0;
3919
0
  return *this;
3920
0
}
3921
3922
0
inline void padded_string::swap(padded_string &o) noexcept {
3923
0
  size_t tmp_viable_size = viable_size;
3924
0
  char *tmp_data_ptr = data_ptr;
3925
0
  viable_size = o.viable_size;
3926
0
  data_ptr = o.data_ptr;
3927
0
  o.data_ptr = tmp_data_ptr;
3928
0
  o.viable_size = tmp_viable_size;
3929
0
}
3930
3931
inline padded_string::~padded_string() noexcept {
3932
  delete[] data_ptr;
3933
}
3934
3935
0
inline size_t padded_string::size() const noexcept { return viable_size; }
3936
3937
0
inline size_t padded_string::length() const noexcept { return viable_size; }
3938
3939
0
inline const char *padded_string::data() const noexcept { return data_ptr; }
3940
3941
0
inline char *padded_string::data() noexcept { return data_ptr; }
3942
3943
0
inline padded_string::operator std::string_view() const { return std::string_view(data(), length()); }
3944
3945
0
inline padded_string::operator padded_string_view() const noexcept {
3946
0
  return padded_string_view(data(), length(), length() + SIMDJSON_PADDING);
3947
0
}
3948
3949
0
inline simdjson_result<padded_string> padded_string::load(std::string_view filename) noexcept {
3950
0
  // Open the file
3951
0
  SIMDJSON_PUSH_DISABLE_WARNINGS
3952
0
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
3953
0
  std::FILE *fp = std::fopen(filename.data(), "rb");
3954
0
  SIMDJSON_POP_DISABLE_WARNINGS
3955
0
3956
0
  if (fp == nullptr) {
3957
0
    return IO_ERROR;
3958
0
  }
3959
0
3960
0
  // Get the file size
3961
0
  int ret;
3962
0
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
3963
0
  ret = _fseeki64(fp, 0, SEEK_END);
3964
0
#else
3965
0
  ret = std::fseek(fp, 0, SEEK_END);
3966
0
#endif // _WIN64
3967
0
  if(ret < 0) {
3968
0
    std::fclose(fp);
3969
0
    return IO_ERROR;
3970
0
  }
3971
0
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
3972
0
  __int64 llen = _ftelli64(fp);
3973
0
  if(llen == -1L) {
3974
0
    std::fclose(fp);
3975
0
    return IO_ERROR;
3976
0
  }
3977
0
#else
3978
0
  long llen = std::ftell(fp);
3979
0
  if((llen < 0) || (llen == LONG_MAX)) {
3980
0
    std::fclose(fp);
3981
0
    return IO_ERROR;
3982
0
  }
3983
0
#endif
3984
0
3985
0
  // Allocate the padded_string
3986
0
  size_t len = static_cast<size_t>(llen);
3987
0
  padded_string s(len);
3988
0
  if (s.data() == nullptr) {
3989
0
    std::fclose(fp);
3990
0
    return MEMALLOC;
3991
0
  }
3992
0
3993
0
  // Read the padded_string
3994
0
  std::rewind(fp);
3995
0
  size_t bytes_read = std::fread(s.data(), 1, len, fp);
3996
0
  if (std::fclose(fp) != 0 || bytes_read != len) {
3997
0
    return IO_ERROR;
3998
0
  }
3999
0
4000
0
  return s;
4001
0
}
4002
4003
} // namespace simdjson
4004
4005
0
inline simdjson::padded_string operator "" _padded(const char *str, size_t len) {
4006
0
  return simdjson::padded_string(str, len);
4007
0
}
4008
#ifdef __cpp_char8_t
4009
inline simdjson::padded_string operator "" _padded(const char8_t *str, size_t len) {
4010
  return simdjson::padded_string(reinterpret_cast<const char8_t *>(str), len);
4011
}
4012
#endif
4013
#endif // SIMDJSON_PADDED_STRING_INL_H
4014
/* end file simdjson/padded_string-inl.h */
4015
/* skipped duplicate #include "simdjson/padded_string_view.h" */
4016
/* skipped duplicate #include "simdjson/padded_string_view-inl.h" */
4017
4018
/* including simdjson/dom.h: #include "simdjson/dom.h" */
4019
/* begin file simdjson/dom.h */
4020
#ifndef SIMDJSON_DOM_H
4021
#define SIMDJSON_DOM_H
4022
4023
/* including simdjson/dom/base.h: #include "simdjson/dom/base.h" */
4024
/* begin file simdjson/dom/base.h */
4025
#ifndef SIMDJSON_DOM_BASE_H
4026
#define SIMDJSON_DOM_BASE_H
4027
4028
/* skipped duplicate #include "simdjson/base.h" */
4029
4030
namespace simdjson {
4031
4032
/**
4033
 * @brief A DOM API on top of the simdjson parser.
4034
 */
4035
namespace dom {
4036
4037
/** The default batch size for parser.parse_many() and parser.load_many() */
4038
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
4039
/**
4040
 * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
4041
 * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
4042
 * most users will want a much larger batch size.
4043
 *
4044
 * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
4045
 * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
4046
 */
4047
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
4048
4049
/**
4050
 * It is wasteful to allocate memory for tiny documents (e.g., 4 bytes).
4051
 */
4052
static constexpr size_t MINIMAL_DOCUMENT_CAPACITY = 32;
4053
4054
class array;
4055
class document;
4056
class document_stream;
4057
class element;
4058
class key_value_pair;
4059
class object;
4060
class parser;
4061
4062
#ifdef SIMDJSON_THREADS_ENABLED
4063
struct stage1_worker;
4064
#endif // SIMDJSON_THREADS_ENABLED
4065
4066
} // namespace dom
4067
4068
namespace internal {
4069
4070
template<typename T>
4071
class string_builder;
4072
class tape_ref;
4073
4074
} // namespace internal
4075
4076
} // namespace simdjson
4077
4078
#endif // SIMDJSON_DOM_BASE_H
4079
/* end file simdjson/dom/base.h */
4080
/* including simdjson/dom/array.h: #include "simdjson/dom/array.h" */
4081
/* begin file simdjson/dom/array.h */
4082
#ifndef SIMDJSON_DOM_ARRAY_H
4083
#define SIMDJSON_DOM_ARRAY_H
4084
4085
/* skipped duplicate #include "simdjson/dom/base.h" */
4086
/* including simdjson/internal/tape_ref.h: #include "simdjson/internal/tape_ref.h" */
4087
/* begin file simdjson/internal/tape_ref.h */
4088
#ifndef SIMDJSON_INTERNAL_TAPE_REF_H
4089
#define SIMDJSON_INTERNAL_TAPE_REF_H
4090
4091
/* skipped duplicate #include "simdjson/base.h" */
4092
4093
namespace simdjson {
4094
namespace dom {
4095
class document;
4096
} // namespace dom
4097
4098
namespace internal {
4099
4100
/**
4101
 * A reference to an element on the tape. Internal only.
4102
 */
4103
class tape_ref {
4104
public:
4105
  simdjson_inline tape_ref() noexcept;
4106
  simdjson_inline tape_ref(const dom::document *doc, size_t json_index) noexcept;
4107
  inline size_t after_element() const noexcept;
4108
  simdjson_inline tape_type tape_ref_type() const noexcept;
4109
  simdjson_inline uint64_t tape_value() const noexcept;
4110
  simdjson_inline bool is_double() const noexcept;
4111
  simdjson_inline bool is_int64() const noexcept;
4112
  simdjson_inline bool is_uint64() const noexcept;
4113
  simdjson_inline bool is_false() const noexcept;
4114
  simdjson_inline bool is_true() const noexcept;
4115
  simdjson_inline bool is_null_on_tape() const noexcept;// different name to avoid clash with is_null.
4116
  simdjson_inline uint32_t matching_brace_index() const noexcept;
4117
  simdjson_inline uint32_t scope_count() const noexcept;
4118
  template<typename T>
4119
  simdjson_inline T next_tape_value() const noexcept;
4120
  simdjson_inline uint32_t get_string_length() const noexcept;
4121
  simdjson_inline const char * get_c_str() const noexcept;
4122
  inline std::string_view get_string_view() const noexcept;
4123
  simdjson_inline bool is_document_root() const noexcept;
4124
  simdjson_inline bool usable() const noexcept;
4125
4126
  /** The document this element references. */
4127
  const dom::document *doc;
4128
4129
  /** The index of this element on `doc.tape[]` */
4130
  size_t json_index;
4131
};
4132
4133
} // namespace internal
4134
} // namespace simdjson
4135
4136
#endif // SIMDJSON_INTERNAL_TAPE_REF_H
4137
/* end file simdjson/internal/tape_ref.h */
4138
4139
namespace simdjson {
4140
namespace dom {
4141
4142
/**
4143
 * JSON array.
4144
 */
4145
class array {
4146
public:
4147
  /** Create a new, invalid array */
4148
  simdjson_inline array() noexcept;
4149
4150
  class iterator {
4151
  public:
4152
    using value_type = element;
4153
    using difference_type = std::ptrdiff_t;
4154
    using pointer = void;
4155
    using reference = value_type;
4156
    using iterator_category = std::forward_iterator_tag;
4157
4158
    /**
4159
     * Get the actual value
4160
     */
4161
    inline reference operator*() const noexcept;
4162
    /**
4163
     * Get the next value.
4164
     *
4165
     * Part of the std::iterator interface.
4166
     */
4167
    inline iterator& operator++() noexcept;
4168
    /**
4169
     * Get the next value.
4170
     *
4171
     * Part of the  std::iterator interface.
4172
     */
4173
    inline iterator operator++(int) noexcept;
4174
    /**
4175
     * Check if these values come from the same place in the JSON.
4176
     *
4177
     * Part of the std::iterator interface.
4178
     */
4179
    inline bool operator!=(const iterator& other) const noexcept;
4180
    inline bool operator==(const iterator& other) const noexcept;
4181
4182
    inline bool operator<(const iterator& other) const noexcept;
4183
    inline bool operator<=(const iterator& other) const noexcept;
4184
    inline bool operator>=(const iterator& other) const noexcept;
4185
    inline bool operator>(const iterator& other) const noexcept;
4186
4187
    iterator() noexcept = default;
4188
    iterator(const iterator&) noexcept = default;
4189
    iterator& operator=(const iterator&) noexcept = default;
4190
  private:
4191
    simdjson_inline iterator(const internal::tape_ref &tape) noexcept;
4192
    internal::tape_ref tape;
4193
    friend class array;
4194
  };
4195
4196
  /**
4197
   * Return the first array element.
4198
   *
4199
   * Part of the std::iterable interface.
4200
   */
4201
  inline iterator begin() const noexcept;
4202
  /**
4203
   * One past the last array element.
4204
   *
4205
   * Part of the std::iterable interface.
4206
   */
4207
  inline iterator end() const noexcept;
4208
  /**
4209
   * Get the size of the array (number of immediate children).
4210
   * It is a saturated value with a maximum of 0xFFFFFF: if the value
4211
   * is 0xFFFFFF then the size is 0xFFFFFF or greater.
4212
   */
4213
  inline size_t size() const noexcept;
4214
  /**
4215
   * Get the total number of slots used by this array on the tape.
4216
   *
4217
   * Note that this is not the same thing as `size()`, which reports the
4218
   * number of actual elements within an array (not counting its children).
4219
   *
4220
   * Since an element can use 1 or 2 slots on the tape, you can only use this
4221
   * to figure out the total size of an array (including its children,
4222
   * recursively) if you know its structure ahead of time.
4223
   **/
4224
  inline size_t number_of_slots() const noexcept;
4225
  /**
4226
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
4227
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
4228
   * as the root of its own JSON document.
4229
   *
4230
   *   dom::parser parser;
4231
   *   array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded);
4232
   *   a.at_pointer("/0/foo/a/1") == 20
4233
   *   a.at_pointer("0")["foo"]["a"].at(1) == 20
4234
   *
4235
   * @return The value associated with the given JSON pointer, or:
4236
   *         - NO_SUCH_FIELD if a field does not exist in an object
4237
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
4238
   *         - INCORRECT_TYPE if a non-integer is used to access an array
4239
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
4240
   */
4241
  inline simdjson_result<element> at_pointer(std::string_view json_pointer) const noexcept;
4242
4243
  /**
4244
   * Get the value at the given index. This function has linear-time complexity and
4245
   * is equivalent to the following:
4246
   *
4247
   *    size_t i=0;
4248
   *    for (auto element : *this) {
4249
   *      if (i == index) { return element; }
4250
   *      i++;
4251
   *    }
4252
   *    return INDEX_OUT_OF_BOUNDS;
4253
   *
4254
   * Avoid calling the at() function repeatedly.
4255
   *
4256
   * @return The value at the given index, or:
4257
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
4258
   */
4259
  inline simdjson_result<element> at(size_t index) const noexcept;
4260
4261
private:
4262
  simdjson_inline array(const internal::tape_ref &tape) noexcept;
4263
  internal::tape_ref tape;
4264
  friend class element;
4265
  friend struct simdjson_result<element>;
4266
  template<typename T>
4267
  friend class simdjson::internal::string_builder;
4268
};
4269
4270
4271
} // namespace dom
4272
4273
/** The result of a JSON conversion that may fail. */
4274
template<>
4275
struct simdjson_result<dom::array> : public internal::simdjson_result_base<dom::array> {
4276
public:
4277
  simdjson_inline simdjson_result() noexcept; ///< @private
4278
  simdjson_inline simdjson_result(dom::array value) noexcept; ///< @private
4279
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
4280
4281
  inline simdjson_result<dom::element> at_pointer(std::string_view json_pointer) const noexcept;
4282
  inline simdjson_result<dom::element> at(size_t index) const noexcept;
4283
4284
#if SIMDJSON_EXCEPTIONS
4285
  inline dom::array::iterator begin() const noexcept(false);
4286
  inline dom::array::iterator end() const noexcept(false);
4287
  inline size_t size() const noexcept(false);
4288
#endif // SIMDJSON_EXCEPTIONS
4289
};
4290
4291
4292
4293
} // namespace simdjson
4294
4295
#if defined(__cpp_lib_ranges)
4296
#include <ranges>
4297
4298
namespace std {
4299
namespace ranges {
4300
template<>
4301
inline constexpr bool enable_view<simdjson::dom::array> = true;
4302
#if SIMDJSON_EXCEPTIONS
4303
template<>
4304
inline constexpr bool enable_view<simdjson::simdjson_result<simdjson::dom::array>> = true;
4305
#endif // SIMDJSON_EXCEPTIONS
4306
} // namespace ranges
4307
} // namespace std
4308
#endif // defined(__cpp_lib_ranges)
4309
4310
#endif // SIMDJSON_DOM_ARRAY_H
4311
/* end file simdjson/dom/array.h */
4312
/* including simdjson/dom/document_stream.h: #include "simdjson/dom/document_stream.h" */
4313
/* begin file simdjson/dom/document_stream.h */
4314
#ifndef SIMDJSON_DOCUMENT_STREAM_H
4315
#define SIMDJSON_DOCUMENT_STREAM_H
4316
4317
/* skipped duplicate #include "simdjson/dom/base.h" */
4318
/* including simdjson/dom/parser.h: #include "simdjson/dom/parser.h" */
4319
/* begin file simdjson/dom/parser.h */
4320
#ifndef SIMDJSON_DOM_PARSER_H
4321
#define SIMDJSON_DOM_PARSER_H
4322
4323
/* skipped duplicate #include "simdjson/dom/base.h" */
4324
/* including simdjson/dom/document.h: #include "simdjson/dom/document.h" */
4325
/* begin file simdjson/dom/document.h */
4326
#ifndef SIMDJSON_DOM_DOCUMENT_H
4327
#define SIMDJSON_DOM_DOCUMENT_H
4328
4329
/* skipped duplicate #include "simdjson/dom/base.h" */
4330
4331
#include <memory>
4332
4333
namespace simdjson {
4334
namespace dom {
4335
4336
/**
4337
 * A parsed JSON document.
4338
 *
4339
 * This class cannot be copied, only moved, to avoid unintended allocations.
4340
 */
4341
class document {
4342
public:
4343
  /**
4344
   * Create a document container with zero capacity.
4345
   *
4346
   * The parser will allocate capacity as needed.
4347
   */
4348
  document() noexcept = default;
4349
  ~document() noexcept = default;
4350
4351
  /**
4352
   * Take another document's buffers.
4353
   *
4354
   * @param other The document to take. Its capacity is zeroed and it is invalidated.
4355
   */
4356
  document(document &&other) noexcept = default;
4357
  /** @private */
4358
  document(const document &) = delete; // Disallow copying
4359
  /**
4360
   * Take another document's buffers.
4361
   *
4362
   * @param other The document to take. Its capacity is zeroed.
4363
   */
4364
  document &operator=(document &&other) noexcept = default;
4365
  /** @private */
4366
  document &operator=(const document &) = delete; // Disallow copying
4367
4368
  /**
4369
   * Get the root element of this document as a JSON array.
4370
   */
4371
  element root() const noexcept;
4372
4373
  /**
4374
   * @private Dump the raw tape for debugging.
4375
   *
4376
   * @param os the stream to output to.
4377
   * @return false if the tape is likely wrong (e.g., you did not parse a valid JSON).
4378
   */
4379
  bool dump_raw_tape(std::ostream &os) const noexcept;
4380
4381
  /** @private Structural values. */
4382
  std::unique_ptr<uint64_t[]> tape{};
4383
4384
  /** @private String values.
4385
   *
4386
   * Should be at least byte_capacity.
4387
   */
4388
  std::unique_ptr<uint8_t[]> string_buf{};
4389
  /** @private Allocate memory to support
4390
   * input JSON documents of up to len bytes.
4391
   *
4392
   * When calling this function, you lose
4393
   * all the data.
4394
   *
4395
   * The memory allocation is strict: you
4396
   * can you use this function to increase
4397
   * or lower the amount of allocated memory.
4398
   * Passsing zero clears the memory.
4399
   */
4400
  error_code allocate(size_t len) noexcept;
4401
  /** @private Capacity in bytes, in terms
4402
   * of how many bytes of input JSON we can
4403
   * support.
4404
   */
4405
  size_t capacity() const noexcept;
4406
4407
4408
private:
4409
  size_t allocated_capacity{0};
4410
  friend class parser;
4411
}; // class document
4412
4413
} // namespace dom
4414
} // namespace simdjson
4415
4416
#endif // SIMDJSON_DOM_DOCUMENT_H
4417
/* end file simdjson/dom/document.h */
4418
4419
namespace simdjson {
4420
4421
namespace dom {
4422
4423
/**
4424
 * A persistent document parser.
4425
 *
4426
 * The parser is designed to be reused, holding the internal buffers necessary to do parsing,
4427
 * as well as memory for a single document. The parsed document is overwritten on each parse.
4428
 *
4429
 * This class cannot be copied, only moved, to avoid unintended allocations.
4430
 *
4431
 * @note Moving a parser instance may invalidate "dom::element" instances. If you need to
4432
 * preserve both the "dom::element" instances and the parser, consider wrapping the parser
4433
 * instance in a std::unique_ptr instance:
4434
 *
4435
 *   std::unique_ptr<dom::parser> parser(new dom::parser{});
4436
 *   auto error = parser->load(f).get(root);
4437
 *
4438
 * You can then move std::unique_ptr safely.
4439
 *
4440
 * @note This is not thread safe: one parser cannot produce two documents at the same time!
4441
 */
4442
class parser {
4443
public:
4444
  /**
4445
   * Create a JSON parser.
4446
   *
4447
   * The new parser will have zero capacity.
4448
   *
4449
   * @param max_capacity The maximum document length the parser can automatically handle. The parser
4450
   *    will allocate more capacity on an as needed basis (when it sees documents too big to handle)
4451
   *    up to this amount. The parser still starts with zero capacity no matter what this number is:
4452
   *    to allocate an initial capacity, call allocate() after constructing the parser.
4453
   *    Defaults to SIMDJSON_MAXSIZE_BYTES (the largest single document simdjson can process).
4454
   */
4455
  simdjson_inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
4456
  /**
4457
   * Take another parser's buffers and state.
4458
   *
4459
   * @param other The parser to take. Its capacity is zeroed.
4460
   */
4461
  simdjson_inline parser(parser &&other) noexcept;
4462
  parser(const parser &) = delete; ///< @private Disallow copying
4463
  /**
4464
   * Take another parser's buffers and state.
4465
   *
4466
   * @param other The parser to take. Its capacity is zeroed.
4467
   */
4468
  simdjson_inline parser &operator=(parser &&other) noexcept;
4469
  parser &operator=(const parser &) = delete; ///< @private Disallow copying
4470
4471
  /** Deallocate the JSON parser. */
4472
  ~parser()=default;
4473
4474
  /**
4475
   * Load a JSON document from a file and return a reference to it.
4476
   *
4477
   *   dom::parser parser;
4478
   *   const element doc = parser.load("jsonexamples/twitter.json");
4479
   *
4480
   * The function is eager: the file's content is loaded in memory inside the parser instance
4481
   * and immediately parsed. The file can be deleted after the  `parser.load` call.
4482
   *
4483
   * ### IMPORTANT: Document Lifetime
4484
   *
4485
   * The JSON document still lives in the parser: this is the most efficient way to parse JSON
4486
   * documents because it reuses the same buffers, but you *must* use the document before you
4487
   * destroy the parser or call parse() again.
4488
   *
4489
   * Moving the parser instance is safe, but it invalidates the element instances. You may store
4490
   * the parser instance without moving it by wrapping it inside an `unique_ptr` instance like
4491
   * so: `std::unique_ptr<dom::parser> parser(new dom::parser{});`.
4492
   *
4493
   * ### Parser Capacity
4494
   *
4495
   * If the parser's current capacity is less than the file length, it will allocate enough capacity
4496
   * to handle it (up to max_capacity).
4497
   *
4498
   * @param path The path to load.
4499
   * @return The document, or an error:
4500
   *         - IO_ERROR if there was an error opening or reading the file.
4501
   *           Be mindful that on some 32-bit systems,
4502
   *           the file size might be limited to 2 GB.
4503
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
4504
   *         - CAPACITY if the parser does not have enough capacity and len > max_capacity.
4505
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
4506
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
4507
   */
4508
  inline simdjson_result<element> load(const std::string &path) & noexcept;
4509
  inline simdjson_result<element> load(const std::string &path) &&  = delete ;
4510
4511
  /**
4512
   * Load a JSON document from a file into a provide document instance and return a temporary reference to it.
4513
   * It is similar to the function `load` except that instead of parsing into the internal
4514
   * `document` instance associated with the parser, it allows the user to provide a document
4515
   * instance.
4516
   *
4517
   *   dom::parser parser;
4518
   *   dom::document doc;
4519
   *   element doc_root = parser.load_into_document(doc, "jsonexamples/twitter.json");
4520
   *
4521
   * The function is eager: the file's content is loaded in memory inside the parser instance
4522
   * and immediately parsed. The file can be deleted after the `parser.load_into_document` call.
4523
   *
4524
   * ### IMPORTANT: Document Lifetime
4525
   *
4526
   * After the call to load_into_document, the parser is no longer needed.
4527
   *
4528
   * The JSON document lives in the document instance: you must keep the document
4529
   * instance alive while you navigate through it (i.e., used the returned value from
4530
   * load_into_document). You are encourage to reuse the document instance
4531
   * many times with new data to avoid reallocations:
4532
   *
4533
   *   dom::document doc;
4534
   *   element doc_root1 = parser.load_into_document(doc, "jsonexamples/twitter.json");
4535
   *   //... doc_root1 is a pointer inside doc
4536
   *   element doc_root2 = parser.load_into_document(doc, "jsonexamples/twitter.json");
4537
   *   //... doc_root2 is a pointer inside doc
4538
   *   // at this point doc_root1 is no longer safe
4539
   *
4540
   * Moving the document instance is safe, but it invalidates the element instances. After
4541
   * moving a document, you can recover safe access to the document root with its `root()` method.
4542
   *
4543
   * @param doc The document instance where the parsed data will be stored (on success).
4544
   * @param path The path to load.
4545
   * @return The document, or an error:
4546
   *         - IO_ERROR if there was an error opening or reading the file.
4547
   *           Be mindful that on some 32-bit systems,
4548
   *           the file size might be limited to 2 GB.
4549
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
4550
   *         - CAPACITY if the parser does not have enough capacity and len > max_capacity.
4551
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
4552
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
4553
   */
4554
  inline simdjson_result<element> load_into_document(document& doc, const std::string &path) & noexcept;
4555
  inline simdjson_result<element> load_into_document(document& doc, const std::string &path) && =delete;
4556
4557
  /**
4558
   * Parse a JSON document and return a temporary reference to it.
4559
   *
4560
   *   dom::parser parser;
4561
   *   element doc_root = parser.parse(buf, len);
4562
   *
4563
   * The function eagerly parses the input: the input can be modified and discarded after
4564
   * the `parser.parse(buf, len)` call has completed.
4565
   *
4566
   * ### IMPORTANT: Document Lifetime
4567
   *
4568
   * The JSON document still lives in the parser: this is the most efficient way to parse JSON
4569
   * documents because it reuses the same buffers, but you *must* use the document before you
4570
   * destroy the parser or call parse() again.
4571
   *
4572
   * Moving the parser instance is safe, but it invalidates the element instances. You may store
4573
   * the parser instance without moving it by wrapping it inside an `unique_ptr` instance like
4574
   * so: `std::unique_ptr<dom::parser> parser(new dom::parser{});`.
4575
   *
4576
   * ### REQUIRED: Buffer Padding
4577
   *
4578
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
4579
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
4580
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
4581
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
4582
   *
4583
   * If realloc_if_needed is true (the default), it is assumed that the buffer does *not* have enough padding,
4584
   * and it is copied into an enlarged temporary buffer before parsing. Thus the following is safe:
4585
   *
4586
   *   const char *json      = R"({"key":"value"})";
4587
   *   const size_t json_len = std::strlen(json);
4588
   *   simdjson::dom::parser parser;
4589
   *   simdjson::dom::element element = parser.parse(json, json_len);
4590
   *
4591
   * If you set realloc_if_needed to false (e.g., parser.parse(json, json_len, false)),
4592
   * you must provide a buffer with at least SIMDJSON_PADDING extra bytes at the end.
4593
   * The benefit of setting realloc_if_needed to false is that you avoid a temporary
4594
   * memory allocation and a copy.
4595
   *
4596
   * The padded bytes may be read. It is not important how you initialize
4597
   * these bytes though we recommend a sensible default like null character values or spaces.
4598
   * For example, the following low-level code is safe:
4599
   *
4600
   *   const char *json      = R"({"key":"value"})";
4601
   *   const size_t json_len = std::strlen(json);
4602
   *   std::unique_ptr<char[]> padded_json_copy{new char[json_len + SIMDJSON_PADDING]};
4603
   *   std::memcpy(padded_json_copy.get(), json, json_len);
4604
   *   std::memset(padded_json_copy.get() + json_len, '\0', SIMDJSON_PADDING);
4605
   *   simdjson::dom::parser parser;
4606
   *   simdjson::dom::element element = parser.parse(padded_json_copy.get(), json_len, false);
4607
   *
4608
   * ### Parser Capacity
4609
   *
4610
   * If the parser's current capacity is less than len, it will allocate enough capacity
4611
   * to handle it (up to max_capacity).
4612
   *
4613
   * @param buf The JSON to parse. Must have at least len + SIMDJSON_PADDING allocated bytes, unless
4614
   *            realloc_if_needed is true.
4615
   * @param len The length of the JSON.
4616
   * @param realloc_if_needed Whether to reallocate and enlarge the JSON buffer to add padding.
4617
   * @return An element pointing at the root of the document, or an error:
4618
   *         - MEMALLOC if realloc_if_needed is true or the parser does not have enough capacity,
4619
   *           and memory allocation fails.
4620
   *         - CAPACITY if the parser does not have enough capacity and len > max_capacity.
4621
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
4622
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
4623
   */
4624
  inline simdjson_result<element> parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) & noexcept;
4625
  inline simdjson_result<element> parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) && =delete;
4626
  /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
4627
  simdjson_inline simdjson_result<element> parse(const char *buf, size_t len, bool realloc_if_needed = true) & noexcept;
4628
  simdjson_inline simdjson_result<element> parse(const char *buf, size_t len, bool realloc_if_needed = true) && =delete;
4629
  /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
4630
  simdjson_inline simdjson_result<element> parse(const std::string &s) & noexcept;
4631
  simdjson_inline simdjson_result<element> parse(const std::string &s) && =delete;
4632
  /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
4633
  simdjson_inline simdjson_result<element> parse(const padded_string &s) & noexcept;
4634
  simdjson_inline simdjson_result<element> parse(const padded_string &s) && =delete;
4635
  /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
4636
  simdjson_inline simdjson_result<element> parse(const padded_string_view &v) & noexcept;
4637
  simdjson_inline simdjson_result<element> parse(const padded_string_view &v) && =delete;
4638
4639
  /** @private We do not want to allow implicit conversion from C string to std::string. */
4640
  simdjson_inline simdjson_result<element> parse(const char *buf) noexcept = delete;
4641
4642
  /**
4643
   * Parse a JSON document into a provide document instance and return a temporary reference to it.
4644
   * It is similar to the function `parse` except that instead of parsing into the internal
4645
   * `document` instance associated with the parser, it allows the user to provide a document
4646
   * instance.
4647
   *
4648
   *   dom::parser parser;
4649
   *   dom::document doc;
4650
   *   element doc_root = parser.parse_into_document(doc, buf, len);
4651
   *
4652
   * The function eagerly parses the input: the input can be modified and discarded after
4653
   * the `parser.parse(buf, len)` call has completed.
4654
   *
4655
   * ### IMPORTANT: Document Lifetime
4656
   *
4657
   * After the call to parse_into_document, the parser is no longer needed.
4658
   *
4659
   * The JSON document lives in the document instance: you must keep the document
4660
   * instance alive while you navigate through it (i.e., used the returned value from
4661
   * parse_into_document). You are encourage to reuse the document instance
4662
   * many times with new data to avoid reallocations:
4663
   *
4664
   *   dom::document doc;
4665
   *   element doc_root1 = parser.parse_into_document(doc, buf1, len);
4666
   *   //... doc_root1 is a pointer inside doc
4667
   *   element doc_root2 = parser.parse_into_document(doc, buf1, len);
4668
   *   //... doc_root2 is a pointer inside doc
4669
   *   // at this point doc_root1 is no longer safe
4670
   *
4671
   * Moving the document instance is safe, but it invalidates the element instances. After
4672
   * moving a document, you can recover safe access to the document root with its `root()` method.
4673
   *
4674
   * @param doc The document instance where the parsed data will be stored (on success).
4675
   * @param buf The JSON to parse. Must have at least len + SIMDJSON_PADDING allocated bytes, unless
4676
   *            realloc_if_needed is true.
4677
   * @param len The length of the JSON.
4678
   * @param realloc_if_needed Whether to reallocate and enlarge the JSON buffer to add padding.
4679
   * @return An element pointing at the root of document, or an error:
4680
   *         - MEMALLOC if realloc_if_needed is true or the parser does not have enough capacity,
4681
   *           and memory allocation fails.
4682
   *         - CAPACITY if the parser does not have enough capacity and len > max_capacity.
4683
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
4684
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
4685
   */
4686
  inline simdjson_result<element> parse_into_document(document& doc, const uint8_t *buf, size_t len, bool realloc_if_needed = true) & noexcept;
4687
  inline simdjson_result<element> parse_into_document(document& doc, const uint8_t *buf, size_t len, bool realloc_if_needed = true) && =delete;
4688
  /** @overload parse_into_document(const uint8_t *buf, size_t len, bool realloc_if_needed) */
4689
  simdjson_inline simdjson_result<element> parse_into_document(document& doc, const char *buf, size_t len, bool realloc_if_needed = true) & noexcept;
4690
  simdjson_inline simdjson_result<element> parse_into_document(document& doc, const char *buf, size_t len, bool realloc_if_needed = true) && =delete;
4691
  /** @overload parse_into_document(const uint8_t *buf, size_t len, bool realloc_if_needed) */
4692
  simdjson_inline simdjson_result<element> parse_into_document(document& doc, const std::string &s) & noexcept;
4693
  simdjson_inline simdjson_result<element> parse_into_document(document& doc, const std::string &s) && =delete;
4694
  /** @overload parse_into_document(const uint8_t *buf, size_t len, bool realloc_if_needed) */
4695
  simdjson_inline simdjson_result<element> parse_into_document(document& doc, const padded_string &s) & noexcept;
4696
  simdjson_inline simdjson_result<element> parse_into_document(document& doc, const padded_string &s) && =delete;
4697
4698
  /** @private We do not want to allow implicit conversion from C string to std::string. */
4699
  simdjson_inline simdjson_result<element> parse_into_document(document& doc, const char *buf) noexcept = delete;
4700
4701
  /**
4702
   * Load a file containing many JSON documents.
4703
   *
4704
   *   dom::parser parser;
4705
   *   for (const element doc : parser.load_many(path)) {
4706
   *     cout << std::string(doc["title"]) << endl;
4707
   *   }
4708
   *
4709
   * The file is loaded in memory and can be safely deleted after the `parser.load_many(path)`
4710
   * function has returned. The memory is held by the `parser` instance.
4711
   *
4712
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
4713
   * And, possibly, no document many have been parsed when the `parser.load_many(path)` function
4714
   * returned.
4715
   *
4716
   * If there is a UTF-8 BOM, the parser skips it.
4717
   *
4718
   * ### Format
4719
   *
4720
   * The file must contain a series of one or more JSON documents, concatenated into a single
4721
   * buffer, separated by whitespace. It effectively parses until it has a fully valid document,
4722
   * then starts parsing the next document at that point. (It does this with more parallelism and
4723
   * lookahead than you might think, though.)
4724
   *
4725
   * Documents that consist of an object or array may omit the whitespace between them, concatenating
4726
   * with no separator. documents that consist of a single primitive (i.e. documents that are not
4727
   * arrays or objects) MUST be separated with whitespace.
4728
   *
4729
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
4730
   * Setting batch_size to excessively large or excesively small values may impact negatively the
4731
   * performance.
4732
   *
4733
   * ### Error Handling
4734
   *
4735
   * All errors are returned during iteration: if there is a global error such as memory allocation,
4736
   * it will be yielded as the first result. Iteration always stops after the first error.
4737
   *
4738
   * As with all other simdjson methods, non-exception error handling is readily available through
4739
   * the same interface, requiring you to check the error before using the document:
4740
   *
4741
   *   dom::parser parser;
4742
   *   dom::document_stream docs;
4743
   *   auto error = parser.load_many(path).get(docs);
4744
   *   if (error) { cerr << error << endl; exit(1); }
4745
   *   for (auto doc : docs) {
4746
   *     std::string_view title;
4747
   *     if ((error = doc["title"].get(title)) { cerr << error << endl; exit(1); }
4748
   *     cout << title << endl;
4749
   *   }
4750
   *
4751
   * ### Threads
4752
   *
4753
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
4754
   * hood to do some lookahead.
4755
   *
4756
   * ### Parser Capacity
4757
   *
4758
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
4759
   * to handle it (up to max_capacity).
4760
   *
4761
   * @param path File name pointing at the concatenated JSON to parse.
4762
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
4763
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
4764
   *                   parse as many documents as possible in one tight loop.
4765
   *                   Defaults to 1MB (as simdjson::dom::DEFAULT_BATCH_SIZE), which has been a reasonable sweet
4766
   *                   spot in our tests.
4767
   *                   If you set the batch_size to a value smaller than simdjson::dom::MINIMAL_BATCH_SIZE
4768
   *                   (currently 32B), it will be replaced by simdjson::dom::MINIMAL_BATCH_SIZE.
4769
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
4770
   *         - IO_ERROR if there was an error opening or reading the file.
4771
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
4772
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
4773
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
4774
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
4775
   */
4776
  inline simdjson_result<document_stream> load_many(const std::string &path, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
4777
4778
  /**
4779
   * Parse a buffer containing many JSON documents.
4780
   *
4781
   *   dom::parser parser;
4782
   *   for (element doc : parser.parse_many(buf, len)) {
4783
   *     cout << std::string(doc["title"]) << endl;
4784
   *   }
4785
   *
4786
   * No copy of the input buffer is made.
4787
   *
4788
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
4789
   * And, possibly, no document many have been parsed when the `parser.load_many(path)` function
4790
   * returned.
4791
   *
4792
   * The caller is responsabile to ensure that the input string data remains unchanged and is
4793
   * not deleted during the loop. In particular, the following is unsafe and will not compile:
4794
   *
4795
   *   auto docs = parser.parse_many("[\"temporary data\"]"_padded);
4796
   *   // here the string "[\"temporary data\"]" may no longer exist in memory
4797
   *   // the parser instance may not have even accessed the input yet
4798
   *   for (element doc : docs) {
4799
   *     cout << std::string(doc["title"]) << endl;
4800
   *   }
4801
   *
4802
   * The following is safe:
4803
   *
4804
   *   auto json = "[\"temporary data\"]"_padded;
4805
   *   auto docs = parser.parse_many(json);
4806
   *   for (element doc : docs) {
4807
   *     cout << std::string(doc["title"]) << endl;
4808
   *   }
4809
   *
4810
   * If there is a UTF-8 BOM, the parser skips it.
4811
   *
4812
   * ### Format
4813
   *
4814
   * The buffer must contain a series of one or more JSON documents, concatenated into a single
4815
   * buffer, separated by whitespace. It effectively parses until it has a fully valid document,
4816
   * then starts parsing the next document at that point. (It does this with more parallelism and
4817
   * lookahead than you might think, though.)
4818
   *
4819
   * documents that consist of an object or array may omit the whitespace between them, concatenating
4820
   * with no separator. documents that consist of a single primitive (i.e. documents that are not
4821
   * arrays or objects) MUST be separated with whitespace.
4822
   *
4823
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
4824
   * Setting batch_size to excessively large or excesively small values may impact negatively the
4825
   * performance.
4826
   *
4827
   * ### Error Handling
4828
   *
4829
   * All errors are returned during iteration: if there is a global error such as memory allocation,
4830
   * it will be yielded as the first result. Iteration always stops after the first error.
4831
   *
4832
   * As with all other simdjson methods, non-exception error handling is readily available through
4833
   * the same interface, requiring you to check the error before using the document:
4834
   *
4835
   *   dom::parser parser;
4836
   *   dom::document_stream docs;
4837
   *   auto error = parser.load_many(path).get(docs);
4838
   *   if (error) { cerr << error << endl; exit(1); }
4839
   *   for (auto doc : docs) {
4840
   *     std::string_view title;
4841
   *     if ((error = doc["title"].get(title)) { cerr << error << endl; exit(1); }
4842
   *     cout << title << endl;
4843
   *   }
4844
   *
4845
   * ### REQUIRED: Buffer Padding
4846
   *
4847
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
4848
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
4849
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
4850
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
4851
   *
4852
   * ### Threads
4853
   *
4854
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
4855
   * hood to do some lookahead.
4856
   *
4857
   * ### Parser Capacity
4858
   *
4859
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
4860
   * to handle it (up to max_capacity).
4861
   *
4862
   * @param buf The concatenated JSON to parse. Must have at least len + SIMDJSON_PADDING allocated bytes.
4863
   * @param len The length of the concatenated JSON.
4864
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
4865
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
4866
   *                   parse as many documents as possible in one tight loop.
4867
   *                   Defaults to 10MB, which has been a reasonable sweet spot in our tests.
4868
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
4869
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails
4870
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
4871
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
4872
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
4873
   */
4874
  inline simdjson_result<document_stream> parse_many(const uint8_t *buf, size_t len, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
4875
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
4876
  inline simdjson_result<document_stream> parse_many(const char *buf, size_t len, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
4877
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
4878
  inline simdjson_result<document_stream> parse_many(const std::string &s, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
4879
  inline simdjson_result<document_stream> parse_many(const std::string &&s, size_t batch_size) = delete;// unsafe
4880
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
4881
  inline simdjson_result<document_stream> parse_many(const padded_string &s, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
4882
  inline simdjson_result<document_stream> parse_many(const padded_string &&s, size_t batch_size) = delete;// unsafe
4883
4884
  /** @private We do not want to allow implicit conversion from C string to std::string. */
4885
  simdjson_result<document_stream> parse_many(const char *buf, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept = delete;
4886
4887
  /**
4888
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
4889
   * and `max_depth` depth.
4890
   *
4891
   * @param capacity The new capacity.
4892
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
4893
   * @return The error, if there is one.
4894
   */
4895
  simdjson_warn_unused inline error_code allocate(size_t capacity, size_t max_depth = DEFAULT_MAX_DEPTH) noexcept;
4896
4897
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
4898
  /**
4899
   * @private deprecated because it returns bool instead of error_code, which is our standard for
4900
   * failures. Use allocate() instead.
4901
   *
4902
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
4903
   * and `max_depth` depth.
4904
   *
4905
   * @param capacity The new capacity.
4906
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
4907
   * @return true if successful, false if allocation failed.
4908
   */
4909
  [[deprecated("Use allocate() instead.")]]
4910
  simdjson_warn_unused inline bool allocate_capacity(size_t capacity, size_t max_depth = DEFAULT_MAX_DEPTH) noexcept;
4911
#endif // SIMDJSON_DISABLE_DEPRECATED_API
4912
  /**
4913
   * The largest document this parser can support without reallocating.
4914
   *
4915
   * @return Current capacity, in bytes.
4916
   */
4917
  simdjson_inline size_t capacity() const noexcept;
4918
4919
  /**
4920
   * The largest document this parser can automatically support.
4921
   *
4922
   * The parser may reallocate internal buffers as needed up to this amount.
4923
   *
4924
   * @return Maximum capacity, in bytes.
4925
   */
4926
  simdjson_inline size_t max_capacity() const noexcept;
4927
4928
  /**
4929
   * The maximum level of nested object and arrays supported by this parser.
4930
   *
4931
   * @return Maximum depth, in bytes.
4932
   */
4933
  simdjson_inline size_t max_depth() const noexcept;
4934
4935
  /**
4936
   * Set max_capacity. This is the largest document this parser can automatically support.
4937
   *
4938
   * The parser may reallocate internal buffers as needed up to this amount as documents are passed
4939
   * to it.
4940
   *
4941
   * Note: To avoid limiting the memory to an absurd value, such as zero or two bytes,
4942
   * iff you try to set max_capacity to a value lower than MINIMAL_DOCUMENT_CAPACITY,
4943
   * then the maximal capacity is set to MINIMAL_DOCUMENT_CAPACITY.
4944
   *
4945
   * This call will not allocate or deallocate, even if capacity is currently above max_capacity.
4946
   *
4947
   * @param max_capacity The new maximum capacity, in bytes.
4948
   */
4949
  simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
4950
4951
#ifdef SIMDJSON_THREADS_ENABLED
4952
  /**
4953
   * The parser instance can use threads when they are available to speed up some
4954
   * operations. It is enabled by default. Changing this attribute will change the
4955
   * behavior of the parser for future operations.
4956
   */
4957
  bool threaded{true};
4958
#endif
4959
  /** @private Use the new DOM API instead */
4960
  class Iterator;
4961
  /** @private Use simdjson_error instead */
4962
  using InvalidJSON [[deprecated("Use simdjson_error instead")]] = simdjson_error;
4963
4964
  /** @private [for benchmarking access] The implementation to use */
4965
  std::unique_ptr<internal::dom_parser_implementation> implementation{};
4966
4967
  /** @private Use `if (parser.parse(...).error())` instead */
4968
  bool valid{false};
4969
  /** @private Use `parser.parse(...).error()` instead */
4970
  error_code error{UNINITIALIZED};
4971
4972
  /** @private Use `parser.parse(...).value()` instead */
4973
  document doc{};
4974
4975
  /** @private returns true if the document parsed was valid */
4976
  [[deprecated("Use the result of parser.parse() instead")]]
4977
  inline bool is_valid() const noexcept;
4978
4979
  /**
4980
   * @private return an error code corresponding to the last parsing attempt, see
4981
   * simdjson.h will return UNINITIALIZED if no parsing was attempted
4982
   */
4983
  [[deprecated("Use the result of parser.parse() instead")]]
4984
  inline int get_error_code() const noexcept;
4985
4986
  /** @private return the string equivalent of "get_error_code" */
4987
  [[deprecated("Use error_message() on the result of parser.parse() instead, or cout << error")]]
4988
  inline std::string get_error_message() const noexcept;
4989
4990
  /** @private */
4991
  [[deprecated("Use cout << on the result of parser.parse() instead")]]
4992
  inline bool print_json(std::ostream &os) const noexcept;
4993
4994
  /** @private Private and deprecated: use `parser.parse(...).doc.dump_raw_tape()` instead */
4995
  inline bool dump_raw_tape(std::ostream &os) const noexcept;
4996
4997
4998
private:
4999
  /**
5000
   * The maximum document length this parser will automatically support.
5001
   *
5002
   * The parser will not be automatically allocated above this amount.
5003
   */
5004
  size_t _max_capacity;
5005
5006
  /**
5007
   * The loaded buffer (reused each time load() is called)
5008
   */
5009
  std::unique_ptr<char[]> loaded_bytes;
5010
5011
  /** Capacity of loaded_bytes buffer. */
5012
  size_t _loaded_bytes_capacity{0};
5013
5014
  // all nodes are stored on the doc.tape using a 64-bit word.
5015
  //
5016
  // strings, double and ints are stored as
5017
  //  a 64-bit word with a pointer to the actual value
5018
  //
5019
  //
5020
  //
5021
  // for objects or arrays, store [ or {  at the beginning and } and ] at the
5022
  // end. For the openings ([ or {), we annotate them with a reference to the
5023
  // location on the doc.tape of the end, and for then closings (} and ]), we
5024
  // annotate them with a reference to the location of the opening
5025
  //
5026
  //
5027
5028
  /**
5029
   * Ensure we have enough capacity to handle at least desired_capacity bytes,
5030
   * and auto-allocate if not. This also allocates memory if needed in the
5031
   * internal document.
5032
   */
5033
  inline error_code ensure_capacity(size_t desired_capacity) noexcept;
5034
  /**
5035
   * Ensure we have enough capacity to handle at least desired_capacity bytes,
5036
   * and auto-allocate if not. This also allocates memory if needed in the
5037
   * provided document.
5038
   */
5039
  inline error_code ensure_capacity(document& doc, size_t desired_capacity) noexcept;
5040
5041
  /** Read the file into loaded_bytes */
5042
  inline simdjson_result<size_t> read_file(const std::string &path) noexcept;
5043
5044
  friend class parser::Iterator;
5045
  friend class document_stream;
5046
5047
5048
}; // class parser
5049
5050
} // namespace dom
5051
} // namespace simdjson
5052
5053
#endif // SIMDJSON_DOM_PARSER_H
5054
/* end file simdjson/dom/parser.h */
5055
5056
#ifdef SIMDJSON_THREADS_ENABLED
5057
#include <thread>
5058
#include <mutex>
5059
#include <condition_variable>
5060
#endif
5061
5062
namespace simdjson {
5063
namespace dom {
5064
5065
#ifdef SIMDJSON_THREADS_ENABLED
5066
/** @private Custom worker class **/
5067
struct stage1_worker {
5068
  stage1_worker() noexcept = default;
5069
  stage1_worker(const stage1_worker&) = delete;
5070
  stage1_worker(stage1_worker&&) = delete;
5071
  stage1_worker operator=(const stage1_worker&) = delete;
5072
  ~stage1_worker();
5073
  /**
5074
   * We only start the thread when it is needed, not at object construction, this may throw.
5075
   * You should only call this once.
5076
   **/
5077
  void start_thread();
5078
  /**
5079
   * Start a stage 1 job. You should first call 'run', then 'finish'.
5080
   * You must call start_thread once before.
5081
   */
5082
  void run(document_stream * ds, dom::parser * stage1, size_t next_batch_start);
5083
  /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
5084
  void finish();
5085
5086
private:
5087
5088
  /**
5089
   * Normally, we would never stop the thread. But we do in the destructor.
5090
   * This function is only safe assuming that you are not waiting for results. You
5091
   * should have called run, then finish, and be done.
5092
   **/
5093
  void stop_thread();
5094
5095
  std::thread thread{};
5096
  /** These three variables define the work done by the thread. **/
5097
  dom::parser * stage1_thread_parser{};
5098
  size_t _next_batch_start{};
5099
  document_stream * owner{};
5100
  /**
5101
   * We have two state variables. This could be streamlined to one variable in the future but
5102
   * we use two for clarity.
5103
   */
5104
  bool has_work{false};
5105
  bool can_work{true};
5106
5107
  /**
5108
   * We lock using a mutex.
5109
   */
5110
  std::mutex locking_mutex{};
5111
  std::condition_variable cond_var{};
5112
};
5113
#endif
5114
5115
/**
5116
 * A forward-only stream of documents.
5117
 *
5118
 * Produced by parser::parse_many.
5119
 *
5120
 */
5121
class document_stream {
5122
public:
5123
  /**
5124
   * Construct an uninitialized document_stream.
5125
   *
5126
   *  ```c++
5127
   *  document_stream docs;
5128
   *  error = parser.parse_many(json).get(docs);
5129
   *  ```
5130
   */
5131
  simdjson_inline document_stream() noexcept;
5132
  /** Move one document_stream to another. */
5133
  simdjson_inline document_stream(document_stream &&other) noexcept = default;
5134
  /** Move one document_stream to another. */
5135
  simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
5136
5137
  simdjson_inline ~document_stream() noexcept;
5138
  /**
5139
   * Returns the input size in bytes.
5140
   */
5141
  inline size_t size_in_bytes() const noexcept;
5142
  /**
5143
   * After iterating through the stream, this method
5144
   * returns the number of bytes that were not parsed at the end
5145
   * of the stream. If truncated_bytes() differs from zero,
5146
   * then the input was truncated maybe because incomplete JSON
5147
   * documents were found at the end of the stream. You
5148
   * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
5149
   *
5150
   * You should only call truncated_bytes() after streaming through all
5151
   * documents, like so:
5152
   *
5153
   *   document_stream stream = parser.parse_many(json,window);
5154
   *   for(auto doc : stream) {
5155
   *      // do something with doc
5156
   *   }
5157
   *   size_t truncated = stream.truncated_bytes();
5158
   *
5159
   */
5160
  inline size_t truncated_bytes() const noexcept;
5161
  /**
5162
   * An iterator through a forward-only stream of documents.
5163
   */
5164
  class iterator {
5165
  public:
5166
    using value_type = simdjson_result<element>;
5167
    using reference  = value_type;
5168
5169
    using difference_type   = std::ptrdiff_t;
5170
5171
    using iterator_category = std::input_iterator_tag;
5172
5173
    /**
5174
     * Default constructor.
5175
     */
5176
    simdjson_inline iterator() noexcept;
5177
    /**
5178
     * Get the current document (or error).
5179
     */
5180
    simdjson_inline reference operator*() noexcept;
5181
    /**
5182
     * Advance to the next document (prefix).
5183
     */
5184
    inline iterator& operator++() noexcept;
5185
    /**
5186
     * Check if we're at the end yet.
5187
     * @param other the end iterator to compare to.
5188
     */
5189
    simdjson_inline bool operator!=(const iterator &other) const noexcept;
5190
    /**
5191
     * @private
5192
     *
5193
     * Gives the current index in the input document in bytes.
5194
     *
5195
     *   document_stream stream = parser.parse_many(json,window);
5196
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
5197
     *      auto doc = *i;
5198
     *      size_t index = i.current_index();
5199
     *   }
5200
     *
5201
     * This function (current_index()) is experimental and the usage
5202
     * may change in future versions of simdjson: we find the API somewhat
5203
     * awkward and we would like to offer something friendlier.
5204
     */
5205
     simdjson_inline size_t current_index() const noexcept;
5206
    /**
5207
     * @private
5208
     *
5209
     * Gives a view of the current document.
5210
     *
5211
     *   document_stream stream = parser.parse_many(json,window);
5212
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
5213
     *      auto doc = *i;
5214
     *      std::string_view v = i->source();
5215
     *   }
5216
     *
5217
     * The returned string_view instance is simply a map to the (unparsed)
5218
     * source string: it may thus include white-space characters and all manner
5219
     * of padding.
5220
     *
5221
     * This function (source()) is experimental and the usage
5222
     * may change in future versions of simdjson: we find the API somewhat
5223
     * awkward and we would like to offer something friendlier.
5224
     */
5225
     simdjson_inline std::string_view source() const noexcept;
5226
5227
  private:
5228
    simdjson_inline iterator(document_stream *s, bool finished) noexcept;
5229
    /** The document_stream we're iterating through. */
5230
    document_stream* stream;
5231
    /** Whether we're finished or not. */
5232
    bool finished;
5233
    friend class document_stream;
5234
  };
5235
5236
  /**
5237
   * Start iterating the documents in the stream.
5238
   */
5239
  simdjson_inline iterator begin() noexcept;
5240
  /**
5241
   * The end of the stream, for iterator comparison purposes.
5242
   */
5243
  simdjson_inline iterator end() noexcept;
5244
5245
private:
5246
5247
  document_stream &operator=(const document_stream &) = delete; // Disallow copying
5248
  document_stream(const document_stream &other) = delete; // Disallow copying
5249
5250
  /**
5251
   * Construct a document_stream. Does not allocate or parse anything until the iterator is
5252
   * used.
5253
   *
5254
   * @param parser is a reference to the parser instance used to generate this document_stream
5255
   * @param buf is the raw byte buffer we need to process
5256
   * @param len is the length of the raw byte buffer in bytes
5257
   * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
5258
   */
5259
  simdjson_inline document_stream(
5260
    dom::parser &parser,
5261
    const uint8_t *buf,
5262
    size_t len,
5263
    size_t batch_size
5264
  ) noexcept;
5265
5266
  /**
5267
   * Parse the first document in the buffer. Used by begin(), to handle allocation and
5268
   * initialization.
5269
   */
5270
  inline void start() noexcept;
5271
5272
  /**
5273
   * Parse the next document found in the buffer previously given to document_stream.
5274
   *
5275
   * The content should be a valid JSON document encoded as UTF-8. If there is a
5276
   * UTF-8 BOM, the parser skips it.
5277
   *
5278
   * You do NOT need to pre-allocate a parser.  This function takes care of
5279
   * pre-allocating a capacity defined by the batch_size defined when creating the
5280
   * document_stream object.
5281
   *
5282
   * The function returns simdjson::EMPTY if there is no more data to be parsed.
5283
   *
5284
   * The function returns simdjson::SUCCESS (as integer = 0) in case of success
5285
   * and indicates that the buffer has successfully been parsed to the end.
5286
   * Every document it contained has been parsed without error.
5287
   *
5288
   * The function returns an error code from simdjson/simdjson.h in case of failure
5289
   * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
5290
   * the simdjson::error_message function converts these error codes into a string).
5291
   *
5292
   * You can also check validity by calling parser.is_valid(). The same parser can
5293
   * and should be reused for the other documents in the buffer.
5294
   */
5295
  inline void next() noexcept;
5296
5297
  /**
5298
   * Pass the next batch through stage 1 and return when finished.
5299
   * When threads are enabled, this may wait for the stage 1 thread to finish.
5300
   */
5301
  inline void load_batch() noexcept;
5302
5303
  /** Get the next document index. */
5304
  inline size_t next_batch_start() const noexcept;
5305
5306
  /** Pass the next batch through stage 1 with the given parser. */
5307
  inline error_code run_stage1(dom::parser &p, size_t batch_start) noexcept;
5308
5309
  dom::parser *parser;
5310
  const uint8_t *buf;
5311
  size_t len;
5312
  size_t batch_size;
5313
  /** The error (or lack thereof) from the current document. */
5314
  error_code error;
5315
  size_t batch_start{0};
5316
  size_t doc_index{};
5317
#ifdef SIMDJSON_THREADS_ENABLED
5318
  /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
5319
  bool use_thread;
5320
5321
  inline void load_from_stage1_thread() noexcept;
5322
5323
  /** Start a thread to run stage 1 on the next batch. */
5324
  inline void start_stage1_thread() noexcept;
5325
5326
  /** Wait for the stage 1 thread to finish and capture the results. */
5327
  inline void finish_stage1_thread() noexcept;
5328
5329
  /** The error returned from the stage 1 thread. */
5330
  error_code stage1_thread_error{UNINITIALIZED};
5331
  /** The thread used to run stage 1 against the next batch in the background. */
5332
  friend struct stage1_worker;
5333
  std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
5334
  /**
5335
   * The parser used to run stage 1 in the background. Will be swapped
5336
   * with the regular parser when finished.
5337
   */
5338
  dom::parser stage1_thread_parser{};
5339
#endif // SIMDJSON_THREADS_ENABLED
5340
5341
  friend class dom::parser;
5342
  friend struct simdjson_result<dom::document_stream>;
5343
  friend struct internal::simdjson_result_base<dom::document_stream>;
5344
5345
}; // class document_stream
5346
5347
} // namespace dom
5348
5349
template<>
5350
struct simdjson_result<dom::document_stream> : public internal::simdjson_result_base<dom::document_stream> {
5351
public:
5352
  simdjson_inline simdjson_result() noexcept; ///< @private
5353
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
5354
  simdjson_inline simdjson_result(dom::document_stream &&value) noexcept; ///< @private
5355
5356
#if SIMDJSON_EXCEPTIONS
5357
  simdjson_inline dom::document_stream::iterator begin() noexcept(false);
5358
  simdjson_inline dom::document_stream::iterator end() noexcept(false);
5359
#else // SIMDJSON_EXCEPTIONS
5360
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
5361
  [[deprecated("parse_many() and load_many() may return errors. Use document_stream stream; error = parser.parse_many().get(doc); instead.")]]
5362
  simdjson_inline dom::document_stream::iterator begin() noexcept;
5363
  [[deprecated("parse_many() and load_many() may return errors. Use document_stream stream; error = parser.parse_many().get(doc); instead.")]]
5364
  simdjson_inline dom::document_stream::iterator end() noexcept;
5365
#endif // SIMDJSON_DISABLE_DEPRECATED_API
5366
#endif // SIMDJSON_EXCEPTIONS
5367
}; // struct simdjson_result<dom::document_stream>
5368
5369
} // namespace simdjson
5370
5371
#endif // SIMDJSON_DOCUMENT_STREAM_H
5372
/* end file simdjson/dom/document_stream.h */
5373
/* skipped duplicate #include "simdjson/dom/document.h" */
5374
/* including simdjson/dom/element.h: #include "simdjson/dom/element.h" */
5375
/* begin file simdjson/dom/element.h */
5376
#ifndef SIMDJSON_DOM_ELEMENT_H
5377
#define SIMDJSON_DOM_ELEMENT_H
5378
5379
/* skipped duplicate #include "simdjson/dom/base.h" */
5380
/* skipped duplicate #include "simdjson/dom/array.h" */
5381
5382
namespace simdjson {
5383
namespace dom {
5384
5385
/**
5386
 * The actual concrete type of a JSON element
5387
 * This is the type it is most easily cast to with get<>.
5388
 */
5389
enum class element_type {
5390
  ARRAY = '[',     ///< dom::array
5391
  OBJECT = '{',    ///< dom::object
5392
  INT64 = 'l',     ///< int64_t
5393
  UINT64 = 'u',    ///< uint64_t: any integer that fits in uint64_t but *not* int64_t
5394
  DOUBLE = 'd',    ///< double: Any number with a "." or "e" that fits in double.
5395
  STRING = '"',    ///< std::string_view
5396
  BOOL = 't',      ///< bool
5397
  NULL_VALUE = 'n' ///< null
5398
};
5399
5400
/**
5401
 * A JSON element.
5402
 *
5403
 * References an element in a JSON document, representing a JSON null, boolean, string, number,
5404
 * array or object.
5405
 */
5406
class element {
5407
public:
5408
  /** Create a new, invalid element. */
5409
  simdjson_inline element() noexcept;
5410
5411
  /** The type of this element. */
5412
  simdjson_inline element_type type() const noexcept;
5413
5414
  /**
5415
   * Cast this element to an array.
5416
   *
5417
   * @returns An object that can be used to iterate the array, or:
5418
   *          INCORRECT_TYPE if the JSON element is not an array.
5419
   */
5420
  inline simdjson_result<array> get_array() const noexcept;
5421
  /**
5422
   * Cast this element to an object.
5423
   *
5424
   * @returns An object that can be used to look up or iterate the object's fields, or:
5425
   *          INCORRECT_TYPE if the JSON element is not an object.
5426
   */
5427
  inline simdjson_result<object> get_object() const noexcept;
5428
  /**
5429
   * Cast this element to a null-terminated C string.
5430
   *
5431
   * The string is guaranteed to be valid UTF-8.
5432
   *
5433
   * The length of the string is given by get_string_length(). Because JSON strings
5434
   * may contain null characters, it may be incorrect to use strlen to determine the
5435
   * string length.
5436
   *
5437
   * It is possible to get a single string_view instance which represents both the string
5438
   * content and its length: see get_string().
5439
   *
5440
   * @returns A pointer to a null-terminated UTF-8 string. This string is stored in the parser and will
5441
   *          be invalidated the next time it parses a document or when it is destroyed.
5442
   *          Returns INCORRECT_TYPE if the JSON element is not a string.
5443
   */
5444
  inline simdjson_result<const char *> get_c_str() const noexcept;
5445
  /**
5446
   * Gives the length in bytes of the string.
5447
   *
5448
   * It is possible to get a single string_view instance which represents both the string
5449
   * content and its length: see get_string().
5450
   *
5451
   * @returns A string length in bytes.
5452
   *          Returns INCORRECT_TYPE if the JSON element is not a string.
5453
   */
5454
  inline simdjson_result<size_t> get_string_length() const noexcept;
5455
  /**
5456
   * Cast this element to a string.
5457
   *
5458
   * The string is guaranteed to be valid UTF-8.
5459
   *
5460
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next time it
5461
   *          parses a document or when it is destroyed.
5462
   *          Returns INCORRECT_TYPE if the JSON element is not a string.
5463
   */
5464
  inline simdjson_result<std::string_view> get_string() const noexcept;
5465
  /**
5466
   * Cast this element to a signed integer.
5467
   *
5468
   * @returns A signed 64-bit integer.
5469
   *          Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
5470
   *          if it is negative.
5471
   */
5472
  inline simdjson_result<int64_t> get_int64() const noexcept;
5473
  /**
5474
   * Cast this element to an unsigned integer.
5475
   *
5476
   * @returns An unsigned 64-bit integer.
5477
   *          Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
5478
   *          if it is too large.
5479
   */
5480
  inline simdjson_result<uint64_t> get_uint64() const noexcept;
5481
  /**
5482
   * Cast this element to a double floating-point.
5483
   *
5484
   * @returns A double value.
5485
   *          Returns INCORRECT_TYPE if the JSON element is not a number.
5486
   */
5487
  inline simdjson_result<double> get_double() const noexcept;
5488
  /**
5489
   * Cast this element to a bool.
5490
   *
5491
   * @returns A bool value.
5492
   *          Returns INCORRECT_TYPE if the JSON element is not a boolean.
5493
   */
5494
  inline simdjson_result<bool> get_bool() const noexcept;
5495
5496
  /**
5497
   * Whether this element is a json array.
5498
   *
5499
   * Equivalent to is<array>().
5500
   */
5501
  inline bool is_array() const noexcept;
5502
  /**
5503
   * Whether this element is a json object.
5504
   *
5505
   * Equivalent to is<object>().
5506
   */
5507
  inline bool is_object() const noexcept;
5508
  /**
5509
   * Whether this element is a json string.
5510
   *
5511
   * Equivalent to is<std::string_view>() or is<const char *>().
5512
   */
5513
  inline bool is_string() const noexcept;
5514
  /**
5515
   * Whether this element is a json number that fits in a signed 64-bit integer.
5516
   *
5517
   * Equivalent to is<int64_t>().
5518
   */
5519
  inline bool is_int64() const noexcept;
5520
  /**
5521
   * Whether this element is a json number that fits in an unsigned 64-bit integer.
5522
   *
5523
   * Equivalent to is<uint64_t>().
5524
   */
5525
  inline bool is_uint64() const noexcept;
5526
  /**
5527
   * Whether this element is a json number that fits in a double.
5528
   *
5529
   * Equivalent to is<double>().
5530
   */
5531
  inline bool is_double() const noexcept;
5532
5533
  /**
5534
   * Whether this element is a json number.
5535
   *
5536
   * Both integers and floating points will return true.
5537
   */
5538
  inline bool is_number() const noexcept;
5539
5540
  /**
5541
   * Whether this element is a json `true` or `false`.
5542
   *
5543
   * Equivalent to is<bool>().
5544
   */
5545
  inline bool is_bool() const noexcept;
5546
  /**
5547
   * Whether this element is a json `null`.
5548
   */
5549
  inline bool is_null() const noexcept;
5550
5551
  /**
5552
   * Tell whether the value can be cast to provided type (T).
5553
   *
5554
   * Supported types:
5555
   * - Boolean: bool
5556
   * - Number: double, uint64_t, int64_t
5557
   * - String: std::string_view, const char *
5558
   * - Array: dom::array
5559
   * - Object: dom::object
5560
   *
5561
   * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
5562
   */
5563
  template<typename T>
5564
  simdjson_inline bool is() const noexcept;
5565
5566
  /**
5567
   * Get the value as the provided type (T).
5568
   *
5569
   * Supported types:
5570
   * - Boolean: bool
5571
   * - Number: double, uint64_t, int64_t
5572
   * - String: std::string_view, const char *
5573
   * - Array: dom::array
5574
   * - Object: dom::object
5575
   *
5576
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
5577
   * get_object(), get_array() or get_string() instead.
5578
   *
5579
   * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
5580
   *
5581
   * @returns The value cast to the given type, or:
5582
   *          INCORRECT_TYPE if the value cannot be cast to the given type.
5583
   */
5584
5585
  template<typename T>
5586
  inline simdjson_result<T> get() const noexcept {
5587
    // Unless the simdjson library provides an inline implementation, calling this method should
5588
    // immediately fail.
5589
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
5590
      "The supported types are Boolean (bool), numbers (double, uint64_t, int64_t), "
5591
      "strings (std::string_view, const char *), arrays (dom::array) and objects (dom::object). "
5592
      "We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
5593
      "get_object(), get_array() or get_string() instead of the get template.");
5594
  }
5595
5596
  /**
5597
   * Get the value as the provided type (T).
5598
   *
5599
   * Supported types:
5600
   * - Boolean: bool
5601
   * - Number: double, uint64_t, int64_t
5602
   * - String: std::string_view, const char *
5603
   * - Array: dom::array
5604
   * - Object: dom::object
5605
   *
5606
   * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
5607
   *
5608
   * @param value The variable to set to the value. May not be set if there is an error.
5609
   *
5610
   * @returns The error that occurred, or SUCCESS if there was no error.
5611
   */
5612
  template<typename T>
5613
  simdjson_warn_unused simdjson_inline error_code get(T &value) const noexcept;
5614
5615
  /**
5616
   * Get the value as the provided type (T), setting error if it's not the given type.
5617
   *
5618
   * Supported types:
5619
   * - Boolean: bool
5620
   * - Number: double, uint64_t, int64_t
5621
   * - String: std::string_view, const char *
5622
   * - Array: dom::array
5623
   * - Object: dom::object
5624
   *
5625
   * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
5626
   *
5627
   * @param value The variable to set to the given type. value is undefined if there is an error.
5628
   * @param error The variable to store the error. error is set to error_code::SUCCEED if there is an error.
5629
   */
5630
  template<typename T>
5631
  inline void tie(T &value, error_code &error) && noexcept;
5632
5633
#if SIMDJSON_EXCEPTIONS
5634
  /**
5635
   * Read this element as a boolean.
5636
   *
5637
   * @return The boolean value
5638
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a boolean.
5639
   */
5640
  inline operator bool() const noexcept(false);
5641
5642
  /**
5643
   * Read this element as a null-terminated UTF-8 string.
5644
   *
5645
   * Be mindful that JSON allows strings to contain null characters.
5646
   *
5647
   * Does *not* convert other types to a string; requires that the JSON type of the element was
5648
   * an actual string.
5649
   *
5650
   * @return The string value.
5651
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a string.
5652
   */
5653
  inline explicit operator const char*() const noexcept(false);
5654
5655
  /**
5656
   * Read this element as a null-terminated UTF-8 string.
5657
   *
5658
   * Does *not* convert other types to a string; requires that the JSON type of the element was
5659
   * an actual string.
5660
   *
5661
   * @return The string value.
5662
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a string.
5663
   */
5664
  inline operator std::string_view() const noexcept(false);
5665
5666
  /**
5667
   * Read this element as an unsigned integer.
5668
   *
5669
   * @return The integer value.
5670
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an integer
5671
   * @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer does not fit in 64 bits or is negative
5672
   */
5673
  inline operator uint64_t() const noexcept(false);
5674
  /**
5675
   * Read this element as an signed integer.
5676
   *
5677
   * @return The integer value.
5678
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an integer
5679
   * @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer does not fit in 64 bits
5680
   */
5681
  inline operator int64_t() const noexcept(false);
5682
  /**
5683
   * Read this element as an double.
5684
   *
5685
   * @return The double value.
5686
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a number
5687
   */
5688
  inline operator double() const noexcept(false);
5689
  /**
5690
   * Read this element as a JSON array.
5691
   *
5692
   * @return The JSON array.
5693
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
5694
   */
5695
  inline operator array() const noexcept(false);
5696
  /**
5697
   * Read this element as a JSON object (key/value pairs).
5698
   *
5699
   * @return The JSON object.
5700
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an object
5701
   */
5702
  inline operator object() const noexcept(false);
5703
5704
  /**
5705
   * Iterate over each element in this array.
5706
   *
5707
   * @return The beginning of the iteration.
5708
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
5709
   */
5710
  inline dom::array::iterator begin() const noexcept(false);
5711
5712
  /**
5713
   * Iterate over each element in this array.
5714
   *
5715
   * @return The end of the iteration.
5716
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
5717
   */
5718
  inline dom::array::iterator end() const noexcept(false);
5719
#endif // SIMDJSON_EXCEPTIONS
5720
5721
  /**
5722
   * Get the value associated with the given key.
5723
   *
5724
   * The key will be matched against **unescaped** JSON:
5725
   *
5726
   *   dom::parser parser;
5727
   *   int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
5728
   *   parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
5729
   *
5730
   * @return The value associated with this field, or:
5731
   *         - NO_SUCH_FIELD if the field does not exist in the object
5732
   *         - INCORRECT_TYPE if this is not an object
5733
   */
5734
  inline simdjson_result<element> operator[](std::string_view key) const noexcept;
5735
5736
  /**
5737
   * Get the value associated with the given key.
5738
   *
5739
   * The key will be matched against **unescaped** JSON:
5740
   *
5741
   *   dom::parser parser;
5742
   *   int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
5743
   *   parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
5744
   *
5745
   * @return The value associated with this field, or:
5746
   *         - NO_SUCH_FIELD if the field does not exist in the object
5747
   *         - INCORRECT_TYPE if this is not an object
5748
   */
5749
  inline simdjson_result<element> operator[](const char *key) const noexcept;
5750
5751
  /**
5752
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
5753
   * https://tools.ietf.org/html/rfc6901 standard.
5754
   *
5755
   *   dom::parser parser;
5756
   *   element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded);
5757
   *   doc.at_pointer("/foo/a/1") == 20
5758
   *   doc.at_pointer("/foo")["a"].at(1) == 20
5759
   *   doc.at_pointer("")["foo"]["a"].at(1) == 20
5760
   *
5761
   * It is allowed for a key to be the empty string:
5762
   *
5763
   *   dom::parser parser;
5764
   *   object obj = parser.parse(R"({ "": { "a": [ 10, 20, 30 ] }})"_padded);
5765
   *   obj.at_pointer("//a/1") == 20
5766
   *
5767
   * @return The value associated with the given JSON pointer, or:
5768
   *         - NO_SUCH_FIELD if a field does not exist in an object
5769
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
5770
   *         - INCORRECT_TYPE if a non-integer is used to access an array
5771
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
5772
   */
5773
  inline simdjson_result<element> at_pointer(const std::string_view json_pointer) const noexcept;
5774
5775
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
5776
  /**
5777
   *
5778
   * Version 0.4 of simdjson used an incorrect interpretation of the JSON Pointer standard
5779
   * and allowed the following :
5780
   *
5781
   *   dom::parser parser;
5782
   *   element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded);
5783
   *   doc.at("foo/a/1") == 20
5784
   *
5785
   * Though it is intuitive, it is not compliant with RFC 6901
5786
   * https://tools.ietf.org/html/rfc6901
5787
   *
5788
   * For standard compliance, use the at_pointer function instead.
5789
   *
5790
   * @return The value associated with the given JSON pointer, or:
5791
   *         - NO_SUCH_FIELD if a field does not exist in an object
5792
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
5793
   *         - INCORRECT_TYPE if a non-integer is used to access an array
5794
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
5795
   */
5796
  [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
5797
  inline simdjson_result<element> at(const std::string_view json_pointer) const noexcept;
5798
#endif // SIMDJSON_DISABLE_DEPRECATED_API
5799
5800
  /**
5801
   * Get the value at the given index.
5802
   *
5803
   * @return The value at the given index, or:
5804
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
5805
   */
5806
  inline simdjson_result<element> at(size_t index) const noexcept;
5807
5808
  /**
5809
   * Get the value associated with the given key.
5810
   *
5811
   * The key will be matched against **unescaped** JSON:
5812
   *
5813
   *   dom::parser parser;
5814
   *   int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
5815
   *   parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
5816
   *
5817
   * @return The value associated with this field, or:
5818
   *         - NO_SUCH_FIELD if the field does not exist in the object
5819
   */
5820
  inline simdjson_result<element> at_key(std::string_view key) const noexcept;
5821
5822
  /**
5823
   * Get the value associated with the given key in a case-insensitive manner.
5824
   *
5825
   * Note: The key will be matched against **unescaped** JSON.
5826
   *
5827
   * @return The value associated with this field, or:
5828
   *         - NO_SUCH_FIELD if the field does not exist in the object
5829
   */
5830
  inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
5831
5832
  /**
5833
   * operator< defines a total order for element allowing to use them in
5834
   * ordered C++ STL containers
5835
   *
5836
   * @return TRUE if the key appears before the other one in the tape
5837
   */
5838
  inline bool operator<(const element &other) const noexcept;
5839
5840
  /**
5841
   * operator== allows to verify if two element values reference the
5842
   * same JSON item
5843
   *
5844
   * @return TRUE if the two values references the same JSON element
5845
   */
5846
  inline bool operator==(const element &other) const noexcept;
5847
5848
  /** @private for debugging. Prints out the root element. */
5849
  inline bool dump_raw_tape(std::ostream &out) const noexcept;
5850
5851
private:
5852
  simdjson_inline element(const internal::tape_ref &tape) noexcept;
5853
  internal::tape_ref tape;
5854
  friend class document;
5855
  friend class object;
5856
  friend class array;
5857
  friend struct simdjson_result<element>;
5858
  template<typename T>
5859
  friend class simdjson::internal::string_builder;
5860
5861
};
5862
5863
} // namespace dom
5864
5865
/** The result of a JSON navigation that may fail. */
5866
template<>
5867
struct simdjson_result<dom::element> : public internal::simdjson_result_base<dom::element> {
5868
public:
5869
  simdjson_inline simdjson_result() noexcept; ///< @private
5870
  simdjson_inline simdjson_result(dom::element &&value) noexcept; ///< @private
5871
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
5872
5873
  simdjson_inline simdjson_result<dom::element_type> type() const noexcept;
5874
  template<typename T>
5875
  simdjson_inline bool is() const noexcept;
5876
  template<typename T>
5877
  simdjson_inline simdjson_result<T> get() const noexcept;
5878
  template<typename T>
5879
  simdjson_warn_unused simdjson_inline error_code get(T &value) const noexcept;
5880
5881
  simdjson_inline simdjson_result<dom::array> get_array() const noexcept;
5882
  simdjson_inline simdjson_result<dom::object> get_object() const noexcept;
5883
  simdjson_inline simdjson_result<const char *> get_c_str() const noexcept;
5884
  simdjson_inline simdjson_result<size_t> get_string_length() const noexcept;
5885
  simdjson_inline simdjson_result<std::string_view> get_string() const noexcept;
5886
  simdjson_inline simdjson_result<int64_t> get_int64() const noexcept;
5887
  simdjson_inline simdjson_result<uint64_t> get_uint64() const noexcept;
5888
  simdjson_inline simdjson_result<double> get_double() const noexcept;
5889
  simdjson_inline simdjson_result<bool> get_bool() const noexcept;
5890
5891
  simdjson_inline bool is_array() const noexcept;
5892
  simdjson_inline bool is_object() const noexcept;
5893
  simdjson_inline bool is_string() const noexcept;
5894
  simdjson_inline bool is_int64() const noexcept;
5895
  simdjson_inline bool is_uint64() const noexcept;
5896
  simdjson_inline bool is_double() const noexcept;
5897
  simdjson_inline bool is_number() const noexcept;
5898
  simdjson_inline bool is_bool() const noexcept;
5899
  simdjson_inline bool is_null() const noexcept;
5900
5901
  simdjson_inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept;
5902
  simdjson_inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
5903
  simdjson_inline simdjson_result<dom::element> at_pointer(const std::string_view json_pointer) const noexcept;
5904
  [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
5905
  simdjson_inline simdjson_result<dom::element> at(const std::string_view json_pointer) const noexcept;
5906
  simdjson_inline simdjson_result<dom::element> at(size_t index) const noexcept;
5907
  simdjson_inline simdjson_result<dom::element> at_key(std::string_view key) const noexcept;
5908
  simdjson_inline simdjson_result<dom::element> at_key_case_insensitive(std::string_view key) const noexcept;
5909
5910
#if SIMDJSON_EXCEPTIONS
5911
  simdjson_inline operator bool() const noexcept(false);
5912
  simdjson_inline explicit operator const char*() const noexcept(false);
5913
  simdjson_inline operator std::string_view() const noexcept(false);
5914
  simdjson_inline operator uint64_t() const noexcept(false);
5915
  simdjson_inline operator int64_t() const noexcept(false);
5916
  simdjson_inline operator double() const noexcept(false);
5917
  simdjson_inline operator dom::array() const noexcept(false);
5918
  simdjson_inline operator dom::object() const noexcept(false);
5919
5920
  simdjson_inline dom::array::iterator begin() const noexcept(false);
5921
  simdjson_inline dom::array::iterator end() const noexcept(false);
5922
#endif // SIMDJSON_EXCEPTIONS
5923
};
5924
5925
} // namespace simdjson
5926
5927
#endif // SIMDJSON_DOM_DOCUMENT_H
5928
/* end file simdjson/dom/element.h */
5929
/* including simdjson/dom/object.h: #include "simdjson/dom/object.h" */
5930
/* begin file simdjson/dom/object.h */
5931
#ifndef SIMDJSON_DOM_OBJECT_H
5932
#define SIMDJSON_DOM_OBJECT_H
5933
5934
/* skipped duplicate #include "simdjson/dom/base.h" */
5935
/* skipped duplicate #include "simdjson/dom/element.h" */
5936
/* skipped duplicate #include "simdjson/internal/tape_ref.h" */
5937
5938
namespace simdjson {
5939
namespace dom {
5940
5941
/**
5942
 * JSON object.
5943
 */
5944
class object {
5945
public:
5946
  /** Create a new, invalid object */
5947
  simdjson_inline object() noexcept;
5948
5949
  class iterator {
5950
  public:
5951
    using value_type = const key_value_pair;
5952
    using difference_type = std::ptrdiff_t;
5953
    using pointer = void;
5954
    using reference = value_type;
5955
    using iterator_category = std::forward_iterator_tag;
5956
5957
    /**
5958
     * Get the actual key/value pair
5959
     */
5960
    inline reference operator*() const noexcept;
5961
    /**
5962
     * Get the next key/value pair.
5963
     *
5964
     * Part of the std::iterator interface.
5965
     *
5966
     */
5967
    inline iterator& operator++() noexcept;
5968
    /**
5969
     * Get the next key/value pair.
5970
     *
5971
     * Part of the std::iterator interface.
5972
     *
5973
     */
5974
    inline iterator operator++(int) noexcept;
5975
    /**
5976
     * Check if these values come from the same place in the JSON.
5977
     *
5978
     * Part of the std::iterator interface.
5979
     */
5980
    inline bool operator!=(const iterator& other) const noexcept;
5981
    inline bool operator==(const iterator& other) const noexcept;
5982
5983
    inline bool operator<(const iterator& other) const noexcept;
5984
    inline bool operator<=(const iterator& other) const noexcept;
5985
    inline bool operator>=(const iterator& other) const noexcept;
5986
    inline bool operator>(const iterator& other) const noexcept;
5987
    /**
5988
     * Get the key of this key/value pair.
5989
     */
5990
    inline std::string_view key() const noexcept;
5991
    /**
5992
     * Get the length (in bytes) of the key in this key/value pair.
5993
     * You should expect this function to be faster than key().size().
5994
     */
5995
    inline uint32_t key_length() const noexcept;
5996
    /**
5997
     * Returns true if the key in this key/value pair is equal
5998
     * to the provided string_view.
5999
     */
6000
    inline bool key_equals(std::string_view o) const noexcept;
6001
    /**
6002
     * Returns true if the key in this key/value pair is equal
6003
     * to the provided string_view in a case-insensitive manner.
6004
     * Case comparisons may only be handled correctly for ASCII strings.
6005
     */
6006
    inline bool key_equals_case_insensitive(std::string_view o) const noexcept;
6007
    /**
6008
     * Get the key of this key/value pair.
6009
     */
6010
    inline const char *key_c_str() const noexcept;
6011
    /**
6012
     * Get the value of this key/value pair.
6013
     */
6014
    inline element value() const noexcept;
6015
6016
    iterator() noexcept = default;
6017
    iterator(const iterator&) noexcept = default;
6018
    iterator& operator=(const iterator&) noexcept = default;
6019
  private:
6020
    simdjson_inline iterator(const internal::tape_ref &tape) noexcept;
6021
6022
    internal::tape_ref tape;
6023
6024
    friend class object;
6025
  };
6026
6027
  /**
6028
   * Return the first key/value pair.
6029
   *
6030
   * Part of the std::iterable interface.
6031
   */
6032
  inline iterator begin() const noexcept;
6033
  /**
6034
   * One past the last key/value pair.
6035
   *
6036
   * Part of the std::iterable interface.
6037
   */
6038
  inline iterator end() const noexcept;
6039
  /**
6040
   * Get the size of the object (number of keys).
6041
   * It is a saturated value with a maximum of 0xFFFFFF: if the value
6042
   * is 0xFFFFFF then the size is 0xFFFFFF or greater.
6043
   */
6044
  inline size_t size() const noexcept;
6045
  /**
6046
   * Get the value associated with the given key.
6047
   *
6048
   * The key will be matched against **unescaped** JSON:
6049
   *
6050
   *   dom::parser parser;
6051
   *   int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
6052
   *   parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
6053
   *
6054
   * This function has linear-time complexity: the keys are checked one by one.
6055
   *
6056
   * @return The value associated with this field, or:
6057
   *         - NO_SUCH_FIELD if the field does not exist in the object
6058
   *         - INCORRECT_TYPE if this is not an object
6059
   */
6060
  inline simdjson_result<element> operator[](std::string_view key) const noexcept;
6061
6062
  /**
6063
   * Get the value associated with the given key.
6064
   *
6065
   * The key will be matched against **unescaped** JSON:
6066
   *
6067
   *   dom::parser parser;
6068
   *   int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
6069
   *   parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
6070
   *
6071
   * This function has linear-time complexity: the keys are checked one by one.
6072
   *
6073
   * @return The value associated with this field, or:
6074
   *         - NO_SUCH_FIELD if the field does not exist in the object
6075
   *         - INCORRECT_TYPE if this is not an object
6076
   */
6077
  inline simdjson_result<element> operator[](const char *key) const noexcept;
6078
6079
  /**
6080
   * Get the value associated with the given JSON pointer. We use the RFC 6901
6081
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
6082
   * as the root of its own JSON document.
6083
   *
6084
   *   dom::parser parser;
6085
   *   object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded);
6086
   *   obj.at_pointer("/foo/a/1") == 20
6087
   *   obj.at_pointer("/foo")["a"].at(1) == 20
6088
   *
6089
   * It is allowed for a key to be the empty string:
6090
   *
6091
   *   dom::parser parser;
6092
   *   object obj = parser.parse(R"({ "": { "a": [ 10, 20, 30 ] }})"_padded);
6093
   *   obj.at_pointer("//a/1") == 20
6094
   *   obj.at_pointer("/")["a"].at(1) == 20
6095
   *
6096
   * @return The value associated with the given JSON pointer, or:
6097
   *         - NO_SUCH_FIELD if a field does not exist in an object
6098
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
6099
   *         - INCORRECT_TYPE if a non-integer is used to access an array
6100
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
6101
   */
6102
  inline simdjson_result<element> at_pointer(std::string_view json_pointer) const noexcept;
6103
6104
  /**
6105
   * Get the value associated with the given key.
6106
   *
6107
   * The key will be matched against **unescaped** JSON:
6108
   *
6109
   *   dom::parser parser;
6110
   *   int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
6111
   *   parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
6112
   *
6113
   * This function has linear-time complexity: the keys are checked one by one.
6114
   *
6115
   * @return The value associated with this field, or:
6116
   *         - NO_SUCH_FIELD if the field does not exist in the object
6117
   */
6118
  inline simdjson_result<element> at_key(std::string_view key) const noexcept;
6119
6120
  /**
6121
   * Get the value associated with the given key in a case-insensitive manner.
6122
   * It is only guaranteed to work over ASCII inputs.
6123
   *
6124
   * Note: The key will be matched against **unescaped** JSON.
6125
   *
6126
   * This function has linear-time complexity: the keys are checked one by one.
6127
   *
6128
   * @return The value associated with this field, or:
6129
   *         - NO_SUCH_FIELD if the field does not exist in the object
6130
   */
6131
  inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
6132
6133
private:
6134
  simdjson_inline object(const internal::tape_ref &tape) noexcept;
6135
6136
  internal::tape_ref tape;
6137
6138
  friend class element;
6139
  friend struct simdjson_result<element>;
6140
  template<typename T>
6141
  friend class simdjson::internal::string_builder;
6142
};
6143
6144
/**
6145
 * Key/value pair in an object.
6146
 */
6147
class key_value_pair {
6148
public:
6149
  /** key in the key-value pair **/
6150
  std::string_view key;
6151
  /** value in the key-value pair **/
6152
  element value;
6153
6154
private:
6155
  simdjson_inline key_value_pair(std::string_view _key, element _value) noexcept;
6156
  friend class object;
6157
};
6158
6159
} // namespace dom
6160
6161
/** The result of a JSON conversion that may fail. */
6162
template<>
6163
struct simdjson_result<dom::object> : public internal::simdjson_result_base<dom::object> {
6164
public:
6165
  simdjson_inline simdjson_result() noexcept; ///< @private
6166
  simdjson_inline simdjson_result(dom::object value) noexcept; ///< @private
6167
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
6168
6169
  inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept;
6170
  inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
6171
  inline simdjson_result<dom::element> at_pointer(std::string_view json_pointer) const noexcept;
6172
  inline simdjson_result<dom::element> at_key(std::string_view key) const noexcept;
6173
  inline simdjson_result<dom::element> at_key_case_insensitive(std::string_view key) const noexcept;
6174
6175
#if SIMDJSON_EXCEPTIONS
6176
  inline dom::object::iterator begin() const noexcept(false);
6177
  inline dom::object::iterator end() const noexcept(false);
6178
  inline size_t size() const noexcept(false);
6179
#endif // SIMDJSON_EXCEPTIONS
6180
};
6181
6182
} // namespace simdjson
6183
6184
#if defined(__cpp_lib_ranges)
6185
#include <ranges>
6186
6187
namespace std {
6188
namespace ranges {
6189
template<>
6190
inline constexpr bool enable_view<simdjson::dom::object> = true;
6191
#if SIMDJSON_EXCEPTIONS
6192
template<>
6193
inline constexpr bool enable_view<simdjson::simdjson_result<simdjson::dom::object>> = true;
6194
#endif // SIMDJSON_EXCEPTIONS
6195
} // namespace ranges
6196
} // namespace std
6197
#endif // defined(__cpp_lib_ranges)
6198
6199
#endif // SIMDJSON_DOM_OBJECT_H
6200
/* end file simdjson/dom/object.h */
6201
/* skipped duplicate #include "simdjson/dom/parser.h" */
6202
/* including simdjson/dom/serialization.h: #include "simdjson/dom/serialization.h" */
6203
/* begin file simdjson/dom/serialization.h */
6204
#ifndef SIMDJSON_SERIALIZATION_H
6205
#define SIMDJSON_SERIALIZATION_H
6206
6207
/* skipped duplicate #include "simdjson/dom/base.h" */
6208
/* skipped duplicate #include "simdjson/dom/element.h" */
6209
/* skipped duplicate #include "simdjson/dom/object.h" */
6210
6211
#include <vector>
6212
6213
namespace simdjson {
6214
6215
/**
6216
 * The string_builder template and mini_formatter class
6217
 * are not part of  our public API and are subject to change
6218
 * at any time!
6219
 */
6220
namespace internal {
6221
6222
template<class formatter>
6223
class base_formatter {
6224
public:
6225
  /** Add a comma **/
6226
  simdjson_inline void comma();
6227
  /** Start an array, prints [ **/
6228
  simdjson_inline void start_array();
6229
  /** End an array, prints ] **/
6230
  simdjson_inline void end_array();
6231
  /** Start an array, prints { **/
6232
  simdjson_inline void start_object();
6233
  /** Start an array, prints } **/
6234
  simdjson_inline void end_object();
6235
  /** Prints a true **/
6236
  simdjson_inline void true_atom();
6237
  /** Prints a false **/
6238
  simdjson_inline void false_atom();
6239
  /** Prints a null **/
6240
  simdjson_inline void null_atom();
6241
  /** Prints a number **/
6242
  simdjson_inline void number(int64_t x);
6243
  /** Prints a number **/
6244
  simdjson_inline void number(uint64_t x);
6245
  /** Prints a number **/
6246
  simdjson_inline void number(double x);
6247
  /** Prints a key (string + colon) **/
6248
  simdjson_inline void key(std::string_view unescaped);
6249
  /** Prints a string. The string is escaped as needed. **/
6250
  simdjson_inline void string(std::string_view unescaped);
6251
  /** Clears out the content. **/
6252
  simdjson_inline void clear();
6253
  /**
6254
   * Get access to the buffer, it is owned by the instance, but
6255
   * the user can make a copy.
6256
   **/
6257
  simdjson_inline std::string_view str() const;
6258
6259
  /** Prints one character **/
6260
  simdjson_inline void one_char(char c);
6261
6262
  simdjson_inline void call_print_newline() {
6263
      this->print_newline();
6264
  }
6265
6266
  simdjson_inline void call_print_indents(size_t depth) {
6267
      this->print_indents(depth);
6268
  }
6269
6270
  simdjson_inline void call_print_space() {
6271
      this->print_space();
6272
  }
6273
6274
protected:
6275
  // implementation details (subject to change)
6276
  /** Backing buffer **/
6277
  std::vector<char> buffer{}; // not ideal!
6278
};
6279
6280
6281
/**
6282
 * @private This is the class that we expect to use with the string_builder
6283
 * template. It tries to produce a compact version of the JSON element
6284
 * as quickly as possible.
6285
 */
6286
class mini_formatter : public base_formatter<mini_formatter> {
6287
public:
6288
  simdjson_inline void print_newline();
6289
6290
  simdjson_inline void print_indents(size_t depth);
6291
6292
  simdjson_inline void print_space();
6293
};
6294
6295
class pretty_formatter : public base_formatter<pretty_formatter> {
6296
public:
6297
  simdjson_inline void print_newline();
6298
6299
  simdjson_inline void print_indents(size_t depth);
6300
6301
  simdjson_inline void print_space();
6302
6303
protected:
6304
  int indent_step = 4;
6305
};
6306
6307
/**
6308
 * @private The string_builder template allows us to construct
6309
 * a string from a document element. It is parametrized
6310
 * by a "formatter" which handles the details. Thus
6311
 * the string_builder template could support both minification
6312
 * and prettification, and various other tradeoffs.
6313
 */
6314
template <class formatter = mini_formatter>
6315
class string_builder {
6316
public:
6317
  /** Construct an initially empty builder, would print the empty string **/
6318
  string_builder() = default;
6319
  /** Append an element to the builder (to be printed) **/
6320
  inline void append(simdjson::dom::element value);
6321
  /** Append an array to the builder (to be printed) **/
6322
  inline void append(simdjson::dom::array value);
6323
  /** Append an object to the builder (to be printed) **/
6324
  inline void append(simdjson::dom::object value);
6325
  /** Reset the builder (so that it would print the empty string) **/
6326
  simdjson_inline void clear();
6327
  /**
6328
   * Get access to the string. The string_view is owned by the builder
6329
   * and it is invalid to use it after the string_builder has been
6330
   * destroyed.
6331
   * However you can make a copy of the string_view on memory that you
6332
   * own.
6333
   */
6334
  simdjson_inline std::string_view str() const;
6335
  /** Append a key_value_pair to the builder (to be printed) **/
6336
  simdjson_inline void append(simdjson::dom::key_value_pair value);
6337
private:
6338
  formatter format{};
6339
};
6340
6341
} // internal
6342
6343
namespace dom {
6344
6345
/**
6346
 * Print JSON to an output stream.
6347
 *
6348
 * @param out The output stream.
6349
 * @param value The element.
6350
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
6351
 */
6352
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value);
6353
#if SIMDJSON_EXCEPTIONS
6354
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x);
6355
#endif
6356
/**
6357
 * Print JSON to an output stream.
6358
 *
6359
 * @param out The output stream.
6360
 * @param value The array.
6361
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
6362
 */
6363
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value);
6364
#if SIMDJSON_EXCEPTIONS
6365
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x);
6366
#endif
6367
/**
6368
 * Print JSON to an output stream.
6369
 *
6370
 * @param out The output stream.
6371
 * @param value The object.
6372
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
6373
 */
6374
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value);
6375
#if SIMDJSON_EXCEPTIONS
6376
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::dom::object> x);
6377
#endif
6378
} // namespace dom
6379
6380
/**
6381
 * Converts JSON to a string.
6382
 *
6383
 *   dom::parser parser;
6384
 *   element doc = parser.parse("   [ 1 , 2 , 3 ] "_padded);
6385
 *   cout << to_string(doc) << endl; // prints [1,2,3]
6386
 *
6387
 */
6388
template <class T>
6389
std::string to_string(T x)   {
6390
    // in C++, to_string is standard: http://www.cplusplus.com/reference/string/to_string/
6391
    // Currently minify and to_string are identical but in the future, they may
6392
    // differ.
6393
    simdjson::internal::string_builder<> sb;
6394
    sb.append(x);
6395
    std::string_view answer = sb.str();
6396
    return std::string(answer.data(), answer.size());
6397
}
6398
#if SIMDJSON_EXCEPTIONS
6399
template <class T>
6400
std::string to_string(simdjson_result<T> x) {
6401
    if (x.error()) { throw simdjson_error(x.error()); }
6402
    return to_string(x.value());
6403
}
6404
#endif
6405
6406
/**
6407
 * Minifies a JSON element or document, printing the smallest possible valid JSON.
6408
 *
6409
 *   dom::parser parser;
6410
 *   element doc = parser.parse("   [ 1 , 2 , 3 ] "_padded);
6411
 *   cout << minify(doc) << endl; // prints [1,2,3]
6412
 *
6413
 */
6414
template <class T>
6415
std::string minify(T x)  {
6416
  return to_string(x);
6417
}
6418
6419
#if SIMDJSON_EXCEPTIONS
6420
template <class T>
6421
std::string minify(simdjson_result<T> x) {
6422
    if (x.error()) { throw simdjson_error(x.error()); }
6423
    return to_string(x.value());
6424
}
6425
#endif
6426
6427
/**
6428
 * Prettifies a JSON element or document, printing the valid JSON with indentation.
6429
 *
6430
 *   dom::parser parser;
6431
 *   element doc = parser.parse("   [ 1 , 2 , 3 ] "_padded);
6432
 *
6433
 *   // Prints:
6434
 *   // {
6435
 *   //     [
6436
 *   //         1,
6437
 *   //         2,
6438
 *   //         3
6439
 *   //     ]
6440
 *   // }
6441
 *   cout << prettify(doc) << endl;
6442
 *
6443
 */
6444
template <class T>
6445
std::string prettify(T x)  {
6446
    simdjson::internal::string_builder<simdjson::internal::pretty_formatter> sb;
6447
    sb.append(x);
6448
    std::string_view answer = sb.str();
6449
    return std::string(answer.data(), answer.size());
6450
}
6451
6452
#if SIMDJSON_EXCEPTIONS
6453
template <class T>
6454
std::string prettify(simdjson_result<T> x) {
6455
    if (x.error()) { throw simdjson_error(x.error()); }
6456
    return to_string(x.value());
6457
}
6458
#endif
6459
6460
} // namespace simdjson
6461
6462
6463
#endif
6464
/* end file simdjson/dom/serialization.h */
6465
6466
// Inline functions
6467
/* including simdjson/dom/array-inl.h: #include "simdjson/dom/array-inl.h" */
6468
/* begin file simdjson/dom/array-inl.h */
6469
#ifndef SIMDJSON_ARRAY_INL_H
6470
#define SIMDJSON_ARRAY_INL_H
6471
6472
#include <utility>
6473
6474
/* skipped duplicate #include "simdjson/dom/base.h" */
6475
/* skipped duplicate #include "simdjson/dom/array.h" */
6476
/* skipped duplicate #include "simdjson/dom/element.h" */
6477
/* skipped duplicate #include "simdjson/error-inl.h" */
6478
/* including simdjson/internal/tape_ref-inl.h: #include "simdjson/internal/tape_ref-inl.h" */
6479
/* begin file simdjson/internal/tape_ref-inl.h */
6480
#ifndef SIMDJSON_TAPE_REF_INL_H
6481
#define SIMDJSON_TAPE_REF_INL_H
6482
6483
/* skipped duplicate #include "simdjson/dom/document.h" */
6484
/* skipped duplicate #include "simdjson/internal/tape_ref.h" */
6485
/* including simdjson/internal/tape_type.h: #include "simdjson/internal/tape_type.h" */
6486
/* begin file simdjson/internal/tape_type.h */
6487
#ifndef SIMDJSON_INTERNAL_TAPE_TYPE_H
6488
#define SIMDJSON_INTERNAL_TAPE_TYPE_H
6489
6490
namespace simdjson {
6491
namespace internal {
6492
6493
/**
6494
 * The possible types in the tape.
6495
 */
6496
enum class tape_type {
6497
  ROOT = 'r',
6498
  START_ARRAY = '[',
6499
  START_OBJECT = '{',
6500
  END_ARRAY = ']',
6501
  END_OBJECT = '}',
6502
  STRING = '"',
6503
  INT64 = 'l',
6504
  UINT64 = 'u',
6505
  DOUBLE = 'd',
6506
  TRUE_VALUE = 't',
6507
  FALSE_VALUE = 'f',
6508
  NULL_VALUE = 'n'
6509
}; // enum class tape_type
6510
6511
} // namespace internal
6512
} // namespace simdjson
6513
6514
#endif // SIMDJSON_INTERNAL_TAPE_TYPE_H
6515
/* end file simdjson/internal/tape_type.h */
6516
6517
#include <cstring>
6518
6519
namespace simdjson {
6520
namespace internal {
6521
6522
constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
6523
constexpr const uint32_t JSON_COUNT_MASK = 0xFFFFFF;
6524
6525
//
6526
// tape_ref inline implementation
6527
//
6528
simdjson_inline tape_ref::tape_ref() noexcept : doc{nullptr}, json_index{0} {}
6529
simdjson_inline tape_ref::tape_ref(const dom::document *_doc, size_t _json_index) noexcept : doc{_doc}, json_index{_json_index} {}
6530
6531
6532
0
simdjson_inline bool tape_ref::is_document_root() const noexcept {
6533
0
  return json_index == 1; // should we ever change the structure of the tape, this should get updated.
6534
0
}
6535
0
simdjson_inline bool tape_ref::usable() const noexcept {
6536
0
  return doc != nullptr; // when the document pointer is null, this tape_ref is uninitialized (should not be accessed).
6537
0
}
6538
// Some value types have a specific on-tape word value. It can be faster
6539
// to check the type by doing a word-to-word comparison instead of extracting the
6540
// most significant 8 bits.
6541
6542
0
simdjson_inline bool tape_ref::is_double() const noexcept {
6543
0
  constexpr uint64_t tape_double = uint64_t(tape_type::DOUBLE)<<56;
6544
0
  return doc->tape[json_index] == tape_double;
6545
0
}
6546
0
simdjson_inline bool tape_ref::is_int64() const noexcept {
6547
0
  constexpr uint64_t tape_int64 = uint64_t(tape_type::INT64)<<56;
6548
0
  return doc->tape[json_index] == tape_int64;
6549
0
}
6550
0
simdjson_inline bool tape_ref::is_uint64() const noexcept {
6551
0
  constexpr uint64_t tape_uint64 = uint64_t(tape_type::UINT64)<<56;
6552
0
  return doc->tape[json_index] == tape_uint64;
6553
0
}
6554
0
simdjson_inline bool tape_ref::is_false() const noexcept {
6555
0
  constexpr uint64_t tape_false = uint64_t(tape_type::FALSE_VALUE)<<56;
6556
0
  return doc->tape[json_index] == tape_false;
6557
0
}
6558
0
simdjson_inline bool tape_ref::is_true() const noexcept {
6559
0
  constexpr uint64_t tape_true = uint64_t(tape_type::TRUE_VALUE)<<56;
6560
0
  return doc->tape[json_index] == tape_true;
6561
0
}
6562
0
simdjson_inline bool tape_ref::is_null_on_tape() const noexcept {
6563
0
  constexpr uint64_t tape_null = uint64_t(tape_type::NULL_VALUE)<<56;
6564
0
  return doc->tape[json_index] == tape_null;
6565
0
}
6566
6567
0
inline size_t tape_ref::after_element() const noexcept {
6568
0
  switch (tape_ref_type()) {
6569
0
    case tape_type::START_ARRAY:
6570
0
    case tape_type::START_OBJECT:
6571
0
      return matching_brace_index();
6572
0
    case tape_type::UINT64:
6573
0
    case tape_type::INT64:
6574
0
    case tape_type::DOUBLE:
6575
0
      return json_index + 2;
6576
0
    default:
6577
0
      return json_index + 1;
6578
0
  }
6579
0
}
6580
0
simdjson_inline tape_type tape_ref::tape_ref_type() const noexcept {
6581
0
  return static_cast<tape_type>(doc->tape[json_index] >> 56);
6582
0
}
6583
0
simdjson_inline uint64_t internal::tape_ref::tape_value() const noexcept {
6584
0
  return doc->tape[json_index] & internal::JSON_VALUE_MASK;
6585
0
}
6586
0
simdjson_inline uint32_t internal::tape_ref::matching_brace_index() const noexcept {
6587
0
  return uint32_t(doc->tape[json_index]);
6588
0
}
6589
0
simdjson_inline uint32_t internal::tape_ref::scope_count() const noexcept {
6590
0
  return uint32_t((doc->tape[json_index] >> 32) & internal::JSON_COUNT_MASK);
6591
0
}
6592
6593
template<typename T>
6594
0
simdjson_inline T tape_ref::next_tape_value() const noexcept {
6595
0
  static_assert(sizeof(T) == sizeof(uint64_t), "next_tape_value() template parameter must be 64-bit");
6596
0
  // Though the following is tempting...
6597
0
  //  return *reinterpret_cast<const T*>(&doc->tape[json_index + 1]);
6598
0
  // It is not generally safe. It is safer, and often faster to rely
6599
0
  // on memcpy. Yes, it is uglier, but it is also encapsulated.
6600
0
  T x;
6601
0
  std::memcpy(&x,&doc->tape[json_index + 1],sizeof(uint64_t));
6602
0
  return x;
6603
0
}
Unexecuted instantiation: long simdjson::internal::tape_ref::next_tape_value<long>() const
Unexecuted instantiation: unsigned long simdjson::internal::tape_ref::next_tape_value<unsigned long>() const
Unexecuted instantiation: double simdjson::internal::tape_ref::next_tape_value<double>() const
6604
6605
0
simdjson_inline uint32_t internal::tape_ref::get_string_length() const noexcept {
6606
0
  size_t string_buf_index = size_t(tape_value());
6607
0
  uint32_t len;
6608
0
  std::memcpy(&len, &doc->string_buf[string_buf_index], sizeof(len));
6609
0
  return len;
6610
0
}
6611
6612
0
simdjson_inline const char * internal::tape_ref::get_c_str() const noexcept {
6613
0
  size_t string_buf_index = size_t(tape_value());
6614
0
  return reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]);
6615
0
}
6616
6617
0
inline std::string_view internal::tape_ref::get_string_view() const noexcept {
6618
0
  return std::string_view(
6619
0
      get_c_str(),
6620
0
      get_string_length()
6621
0
  );
6622
0
}
6623
6624
} // namespace internal
6625
} // namespace simdjson
6626
6627
#endif // SIMDJSON_TAPE_REF_INL_H
6628
/* end file simdjson/internal/tape_ref-inl.h */
6629
6630
#include <limits>
6631
6632
namespace simdjson {
6633
6634
//
6635
// simdjson_result<dom::array> inline implementation
6636
//
6637
simdjson_inline simdjson_result<dom::array>::simdjson_result() noexcept
6638
    : internal::simdjson_result_base<dom::array>() {}
6639
simdjson_inline simdjson_result<dom::array>::simdjson_result(dom::array value) noexcept
6640
    : internal::simdjson_result_base<dom::array>(std::forward<dom::array>(value)) {}
6641
simdjson_inline simdjson_result<dom::array>::simdjson_result(error_code error) noexcept
6642
    : internal::simdjson_result_base<dom::array>(error) {}
6643
6644
#if SIMDJSON_EXCEPTIONS
6645
6646
inline dom::array::iterator simdjson_result<dom::array>::begin() const noexcept(false) {
6647
  if (error()) { throw simdjson_error(error()); }
6648
  return first.begin();
6649
}
6650
inline dom::array::iterator simdjson_result<dom::array>::end() const noexcept(false) {
6651
  if (error()) { throw simdjson_error(error()); }
6652
  return first.end();
6653
}
6654
inline size_t simdjson_result<dom::array>::size() const noexcept(false) {
6655
  if (error()) { throw simdjson_error(error()); }
6656
  return first.size();
6657
}
6658
6659
#endif // SIMDJSON_EXCEPTIONS
6660
6661
0
inline simdjson_result<dom::element> simdjson_result<dom::array>::at_pointer(std::string_view json_pointer) const noexcept {
6662
0
  if (error()) { return error(); }
6663
0
  return first.at_pointer(json_pointer);
6664
0
}
6665
0
inline simdjson_result<dom::element> simdjson_result<dom::array>::at(size_t index) const noexcept {
6666
0
  if (error()) { return error(); }
6667
0
  return first.at(index);
6668
0
}
6669
6670
namespace dom {
6671
6672
//
6673
// array inline implementation
6674
//
6675
simdjson_inline array::array() noexcept : tape{} {}
6676
simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
6677
0
inline array::iterator array::begin() const noexcept {
6678
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6679
0
  return internal::tape_ref(tape.doc, tape.json_index + 1);
6680
0
}
6681
0
inline array::iterator array::end() const noexcept {
6682
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6683
0
  return internal::tape_ref(tape.doc, tape.after_element() - 1);
6684
0
}
6685
0
inline size_t array::size() const noexcept {
6686
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6687
0
  return tape.scope_count();
6688
0
}
6689
0
inline size_t array::number_of_slots() const noexcept {
6690
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6691
0
  return tape.matching_brace_index() - tape.json_index;
6692
0
}
6693
0
inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) const noexcept {
6694
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6695
0
  if(json_pointer.empty()) { // an empty string means that we return the current node
6696
0
      return element(this->tape); // copy the current node
6697
0
  } else if(json_pointer[0] != '/') { // otherwise there is an error
6698
0
      return INVALID_JSON_POINTER;
6699
0
  }
6700
0
  json_pointer = json_pointer.substr(1);
6701
0
  // - means "the append position" or "the element after the end of the array"
6702
0
  // We don't support this, because we're returning a real element, not a position.
6703
0
  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
6704
0
6705
0
  // Read the array index
6706
0
  size_t array_index = 0;
6707
0
  size_t i;
6708
0
  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
6709
0
    uint8_t digit = uint8_t(json_pointer[i] - '0');
6710
0
    // Check for non-digit in array index. If it's there, we're trying to get a field in an object
6711
0
    if (digit > 9) { return INCORRECT_TYPE; }
6712
0
    array_index = array_index*10 + digit;
6713
0
  }
6714
0
6715
0
  // 0 followed by other digits is invalid
6716
0
  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
6717
0
6718
0
  // Empty string is invalid; so is a "/" with no digits before it
6719
0
  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
6720
0
6721
0
  // Get the child
6722
0
  auto child = array(tape).at(array_index);
6723
0
  // If there is an error, it ends here
6724
0
  if(child.error()) {
6725
0
    return child;
6726
0
  }
6727
0
  // If there is a /, we're not done yet, call recursively.
6728
0
  if (i < json_pointer.length()) {
6729
0
    child = child.at_pointer(json_pointer.substr(i));
6730
0
  }
6731
0
  return child;
6732
0
}
6733
6734
0
inline simdjson_result<element> array::at(size_t index) const noexcept {
6735
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6736
0
  size_t i=0;
6737
0
  for (auto element : *this) {
6738
0
    if (i == index) { return element; }
6739
0
    i++;
6740
0
  }
6741
0
  return INDEX_OUT_OF_BOUNDS;
6742
0
}
6743
6744
//
6745
// array::iterator inline implementation
6746
//
6747
simdjson_inline array::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
6748
0
inline element array::iterator::operator*() const noexcept {
6749
0
  return element(tape);
6750
0
}
6751
0
inline array::iterator& array::iterator::operator++() noexcept {
6752
0
  tape.json_index = tape.after_element();
6753
0
  return *this;
6754
0
}
6755
0
inline array::iterator array::iterator::operator++(int) noexcept {
6756
0
  array::iterator out = *this;
6757
0
  ++*this;
6758
0
  return out;
6759
0
}
6760
0
inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
6761
0
  return tape.json_index != other.tape.json_index;
6762
0
}
6763
0
inline bool array::iterator::operator==(const array::iterator& other) const noexcept {
6764
0
  return tape.json_index == other.tape.json_index;
6765
0
}
6766
0
inline bool array::iterator::operator<(const array::iterator& other) const noexcept {
6767
0
  return tape.json_index < other.tape.json_index;
6768
0
}
6769
0
inline bool array::iterator::operator<=(const array::iterator& other) const noexcept {
6770
0
  return tape.json_index <= other.tape.json_index;
6771
0
}
6772
0
inline bool array::iterator::operator>=(const array::iterator& other) const noexcept {
6773
0
  return tape.json_index >= other.tape.json_index;
6774
0
}
6775
0
inline bool array::iterator::operator>(const array::iterator& other) const noexcept {
6776
0
  return tape.json_index > other.tape.json_index;
6777
0
}
6778
6779
} // namespace dom
6780
6781
6782
} // namespace simdjson
6783
6784
/* including simdjson/dom/element-inl.h: #include "simdjson/dom/element-inl.h" */
6785
/* begin file simdjson/dom/element-inl.h */
6786
#ifndef SIMDJSON_ELEMENT_INL_H
6787
#define SIMDJSON_ELEMENT_INL_H
6788
6789
/* skipped duplicate #include "simdjson/dom/base.h" */
6790
/* skipped duplicate #include "simdjson/dom/element.h" */
6791
/* skipped duplicate #include "simdjson/dom/document.h" */
6792
/* skipped duplicate #include "simdjson/dom/object.h" */
6793
/* skipped duplicate #include "simdjson/internal/tape_type.h" */
6794
6795
/* including simdjson/dom/object-inl.h: #include "simdjson/dom/object-inl.h" */
6796
/* begin file simdjson/dom/object-inl.h */
6797
#ifndef SIMDJSON_OBJECT_INL_H
6798
#define SIMDJSON_OBJECT_INL_H
6799
6800
/* skipped duplicate #include "simdjson/dom/base.h" */
6801
/* skipped duplicate #include "simdjson/dom/object.h" */
6802
/* skipped duplicate #include "simdjson/dom/document.h" */
6803
6804
/* skipped duplicate #include "simdjson/dom/element-inl.h" */
6805
/* skipped duplicate #include "simdjson/error-inl.h" */
6806
6807
#include <cstring>
6808
6809
namespace simdjson {
6810
6811
//
6812
// simdjson_result<dom::object> inline implementation
6813
//
6814
simdjson_inline simdjson_result<dom::object>::simdjson_result() noexcept
6815
    : internal::simdjson_result_base<dom::object>() {}
6816
simdjson_inline simdjson_result<dom::object>::simdjson_result(dom::object value) noexcept
6817
    : internal::simdjson_result_base<dom::object>(std::forward<dom::object>(value)) {}
6818
simdjson_inline simdjson_result<dom::object>::simdjson_result(error_code error) noexcept
6819
    : internal::simdjson_result_base<dom::object>(error) {}
6820
6821
0
inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](std::string_view key) const noexcept {
6822
0
  if (error()) { return error(); }
6823
0
  return first[key];
6824
0
}
6825
0
inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](const char *key) const noexcept {
6826
0
  if (error()) { return error(); }
6827
0
  return first[key];
6828
0
}
6829
0
inline simdjson_result<dom::element> simdjson_result<dom::object>::at_pointer(std::string_view json_pointer) const noexcept {
6830
0
  if (error()) { return error(); }
6831
0
  return first.at_pointer(json_pointer);
6832
0
}
6833
0
inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key(std::string_view key) const noexcept {
6834
0
  if (error()) { return error(); }
6835
0
  return first.at_key(key);
6836
0
}
6837
0
inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key_case_insensitive(std::string_view key) const noexcept {
6838
0
  if (error()) { return error(); }
6839
0
  return first.at_key_case_insensitive(key);
6840
0
}
6841
6842
#if SIMDJSON_EXCEPTIONS
6843
6844
inline dom::object::iterator simdjson_result<dom::object>::begin() const noexcept(false) {
6845
  if (error()) { throw simdjson_error(error()); }
6846
  return first.begin();
6847
}
6848
inline dom::object::iterator simdjson_result<dom::object>::end() const noexcept(false) {
6849
  if (error()) { throw simdjson_error(error()); }
6850
  return first.end();
6851
}
6852
inline size_t simdjson_result<dom::object>::size() const noexcept(false) {
6853
  if (error()) { throw simdjson_error(error()); }
6854
  return first.size();
6855
}
6856
6857
#endif // SIMDJSON_EXCEPTIONS
6858
6859
namespace dom {
6860
6861
//
6862
// object inline implementation
6863
//
6864
simdjson_inline object::object() noexcept : tape{} {}
6865
simdjson_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
6866
0
inline object::iterator object::begin() const noexcept {
6867
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6868
0
  return internal::tape_ref(tape.doc, tape.json_index + 1);
6869
0
}
6870
0
inline object::iterator object::end() const noexcept {
6871
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6872
0
  return internal::tape_ref(tape.doc, tape.after_element() - 1);
6873
0
}
6874
0
inline size_t object::size() const noexcept {
6875
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6876
0
  return tape.scope_count();
6877
0
}
6878
6879
0
inline simdjson_result<element> object::operator[](std::string_view key) const noexcept {
6880
0
  return at_key(key);
6881
0
}
6882
0
inline simdjson_result<element> object::operator[](const char *key) const noexcept {
6883
0
  return at_key(key);
6884
0
}
6885
0
inline simdjson_result<element> object::at_pointer(std::string_view json_pointer) const noexcept {
6886
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
6887
0
  if(json_pointer.empty()) { // an empty string means that we return the current node
6888
0
      return element(this->tape); // copy the current node
6889
0
  } else if(json_pointer[0] != '/') { // otherwise there is an error
6890
0
      return INVALID_JSON_POINTER;
6891
0
  }
6892
0
  json_pointer = json_pointer.substr(1);
6893
0
  size_t slash = json_pointer.find('/');
6894
0
  std::string_view key = json_pointer.substr(0, slash);
6895
0
  // Grab the child with the given key
6896
0
  simdjson_result<element> child;
6897
0
6898
0
  // If there is an escape character in the key, unescape it and then get the child.
6899
0
  size_t escape = key.find('~');
6900
0
  if (escape != std::string_view::npos) {
6901
0
    // Unescape the key
6902
0
    std::string unescaped(key);
6903
0
    do {
6904
0
      switch (unescaped[escape+1]) {
6905
0
        case '0':
6906
0
          unescaped.replace(escape, 2, "~");
6907
0
          break;
6908
0
        case '1':
6909
0
          unescaped.replace(escape, 2, "/");
6910
0
          break;
6911
0
        default:
6912
0
          return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
6913
0
      }
6914
0
      escape = unescaped.find('~', escape+1);
6915
0
    } while (escape != std::string::npos);
6916
0
    child = at_key(unescaped);
6917
0
  } else {
6918
0
    child = at_key(key);
6919
0
  }
6920
0
  if(child.error()) {
6921
0
    return child; // we do not continue if there was an error
6922
0
  }
6923
0
  // If there is a /, we have to recurse and look up more of the path
6924
0
  if (slash != std::string_view::npos) {
6925
0
    child = child.at_pointer(json_pointer.substr(slash));
6926
0
  }
6927
0
  return child;
6928
0
}
6929
6930
0
inline simdjson_result<element> object::at_key(std::string_view key) const noexcept {
6931
0
  iterator end_field = end();
6932
0
  for (iterator field = begin(); field != end_field; ++field) {
6933
0
    if (field.key_equals(key)) {
6934
0
      return field.value();
6935
0
    }
6936
0
  }
6937
0
  return NO_SUCH_FIELD;
6938
0
}
6939
// In case you wonder why we need this, please see
6940
// https://github.com/simdjson/simdjson/issues/323
6941
// People do seek keys in a case-insensitive manner.
6942
0
inline simdjson_result<element> object::at_key_case_insensitive(std::string_view key) const noexcept {
6943
0
  iterator end_field = end();
6944
0
  for (iterator field = begin(); field != end_field; ++field) {
6945
0
    if (field.key_equals_case_insensitive(key)) {
6946
0
      return field.value();
6947
0
    }
6948
0
  }
6949
0
  return NO_SUCH_FIELD;
6950
0
}
6951
6952
//
6953
// object::iterator inline implementation
6954
//
6955
simdjson_inline object::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
6956
0
inline const key_value_pair object::iterator::operator*() const noexcept {
6957
0
  return key_value_pair(key(), value());
6958
0
}
6959
0
inline bool object::iterator::operator!=(const object::iterator& other) const noexcept {
6960
0
  return tape.json_index != other.tape.json_index;
6961
0
}
6962
0
inline bool object::iterator::operator==(const object::iterator& other) const noexcept {
6963
0
  return tape.json_index == other.tape.json_index;
6964
0
}
6965
0
inline bool object::iterator::operator<(const object::iterator& other) const noexcept {
6966
0
  return tape.json_index < other.tape.json_index;
6967
0
}
6968
0
inline bool object::iterator::operator<=(const object::iterator& other) const noexcept {
6969
0
  return tape.json_index <= other.tape.json_index;
6970
0
}
6971
0
inline bool object::iterator::operator>=(const object::iterator& other) const noexcept {
6972
0
  return tape.json_index >= other.tape.json_index;
6973
0
}
6974
0
inline bool object::iterator::operator>(const object::iterator& other) const noexcept {
6975
0
  return tape.json_index > other.tape.json_index;
6976
0
}
6977
0
inline object::iterator& object::iterator::operator++() noexcept {
6978
0
  tape.json_index++;
6979
0
  tape.json_index = tape.after_element();
6980
0
  return *this;
6981
0
}
6982
0
inline object::iterator object::iterator::operator++(int) noexcept {
6983
0
  object::iterator out = *this;
6984
0
  ++*this;
6985
0
  return out;
6986
0
}
6987
0
inline std::string_view object::iterator::key() const noexcept {
6988
0
  return tape.get_string_view();
6989
0
}
6990
0
inline uint32_t object::iterator::key_length() const noexcept {
6991
0
  return tape.get_string_length();
6992
0
}
6993
0
inline const char* object::iterator::key_c_str() const noexcept {
6994
0
  return reinterpret_cast<const char *>(&tape.doc->string_buf[size_t(tape.tape_value()) + sizeof(uint32_t)]);
6995
0
}
6996
0
inline element object::iterator::value() const noexcept {
6997
0
  return element(internal::tape_ref(tape.doc, tape.json_index + 1));
6998
0
}
6999
7000
/**
7001
 * Design notes:
7002
 * Instead of constructing a string_view and then comparing it with a
7003
 * user-provided strings, it is probably more performant to have dedicated
7004
 * functions taking as a parameter the string we want to compare against
7005
 * and return true when they are equal. That avoids the creation of a temporary
7006
 * std::string_view. Though it is possible for the compiler to avoid entirely
7007
 * any overhead due to string_view, relying too much on compiler magic is
7008
 * problematic: compiler magic sometimes fail, and then what do you do?
7009
 * Also, enticing users to rely on high-performance function is probably better
7010
 * on the long run.
7011
 */
7012
7013
0
inline bool object::iterator::key_equals(std::string_view o) const noexcept {
7014
0
  // We use the fact that the key length can be computed quickly
7015
0
  // without access to the string buffer.
7016
0
  const uint32_t len = key_length();
7017
0
  if(o.size() == len) {
7018
0
    // We avoid construction of a temporary string_view instance.
7019
0
    return (memcmp(o.data(), key_c_str(), len) == 0);
7020
0
  }
7021
0
  return false;
7022
0
}
7023
7024
0
inline bool object::iterator::key_equals_case_insensitive(std::string_view o) const noexcept {
7025
0
  // We use the fact that the key length can be computed quickly
7026
0
  // without access to the string buffer.
7027
0
  const uint32_t len = key_length();
7028
0
  if(o.size() == len) {
7029
0
      // See For case-insensitive string comparisons, avoid char-by-char functions
7030
0
      // https://lemire.me/blog/2020/04/30/for-case-insensitive-string-comparisons-avoid-char-by-char-functions/
7031
0
      // Note that it might be worth rolling our own strncasecmp function, with vectorization.
7032
0
      return (simdjson_strncasecmp(o.data(), key_c_str(), len) == 0);
7033
0
  }
7034
0
  return false;
7035
0
}
7036
//
7037
// key_value_pair inline implementation
7038
//
7039
inline key_value_pair::key_value_pair(std::string_view _key, element _value) noexcept :
7040
  key(_key), value(_value) {}
7041
7042
} // namespace dom
7043
7044
} // namespace simdjson
7045
7046
#if defined(__cpp_lib_ranges)
7047
static_assert(std::ranges::view<simdjson::dom::object>);
7048
static_assert(std::ranges::sized_range<simdjson::dom::object>);
7049
#if SIMDJSON_EXCEPTIONS
7050
static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::object>>);
7051
static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::object>>);
7052
#endif // SIMDJSON_EXCEPTIONS
7053
#endif // defined(__cpp_lib_ranges)
7054
7055
#endif // SIMDJSON_OBJECT_INL_H
7056
/* end file simdjson/dom/object-inl.h */
7057
/* skipped duplicate #include "simdjson/error-inl.h" */
7058
7059
#include <ostream>
7060
#include <limits>
7061
7062
namespace simdjson {
7063
7064
//
7065
// simdjson_result<dom::element> inline implementation
7066
//
7067
simdjson_inline simdjson_result<dom::element>::simdjson_result() noexcept
7068
    : internal::simdjson_result_base<dom::element>() {}
7069
simdjson_inline simdjson_result<dom::element>::simdjson_result(dom::element &&value) noexcept
7070
    : internal::simdjson_result_base<dom::element>(std::forward<dom::element>(value)) {}
7071
simdjson_inline simdjson_result<dom::element>::simdjson_result(error_code error) noexcept
7072
    : internal::simdjson_result_base<dom::element>(error) {}
7073
0
inline simdjson_result<dom::element_type> simdjson_result<dom::element>::type() const noexcept {
7074
0
  if (error()) { return error(); }
7075
0
  return first.type();
7076
0
}
7077
7078
template<typename T>
7079
simdjson_inline bool simdjson_result<dom::element>::is() const noexcept {
7080
  return !error() && first.is<T>();
7081
}
7082
template<typename T>
7083
simdjson_inline simdjson_result<T> simdjson_result<dom::element>::get() const noexcept {
7084
  if (error()) { return error(); }
7085
  return first.get<T>();
7086
}
7087
template<typename T>
7088
simdjson_warn_unused simdjson_inline error_code simdjson_result<dom::element>::get(T &value) const noexcept {
7089
  if (error()) { return error(); }
7090
  return first.get<T>(value);
7091
}
7092
7093
0
simdjson_inline simdjson_result<dom::array> simdjson_result<dom::element>::get_array() const noexcept {
7094
0
  if (error()) { return error(); }
7095
0
  return first.get_array();
7096
0
}
7097
0
simdjson_inline simdjson_result<dom::object> simdjson_result<dom::element>::get_object() const noexcept {
7098
0
  if (error()) { return error(); }
7099
0
  return first.get_object();
7100
0
}
7101
0
simdjson_inline simdjson_result<const char *> simdjson_result<dom::element>::get_c_str() const noexcept {
7102
0
  if (error()) { return error(); }
7103
0
  return first.get_c_str();
7104
0
}
7105
0
simdjson_inline simdjson_result<size_t> simdjson_result<dom::element>::get_string_length() const noexcept {
7106
0
  if (error()) { return error(); }
7107
0
  return first.get_string_length();
7108
0
}
7109
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<dom::element>::get_string() const noexcept {
7110
0
  if (error()) { return error(); }
7111
0
  return first.get_string();
7112
0
}
7113
0
simdjson_inline simdjson_result<int64_t> simdjson_result<dom::element>::get_int64() const noexcept {
7114
0
  if (error()) { return error(); }
7115
0
  return first.get_int64();
7116
0
}
7117
0
simdjson_inline simdjson_result<uint64_t> simdjson_result<dom::element>::get_uint64() const noexcept {
7118
0
  if (error()) { return error(); }
7119
0
  return first.get_uint64();
7120
0
}
7121
0
simdjson_inline simdjson_result<double> simdjson_result<dom::element>::get_double() const noexcept {
7122
0
  if (error()) { return error(); }
7123
0
  return first.get_double();
7124
0
}
7125
0
simdjson_inline simdjson_result<bool> simdjson_result<dom::element>::get_bool() const noexcept {
7126
0
  if (error()) { return error(); }
7127
0
  return first.get_bool();
7128
0
}
7129
7130
0
simdjson_inline bool simdjson_result<dom::element>::is_array() const noexcept {
7131
0
  return !error() && first.is_array();
7132
0
}
7133
0
simdjson_inline bool simdjson_result<dom::element>::is_object() const noexcept {
7134
0
  return !error() && first.is_object();
7135
0
}
7136
0
simdjson_inline bool simdjson_result<dom::element>::is_string() const noexcept {
7137
0
  return !error() && first.is_string();
7138
0
}
7139
0
simdjson_inline bool simdjson_result<dom::element>::is_int64() const noexcept {
7140
0
  return !error() && first.is_int64();
7141
0
}
7142
0
simdjson_inline bool simdjson_result<dom::element>::is_uint64() const noexcept {
7143
0
  return !error() && first.is_uint64();
7144
0
}
7145
0
simdjson_inline bool simdjson_result<dom::element>::is_double() const noexcept {
7146
0
  return !error() && first.is_double();
7147
0
}
7148
0
simdjson_inline bool simdjson_result<dom::element>::is_number() const noexcept {
7149
0
  return !error() && first.is_number();
7150
0
}
7151
0
simdjson_inline bool simdjson_result<dom::element>::is_bool() const noexcept {
7152
0
  return !error() && first.is_bool();
7153
0
}
7154
7155
0
simdjson_inline bool simdjson_result<dom::element>::is_null() const noexcept {
7156
0
  return !error() && first.is_null();
7157
0
}
7158
7159
0
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](std::string_view key) const noexcept {
7160
0
  if (error()) { return error(); }
7161
0
  return first[key];
7162
0
}
7163
0
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](const char *key) const noexcept {
7164
0
  if (error()) { return error(); }
7165
0
  return first[key];
7166
0
}
7167
0
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_pointer(const std::string_view json_pointer) const noexcept {
7168
0
  if (error()) { return error(); }
7169
0
  return first.at_pointer(json_pointer);
7170
0
}
7171
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
7172
[[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
7173
0
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at(const std::string_view json_pointer) const noexcept {
7174
0
SIMDJSON_PUSH_DISABLE_WARNINGS
7175
0
SIMDJSON_DISABLE_DEPRECATED_WARNING
7176
0
  if (error()) { return error(); }
7177
0
  return first.at(json_pointer);
7178
0
SIMDJSON_POP_DISABLE_WARNINGS
7179
0
}
7180
#endif // SIMDJSON_DISABLE_DEPRECATED_API
7181
0
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at(size_t index) const noexcept {
7182
0
  if (error()) { return error(); }
7183
0
  return first.at(index);
7184
0
}
7185
0
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_key(std::string_view key) const noexcept {
7186
0
  if (error()) { return error(); }
7187
0
  return first.at_key(key);
7188
0
}
7189
0
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_key_case_insensitive(std::string_view key) const noexcept {
7190
0
  if (error()) { return error(); }
7191
0
  return first.at_key_case_insensitive(key);
7192
0
}
7193
7194
#if SIMDJSON_EXCEPTIONS
7195
7196
simdjson_inline simdjson_result<dom::element>::operator bool() const noexcept(false) {
7197
  return get<bool>();
7198
}
7199
simdjson_inline simdjson_result<dom::element>::operator const char *() const noexcept(false) {
7200
  return get<const char *>();
7201
}
7202
simdjson_inline simdjson_result<dom::element>::operator std::string_view() const noexcept(false) {
7203
  return get<std::string_view>();
7204
}
7205
simdjson_inline simdjson_result<dom::element>::operator uint64_t() const noexcept(false) {
7206
  return get<uint64_t>();
7207
}
7208
simdjson_inline simdjson_result<dom::element>::operator int64_t() const noexcept(false) {
7209
  return get<int64_t>();
7210
}
7211
simdjson_inline simdjson_result<dom::element>::operator double() const noexcept(false) {
7212
  return get<double>();
7213
}
7214
simdjson_inline simdjson_result<dom::element>::operator dom::array() const noexcept(false) {
7215
  return get<dom::array>();
7216
}
7217
simdjson_inline simdjson_result<dom::element>::operator dom::object() const noexcept(false) {
7218
  return get<dom::object>();
7219
}
7220
7221
simdjson_inline dom::array::iterator simdjson_result<dom::element>::begin() const noexcept(false) {
7222
  if (error()) { throw simdjson_error(error()); }
7223
  return first.begin();
7224
}
7225
simdjson_inline dom::array::iterator simdjson_result<dom::element>::end() const noexcept(false) {
7226
  if (error()) { throw simdjson_error(error()); }
7227
  return first.end();
7228
}
7229
7230
#endif // SIMDJSON_EXCEPTIONS
7231
7232
namespace dom {
7233
7234
//
7235
// element inline implementation
7236
//
7237
simdjson_inline element::element() noexcept : tape{} {}
7238
simdjson_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
7239
7240
0
inline element_type element::type() const noexcept {
7241
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7242
0
  auto tape_type = tape.tape_ref_type();
7243
0
  return tape_type == internal::tape_type::FALSE_VALUE ? element_type::BOOL : static_cast<element_type>(tape_type);
7244
0
}
7245
7246
0
inline simdjson_result<bool> element::get_bool() const noexcept {
7247
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7248
0
  if(tape.is_true()) {
7249
0
    return true;
7250
0
  } else if(tape.is_false()) {
7251
0
    return false;
7252
0
  }
7253
0
  return INCORRECT_TYPE;
7254
0
}
7255
0
inline simdjson_result<const char *> element::get_c_str() const noexcept {
7256
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7257
0
  switch (tape.tape_ref_type()) {
7258
0
    case internal::tape_type::STRING: {
7259
0
      return tape.get_c_str();
7260
0
    }
7261
0
    default:
7262
0
      return INCORRECT_TYPE;
7263
0
  }
7264
0
}
7265
0
inline simdjson_result<size_t> element::get_string_length() const noexcept {
7266
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7267
0
  switch (tape.tape_ref_type()) {
7268
0
    case internal::tape_type::STRING: {
7269
0
      return tape.get_string_length();
7270
0
    }
7271
0
    default:
7272
0
      return INCORRECT_TYPE;
7273
0
  }
7274
0
}
7275
0
inline simdjson_result<std::string_view> element::get_string() const noexcept {
7276
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7277
0
  switch (tape.tape_ref_type()) {
7278
0
    case internal::tape_type::STRING:
7279
0
      return tape.get_string_view();
7280
0
    default:
7281
0
      return INCORRECT_TYPE;
7282
0
  }
7283
0
}
7284
0
inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
7285
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7286
0
  if(simdjson_unlikely(!tape.is_uint64())) { // branch rarely taken
7287
0
    if(tape.is_int64()) {
7288
0
      int64_t result = tape.next_tape_value<int64_t>();
7289
0
      if (result < 0) {
7290
0
        return NUMBER_OUT_OF_RANGE;
7291
0
      }
7292
0
      return uint64_t(result);
7293
0
    }
7294
0
    return INCORRECT_TYPE;
7295
0
  }
7296
0
  return tape.next_tape_value<int64_t>();
7297
0
}
7298
0
inline simdjson_result<int64_t> element::get_int64() const noexcept {
7299
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7300
0
  if(simdjson_unlikely(!tape.is_int64())) { // branch rarely taken
7301
0
    if(tape.is_uint64()) {
7302
0
      uint64_t result = tape.next_tape_value<uint64_t>();
7303
0
      // Wrapping max in parens to handle Windows issue: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
7304
0
      if (result > uint64_t((std::numeric_limits<int64_t>::max)())) {
7305
0
        return NUMBER_OUT_OF_RANGE;
7306
0
      }
7307
0
      return static_cast<int64_t>(result);
7308
0
    }
7309
0
    return INCORRECT_TYPE;
7310
0
  }
7311
0
  return tape.next_tape_value<int64_t>();
7312
0
}
7313
0
inline simdjson_result<double> element::get_double() const noexcept {
7314
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7315
0
  // Performance considerations:
7316
0
  // 1. Querying tape_ref_type() implies doing a shift, it is fast to just do a straight
7317
0
  //   comparison.
7318
0
  // 2. Using a switch-case relies on the compiler guessing what kind of code generation
7319
0
  //    we want... But the compiler cannot know that we expect the type to be "double"
7320
0
  //    most of the time.
7321
0
  // We can expect get<double> to refer to a double type almost all the time.
7322
0
  // It is important to craft the code accordingly so that the compiler can use this
7323
0
  // information. (This could also be solved with profile-guided optimization.)
7324
0
  if(simdjson_unlikely(!tape.is_double())) { // branch rarely taken
7325
0
    if(tape.is_uint64()) {
7326
0
      return double(tape.next_tape_value<uint64_t>());
7327
0
    } else if(tape.is_int64()) {
7328
0
      return double(tape.next_tape_value<int64_t>());
7329
0
    }
7330
0
    return INCORRECT_TYPE;
7331
0
  }
7332
0
  // this is common:
7333
0
  return tape.next_tape_value<double>();
7334
0
}
7335
0
inline simdjson_result<array> element::get_array() const noexcept {
7336
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7337
0
  switch (tape.tape_ref_type()) {
7338
0
    case internal::tape_type::START_ARRAY:
7339
0
      return array(tape);
7340
0
    default:
7341
0
      return INCORRECT_TYPE;
7342
0
  }
7343
0
}
7344
0
inline simdjson_result<object> element::get_object() const noexcept {
7345
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7346
0
  switch (tape.tape_ref_type()) {
7347
0
    case internal::tape_type::START_OBJECT:
7348
0
      return object(tape);
7349
0
    default:
7350
0
      return INCORRECT_TYPE;
7351
0
  }
7352
0
}
7353
7354
template<typename T>
7355
simdjson_warn_unused simdjson_inline error_code element::get(T &value) const noexcept {
7356
  return get<T>().get(value);
7357
}
7358
// An element-specific version prevents recursion with simdjson_result::get<element>(value)
7359
template<>
7360
0
simdjson_warn_unused simdjson_inline error_code element::get<element>(element &value) const noexcept {
7361
0
  value = element(tape);
7362
0
  return SUCCESS;
7363
0
}
7364
template<typename T>
7365
inline void element::tie(T &value, error_code &error) && noexcept {
7366
  error = get<T>(value);
7367
}
7368
7369
template<typename T>
7370
0
simdjson_inline bool element::is() const noexcept {
7371
0
  auto result = get<T>();
7372
0
  return !result.error();
7373
0
}
Unexecuted instantiation: bool simdjson::dom::element::is<simdjson::dom::array>() const
Unexecuted instantiation: bool simdjson::dom::element::is<simdjson::dom::object>() const
Unexecuted instantiation: bool simdjson::dom::element::is<std::__1::basic_string_view<char, std::__1::char_traits<char> > >() const
Unexecuted instantiation: bool simdjson::dom::element::is<long>() const
Unexecuted instantiation: bool simdjson::dom::element::is<unsigned long>() const
Unexecuted instantiation: bool simdjson::dom::element::is<double>() const
Unexecuted instantiation: bool simdjson::dom::element::is<bool>() const
7374
7375
0
template<> inline simdjson_result<array> element::get<array>() const noexcept { return get_array(); }
7376
0
template<> inline simdjson_result<object> element::get<object>() const noexcept { return get_object(); }
7377
0
template<> inline simdjson_result<const char *> element::get<const char *>() const noexcept { return get_c_str(); }
7378
0
template<> inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept { return get_string(); }
7379
0
template<> inline simdjson_result<int64_t> element::get<int64_t>() const noexcept { return get_int64(); }
7380
0
template<> inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept { return get_uint64(); }
7381
0
template<> inline simdjson_result<double> element::get<double>() const noexcept { return get_double(); }
7382
0
template<> inline simdjson_result<bool> element::get<bool>() const noexcept { return get_bool(); }
7383
7384
0
inline bool element::is_array() const noexcept { return is<array>(); }
7385
0
inline bool element::is_object() const noexcept { return is<object>(); }
7386
0
inline bool element::is_string() const noexcept { return is<std::string_view>(); }
7387
0
inline bool element::is_int64() const noexcept { return is<int64_t>(); }
7388
0
inline bool element::is_uint64() const noexcept { return is<uint64_t>(); }
7389
0
inline bool element::is_double() const noexcept { return is<double>(); }
7390
0
inline bool element::is_bool() const noexcept { return is<bool>(); }
7391
0
inline bool element::is_number() const noexcept { return is_int64() || is_uint64() || is_double(); }
7392
7393
0
inline bool element::is_null() const noexcept {
7394
0
  return tape.is_null_on_tape();
7395
0
}
7396
7397
#if SIMDJSON_EXCEPTIONS
7398
7399
inline element::operator bool() const noexcept(false) { return get<bool>(); }
7400
inline element::operator const char*() const noexcept(false) { return get<const char *>(); }
7401
inline element::operator std::string_view() const noexcept(false) { return get<std::string_view>(); }
7402
inline element::operator uint64_t() const noexcept(false) { return get<uint64_t>(); }
7403
inline element::operator int64_t() const noexcept(false) { return get<int64_t>(); }
7404
inline element::operator double() const noexcept(false) { return get<double>(); }
7405
inline element::operator array() const noexcept(false) { return get<array>(); }
7406
inline element::operator object() const noexcept(false) { return get<object>(); }
7407
7408
inline array::iterator element::begin() const noexcept(false) {
7409
  return get<array>().begin();
7410
}
7411
inline array::iterator element::end() const noexcept(false) {
7412
  return get<array>().end();
7413
}
7414
7415
#endif // SIMDJSON_EXCEPTIONS
7416
7417
0
inline simdjson_result<element> element::operator[](std::string_view key) const noexcept {
7418
0
  return at_key(key);
7419
0
}
7420
0
inline simdjson_result<element> element::operator[](const char *key) const noexcept {
7421
0
  return at_key(key);
7422
0
}
7423
7424
0
inline simdjson_result<element> element::at_pointer(std::string_view json_pointer) const noexcept {
7425
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7426
0
  switch (tape.tape_ref_type()) {
7427
0
    case internal::tape_type::START_OBJECT:
7428
0
      return object(tape).at_pointer(json_pointer);
7429
0
    case internal::tape_type::START_ARRAY:
7430
0
      return array(tape).at_pointer(json_pointer);
7431
0
    default: {
7432
0
      if(!json_pointer.empty()) { // a non-empty string is invalid on an atom
7433
0
        return INVALID_JSON_POINTER;
7434
0
      }
7435
0
      // an empty string means that we return the current node
7436
0
      dom::element copy(*this);
7437
0
      return simdjson_result<element>(std::move(copy));
7438
0
    }
7439
0
  }
7440
0
}
7441
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
7442
[[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
7443
0
inline simdjson_result<element> element::at(std::string_view json_pointer) const noexcept {
7444
0
  // version 0.4 of simdjson allowed non-compliant pointers
7445
0
  auto std_pointer = (json_pointer.empty() ? "" : "/") + std::string(json_pointer.begin(), json_pointer.end());
7446
0
  return at_pointer(std_pointer);
7447
0
}
7448
#endif // SIMDJSON_DISABLE_DEPRECATED_API
7449
7450
0
inline simdjson_result<element> element::at(size_t index) const noexcept {
7451
0
  return get<array>().at(index);
7452
0
}
7453
0
inline simdjson_result<element> element::at_key(std::string_view key) const noexcept {
7454
0
  return get<object>().at_key(key);
7455
0
}
7456
0
inline simdjson_result<element> element::at_key_case_insensitive(std::string_view key) const noexcept {
7457
0
  return get<object>().at_key_case_insensitive(key);
7458
0
}
7459
0
inline bool element::operator<(const element &other) const noexcept {
7460
0
  return tape.json_index < other.tape.json_index;
7461
0
}
7462
0
inline bool element::operator==(const element &other) const noexcept {
7463
0
  return tape.json_index == other.tape.json_index;
7464
0
}
7465
7466
0
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
7467
0
  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
7468
0
  return tape.doc->dump_raw_tape(out);
7469
0
}
7470
7471
7472
0
inline std::ostream& operator<<(std::ostream& out, element_type type) {
7473
0
  switch (type) {
7474
0
    case element_type::ARRAY:
7475
0
      return out << "array";
7476
0
    case element_type::OBJECT:
7477
0
      return out << "object";
7478
0
    case element_type::INT64:
7479
0
      return out << "int64_t";
7480
0
    case element_type::UINT64:
7481
0
      return out << "uint64_t";
7482
0
    case element_type::DOUBLE:
7483
0
      return out << "double";
7484
0
    case element_type::STRING:
7485
0
      return out << "string";
7486
0
    case element_type::BOOL:
7487
0
      return out << "bool";
7488
0
    case element_type::NULL_VALUE:
7489
0
      return out << "null";
7490
0
    default:
7491
0
      return out << "unexpected content!!!"; // abort() usage is forbidden in the library
7492
0
  }
7493
0
}
7494
7495
} // namespace dom
7496
7497
} // namespace simdjson
7498
7499
#endif // SIMDJSON_ELEMENT_INL_H
7500
/* end file simdjson/dom/element-inl.h */
7501
7502
#if defined(__cpp_lib_ranges)
7503
static_assert(std::ranges::view<simdjson::dom::array>);
7504
static_assert(std::ranges::sized_range<simdjson::dom::array>);
7505
#if SIMDJSON_EXCEPTIONS
7506
static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::array>>);
7507
static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::array>>);
7508
#endif // SIMDJSON_EXCEPTIONS
7509
#endif // defined(__cpp_lib_ranges)
7510
7511
#endif // SIMDJSON_ARRAY_INL_H
7512
/* end file simdjson/dom/array-inl.h */
7513
/* including simdjson/dom/document_stream-inl.h: #include "simdjson/dom/document_stream-inl.h" */
7514
/* begin file simdjson/dom/document_stream-inl.h */
7515
#ifndef SIMDJSON_DOCUMENT_STREAM_INL_H
7516
#define SIMDJSON_DOCUMENT_STREAM_INL_H
7517
7518
/* skipped duplicate #include "simdjson/dom/base.h" */
7519
/* skipped duplicate #include "simdjson/dom/document_stream.h" */
7520
/* skipped duplicate #include "simdjson/dom/element-inl.h" */
7521
/* including simdjson/dom/parser-inl.h: #include "simdjson/dom/parser-inl.h" */
7522
/* begin file simdjson/dom/parser-inl.h */
7523
#ifndef SIMDJSON_PARSER_INL_H
7524
#define SIMDJSON_PARSER_INL_H
7525
7526
/* skipped duplicate #include "simdjson/dom/base.h" */
7527
/* skipped duplicate #include "simdjson/dom/document_stream.h" */
7528
/* skipped duplicate #include "simdjson/implementation.h" */
7529
/* skipped duplicate #include "simdjson/internal/dom_parser_implementation.h" */
7530
7531
/* skipped duplicate #include "simdjson/error-inl.h" */
7532
/* skipped duplicate #include "simdjson/padded_string-inl.h" */
7533
/* skipped duplicate #include "simdjson/dom/document_stream-inl.h" */
7534
/* skipped duplicate #include "simdjson/dom/element-inl.h" */
7535
7536
#include <climits>
7537
#include <cstring> /* memcmp */
7538
7539
namespace simdjson {
7540
namespace dom {
7541
7542
//
7543
// parser inline implementation
7544
//
7545
simdjson_inline parser::parser(size_t max_capacity) noexcept
7546
  : _max_capacity{max_capacity},
7547
    loaded_bytes(nullptr) {
7548
}
7549
simdjson_inline parser::parser(parser &&other) noexcept = default;
7550
0
simdjson_inline parser &parser::operator=(parser &&other) noexcept = default;
7551
7552
0
inline bool parser::is_valid() const noexcept { return valid; }
7553
0
inline int parser::get_error_code() const noexcept { return error; }
7554
0
inline std::string parser::get_error_message() const noexcept { return error_message(error); }
7555
7556
0
inline bool parser::dump_raw_tape(std::ostream &os) const noexcept {
7557
0
  return valid ? doc.dump_raw_tape(os) : false;
7558
0
}
7559
7560
0
inline simdjson_result<size_t> parser::read_file(const std::string &path) noexcept {
7561
0
  // Open the file
7562
0
  SIMDJSON_PUSH_DISABLE_WARNINGS
7563
0
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
7564
0
  std::FILE *fp = std::fopen(path.c_str(), "rb");
7565
0
  SIMDJSON_POP_DISABLE_WARNINGS
7566
0
7567
0
  if (fp == nullptr) {
7568
0
    return IO_ERROR;
7569
0
  }
7570
0
7571
0
  // Get the file size
7572
0
  int ret;
7573
0
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
7574
0
  ret = _fseeki64(fp, 0, SEEK_END);
7575
0
#else
7576
0
  ret = std::fseek(fp, 0, SEEK_END);
7577
0
#endif // _WIN64
7578
0
  if(ret < 0) {
7579
0
    std::fclose(fp);
7580
0
    return IO_ERROR;
7581
0
  }
7582
0
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
7583
0
  __int64 len = _ftelli64(fp);
7584
0
  if(len == -1L) {
7585
0
    std::fclose(fp);
7586
0
    return IO_ERROR;
7587
0
  }
7588
0
#else
7589
0
  long len = std::ftell(fp);
7590
0
  if((len < 0) || (len == LONG_MAX)) {
7591
0
    std::fclose(fp);
7592
0
    return IO_ERROR;
7593
0
  }
7594
0
#endif
7595
0
7596
0
  // Make sure we have enough capacity to load the file
7597
0
  if (_loaded_bytes_capacity < size_t(len)) {
7598
0
    loaded_bytes.reset( internal::allocate_padded_buffer(len) );
7599
0
    if (!loaded_bytes) {
7600
0
      std::fclose(fp);
7601
0
      return MEMALLOC;
7602
0
    }
7603
0
    _loaded_bytes_capacity = len;
7604
0
  }
7605
0
7606
0
  // Read the string
7607
0
  std::rewind(fp);
7608
0
  size_t bytes_read = std::fread(loaded_bytes.get(), 1, len, fp);
7609
0
  if (std::fclose(fp) != 0 || bytes_read != size_t(len)) {
7610
0
    return IO_ERROR;
7611
0
  }
7612
0
7613
0
  return bytes_read;
7614
0
}
7615
7616
0
inline simdjson_result<element> parser::load(const std::string &path) & noexcept {
7617
0
  return load_into_document(doc, path);
7618
0
}
7619
7620
0
inline simdjson_result<element> parser::load_into_document(document& provided_doc, const std::string &path) & noexcept {
7621
0
  size_t len;
7622
0
  auto _error = read_file(path).get(len);
7623
0
  if (_error) { return _error; }
7624
0
  return parse_into_document(provided_doc, loaded_bytes.get(), len, false);
7625
0
}
7626
7627
0
inline simdjson_result<document_stream> parser::load_many(const std::string &path, size_t batch_size) noexcept {
7628
0
  size_t len;
7629
0
  auto _error = read_file(path).get(len);
7630
0
  if (_error) { return _error; }
7631
0
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
7632
0
  return document_stream(*this, reinterpret_cast<const uint8_t*>(loaded_bytes.get()), len, batch_size);
7633
0
}
7634
7635
0
inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const uint8_t *buf, size_t len, bool realloc_if_needed) & noexcept {
7636
0
  // Important: we need to ensure that document has enough capacity.
7637
0
  // Important: It is possible that provided_doc is actually the internal 'doc' within the parser!!!
7638
0
  error_code _error = ensure_capacity(provided_doc, len);
7639
0
  if (_error) { return _error; }
7640
0
  if (realloc_if_needed) {
7641
0
    // Make sure we have enough capacity to copy len bytes
7642
0
    if (!loaded_bytes || _loaded_bytes_capacity < len) {
7643
0
      loaded_bytes.reset( internal::allocate_padded_buffer(len) );
7644
0
      if (!loaded_bytes) {
7645
0
        return MEMALLOC;
7646
0
      }
7647
0
      _loaded_bytes_capacity = len;
7648
0
    }
7649
0
    std::memcpy(static_cast<void *>(loaded_bytes.get()), buf, len);
7650
0
    buf = reinterpret_cast<const uint8_t*>(loaded_bytes.get());
7651
0
  }
7652
0
7653
0
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
7654
0
    buf += 3;
7655
0
    len -= 3;
7656
0
  }
7657
0
  _error = implementation->parse(buf, len, provided_doc);
7658
0
7659
0
  if (_error) { return _error; }
7660
0
7661
0
  return provided_doc.root();
7662
0
}
7663
7664
0
simdjson_inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const char *buf, size_t len, bool realloc_if_needed) & noexcept {
7665
0
  return parse_into_document(provided_doc, reinterpret_cast<const uint8_t *>(buf), len, realloc_if_needed);
7666
0
}
7667
0
simdjson_inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const std::string &s) & noexcept {
7668
0
  return parse_into_document(provided_doc, s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
7669
0
}
7670
0
simdjson_inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const padded_string &s) & noexcept {
7671
0
  return parse_into_document(provided_doc, s.data(), s.length(), false);
7672
0
}
7673
7674
7675
0
inline simdjson_result<element> parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) & noexcept {
7676
0
  return parse_into_document(doc, buf, len, realloc_if_needed);
7677
0
}
7678
7679
0
simdjson_inline simdjson_result<element> parser::parse(const char *buf, size_t len, bool realloc_if_needed) & noexcept {
7680
0
  return parse(reinterpret_cast<const uint8_t *>(buf), len, realloc_if_needed);
7681
0
}
7682
0
simdjson_inline simdjson_result<element> parser::parse(const std::string &s) & noexcept {
7683
0
  return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
7684
0
}
7685
0
simdjson_inline simdjson_result<element> parser::parse(const padded_string &s) & noexcept {
7686
0
  return parse(s.data(), s.length(), false);
7687
0
}
7688
0
simdjson_inline simdjson_result<element> parser::parse(const padded_string_view &v) & noexcept {
7689
0
  return parse(v.data(), v.length(), false);
7690
0
}
7691
7692
0
inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
7693
0
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
7694
0
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
7695
0
    buf += 3;
7696
0
    len -= 3;
7697
0
  }
7698
0
  return document_stream(*this, buf, len, batch_size);
7699
0
}
7700
0
inline simdjson_result<document_stream> parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept {
7701
0
  return parse_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size);
7702
0
}
7703
0
inline simdjson_result<document_stream> parser::parse_many(const std::string &s, size_t batch_size) noexcept {
7704
0
  return parse_many(s.data(), s.length(), batch_size);
7705
0
}
7706
0
inline simdjson_result<document_stream> parser::parse_many(const padded_string &s, size_t batch_size) noexcept {
7707
0
  return parse_many(s.data(), s.length(), batch_size);
7708
0
}
7709
7710
0
simdjson_inline size_t parser::capacity() const noexcept {
7711
0
  return implementation ? implementation->capacity() : 0;
7712
0
}
7713
0
simdjson_inline size_t parser::max_capacity() const noexcept {
7714
0
  return _max_capacity;
7715
0
}
7716
0
simdjson_inline size_t parser::max_depth() const noexcept {
7717
0
  return implementation ? implementation->max_depth() : DEFAULT_MAX_DEPTH;
7718
0
}
7719
7720
simdjson_warn_unused
7721
0
inline error_code parser::allocate(size_t capacity, size_t max_depth) noexcept {
7722
0
  //
7723
0
  // Reallocate implementation if needed
7724
0
  //
7725
0
  error_code err;
7726
0
  if (implementation) {
7727
0
    err = implementation->allocate(capacity, max_depth);
7728
0
  } else {
7729
0
    err = simdjson::get_active_implementation()->create_dom_parser_implementation(capacity, max_depth, implementation);
7730
0
  }
7731
0
  if (err) { return err; }
7732
0
  return SUCCESS;
7733
0
}
7734
7735
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
7736
simdjson_warn_unused
7737
0
inline bool parser::allocate_capacity(size_t capacity, size_t max_depth) noexcept {
7738
0
  return !allocate(capacity, max_depth);
7739
0
}
7740
#endif // SIMDJSON_DISABLE_DEPRECATED_API
7741
7742
0
inline error_code parser::ensure_capacity(size_t desired_capacity) noexcept {
7743
0
  return ensure_capacity(doc, desired_capacity);
7744
0
}
7745
7746
7747
0
inline error_code parser::ensure_capacity(document& target_document, size_t desired_capacity) noexcept {
7748
0
  // 1. It is wasteful to allocate a document and a parser for documents spanning less than MINIMAL_DOCUMENT_CAPACITY bytes.
7749
0
  // 2. If we allow desired_capacity = 0 then it is possible to exit this function with implementation == nullptr.
7750
0
  if(desired_capacity < MINIMAL_DOCUMENT_CAPACITY) { desired_capacity = MINIMAL_DOCUMENT_CAPACITY; }
7751
0
  // If we don't have enough capacity, (try to) automatically bump it.
7752
0
  // If the document needs allocation, do it too.
7753
0
  // Both in one if statement to minimize unlikely branching.
7754
0
  //
7755
0
  // Note: we must make sure that this function is called if capacity() == 0. We do so because we
7756
0
  // ensure that desired_capacity > 0.
7757
0
  if (simdjson_unlikely(capacity() < desired_capacity || target_document.capacity() < desired_capacity)) {
7758
0
    if (desired_capacity > max_capacity()) {
7759
0
      return error = CAPACITY;
7760
0
    }
7761
0
    error_code err1 = target_document.capacity() < desired_capacity ? target_document.allocate(desired_capacity) : SUCCESS;
7762
0
    error_code err2 = capacity() < desired_capacity ? allocate(desired_capacity, max_depth()) : SUCCESS;
7763
0
    if(err1 != SUCCESS) { return error = err1; }
7764
0
    if(err2 != SUCCESS) { return error = err2; }
7765
0
  }
7766
0
  return SUCCESS;
7767
0
}
7768
7769
0
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
7770
0
  if(max_capacity > MINIMAL_DOCUMENT_CAPACITY) {
7771
0
    _max_capacity = max_capacity;
7772
0
  } else {
7773
0
    _max_capacity = MINIMAL_DOCUMENT_CAPACITY;
7774
0
  }
7775
0
}
7776
7777
} // namespace dom
7778
} // namespace simdjson
7779
7780
#endif // SIMDJSON_PARSER_INL_H
7781
/* end file simdjson/dom/parser-inl.h */
7782
/* skipped duplicate #include "simdjson/error-inl.h" */
7783
/* skipped duplicate #include "simdjson/internal/dom_parser_implementation.h" */
7784
7785
namespace simdjson {
7786
namespace dom {
7787
7788
#ifdef SIMDJSON_THREADS_ENABLED
7789
7790
0
inline void stage1_worker::finish() {
7791
0
  // After calling "run" someone would call finish() to wait
7792
0
  // for the end of the processing.
7793
0
  // This function will wait until either the thread has done
7794
0
  // the processing or, else, the destructor has been called.
7795
0
  std::unique_lock<std::mutex> lock(locking_mutex);
7796
0
  cond_var.wait(lock, [this]{return has_work == false;});
7797
0
}
7798
7799
inline stage1_worker::~stage1_worker() {
7800
  // The thread may never outlive the stage1_worker instance
7801
  // and will always be stopped/joined before the stage1_worker
7802
  // instance is gone.
7803
  stop_thread();
7804
}
7805
7806
0
inline void stage1_worker::start_thread() {
7807
0
  std::unique_lock<std::mutex> lock(locking_mutex);
7808
0
  if(thread.joinable()) {
7809
0
    return; // This should never happen but we never want to create more than one thread.
7810
0
  }
7811
0
  thread = std::thread([this]{
7812
0
      while(true) {
7813
0
        std::unique_lock<std::mutex> thread_lock(locking_mutex);
7814
0
        // We wait for either "run" or "stop_thread" to be called.
7815
0
        cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
7816
0
        // If, for some reason, the stop_thread() method was called (i.e., the
7817
0
        // destructor of stage1_worker is called, then we want to immediately destroy
7818
0
        // the thread (and not do any more processing).
7819
0
        if(!can_work) {
7820
0
          break;
7821
0
        }
7822
0
        this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
7823
0
              this->_next_batch_start);
7824
0
        this->has_work = false;
7825
0
        // The condition variable call should be moved after thread_lock.unlock() for performance
7826
0
        // reasons but thread sanitizers may report it as a data race if we do.
7827
0
        // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
7828
0
        cond_var.notify_one(); // will notify "finish"
7829
0
        thread_lock.unlock();
7830
0
      }
7831
0
    }
7832
0
  );
7833
0
}
7834
7835
7836
0
inline void stage1_worker::stop_thread() {
7837
0
  std::unique_lock<std::mutex> lock(locking_mutex);
7838
0
  // We have to make sure that all locks can be released.
7839
0
  can_work = false;
7840
0
  has_work = false;
7841
0
  cond_var.notify_all();
7842
0
  lock.unlock();
7843
0
  if(thread.joinable()) {
7844
0
    thread.join();
7845
0
  }
7846
0
}
7847
7848
0
inline void stage1_worker::run(document_stream * ds, dom::parser * stage1, size_t next_batch_start) {
7849
0
  std::unique_lock<std::mutex> lock(locking_mutex);
7850
0
  owner = ds;
7851
0
  _next_batch_start = next_batch_start;
7852
0
  stage1_thread_parser = stage1;
7853
0
  has_work = true;
7854
0
  // The condition variable call should be moved after thread_lock.unlock() for performance
7855
0
  // reasons but thread sanitizers may report it as a data race if we do.
7856
0
  // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
7857
0
  cond_var.notify_one(); // will notify the thread lock that we have work
7858
0
  lock.unlock();
7859
0
}
7860
#endif
7861
7862
simdjson_inline document_stream::document_stream(
7863
  dom::parser &_parser,
7864
  const uint8_t *_buf,
7865
  size_t _len,
7866
  size_t _batch_size
7867
) noexcept
7868
  : parser{&_parser},
7869
    buf{_buf},
7870
    len{_len},
7871
    batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
7872
    error{SUCCESS}
7873
#ifdef SIMDJSON_THREADS_ENABLED
7874
    , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
7875
#endif
7876
{
7877
#ifdef SIMDJSON_THREADS_ENABLED
7878
  if(worker.get() == nullptr) {
7879
    error = MEMALLOC;
7880
  }
7881
#endif
7882
}
7883
7884
simdjson_inline document_stream::document_stream() noexcept
7885
  : parser{nullptr},
7886
    buf{nullptr},
7887
    len{0},
7888
    batch_size{0},
7889
    error{UNINITIALIZED}
7890
#ifdef SIMDJSON_THREADS_ENABLED
7891
    , use_thread(false)
7892
#endif
7893
{
7894
}
7895
7896
simdjson_inline document_stream::~document_stream() noexcept {
7897
#ifdef SIMDJSON_THREADS_ENABLED
7898
  worker.reset();
7899
#endif
7900
}
7901
7902
simdjson_inline document_stream::iterator::iterator() noexcept
7903
  : stream{nullptr}, finished{true} {
7904
}
7905
7906
0
simdjson_inline document_stream::iterator document_stream::begin() noexcept {
7907
0
  start();
7908
0
  // If there are no documents, we're finished.
7909
0
  return iterator(this, error == EMPTY);
7910
0
}
7911
7912
0
simdjson_inline document_stream::iterator document_stream::end() noexcept {
7913
0
  return iterator(this, true);
7914
0
}
7915
7916
simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
7917
  : stream{_stream}, finished{is_end} {
7918
}
7919
7920
0
simdjson_inline document_stream::iterator::reference document_stream::iterator::operator*() noexcept {
7921
0
  // Note that in case of error, we do not yet mark
7922
0
  // the iterator as "finished": this detection is done
7923
0
  // in the operator++ function since it is possible
7924
0
  // to call operator++ repeatedly while omitting
7925
0
  // calls to operator*.
7926
0
  if (stream->error) { return stream->error; }
7927
0
  return stream->parser->doc.root();
7928
0
}
7929
7930
0
simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
7931
0
  // If there is an error, then we want the iterator
7932
0
  // to be finished, no matter what. (E.g., we do not
7933
0
  // keep generating documents with errors, or go beyond
7934
0
  // a document with errors.)
7935
0
  //
7936
0
  // Users do not have to call "operator*()" when they use operator++,
7937
0
  // so we need to end the stream in the operator++ function.
7938
0
  //
7939
0
  // Note that setting finished = true is essential otherwise
7940
0
  // we would enter an infinite loop.
7941
0
  if (stream->error) { finished = true; }
7942
0
  // Note that stream->error() is guarded against error conditions
7943
0
  // (it will immediately return if stream->error casts to false).
7944
0
  // In effect, this next function does nothing when (stream->error)
7945
0
  // is true (hence the risk of an infinite loop).
7946
0
  stream->next();
7947
0
  // If that was the last document, we're finished.
7948
0
  // It is the only type of error we do not want to appear
7949
0
  // in operator*.
7950
0
  if (stream->error == EMPTY) { finished = true; }
7951
0
  // If we had any other kind of error (not EMPTY) then we want
7952
0
  // to pass it along to the operator* and we cannot mark the result
7953
0
  // as "finished" just yet.
7954
0
  return *this;
7955
0
}
7956
7957
0
simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
7958
0
  return finished != other.finished;
7959
0
}
7960
7961
0
inline void document_stream::start() noexcept {
7962
0
  if (error) { return; }
7963
0
  error = parser->ensure_capacity(batch_size);
7964
0
  if (error) { return; }
7965
0
  // Always run the first stage 1 parse immediately
7966
0
  batch_start = 0;
7967
0
  error = run_stage1(*parser, batch_start);
7968
0
  while(error == EMPTY) {
7969
0
    // In exceptional cases, we may start with an empty block
7970
0
    batch_start = next_batch_start();
7971
0
    if (batch_start >= len) { return; }
7972
0
    error = run_stage1(*parser, batch_start);
7973
0
  }
7974
0
  if (error) { return; }
7975
0
#ifdef SIMDJSON_THREADS_ENABLED
7976
0
  if (use_thread && next_batch_start() < len) {
7977
0
    // Kick off the first thread if needed
7978
0
    error = stage1_thread_parser.ensure_capacity(batch_size);
7979
0
    if (error) { return; }
7980
0
    worker->start_thread();
7981
0
    start_stage1_thread();
7982
0
    if (error) { return; }
7983
0
  }
7984
0
#endif // SIMDJSON_THREADS_ENABLED
7985
0
  next();
7986
0
}
7987
7988
0
simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
7989
0
  return stream->doc_index;
7990
0
}
7991
7992
0
simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
7993
0
  const char* start = reinterpret_cast<const char*>(stream->buf) + current_index();
7994
0
  bool object_or_array = ((*start == '[') || (*start == '{'));
7995
0
  if(object_or_array) {
7996
0
    size_t next_doc_index = stream->batch_start + stream->parser->implementation->structural_indexes[stream->parser->implementation->next_structural_index - 1];
7997
0
    return std::string_view(start, next_doc_index - current_index() + 1);
7998
0
  } else {
7999
0
    size_t next_doc_index = stream->batch_start + stream->parser->implementation->structural_indexes[stream->parser->implementation->next_structural_index];
8000
0
    return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), next_doc_index - current_index() - 1);
8001
0
  }
8002
0
}
8003
8004
8005
0
inline void document_stream::next() noexcept {
8006
0
  // We always exit at once, once in an error condition.
8007
0
  if (error) { return; }
8008
0
8009
0
  // Load the next document from the batch
8010
0
  doc_index = batch_start + parser->implementation->structural_indexes[parser->implementation->next_structural_index];
8011
0
  error = parser->implementation->stage2_next(parser->doc);
8012
0
  // If that was the last document in the batch, load another batch (if available)
8013
0
  while (error == EMPTY) {
8014
0
    batch_start = next_batch_start();
8015
0
    if (batch_start >= len) { break; }
8016
0
8017
0
#ifdef SIMDJSON_THREADS_ENABLED
8018
0
    if(use_thread) {
8019
0
      load_from_stage1_thread();
8020
0
    } else {
8021
0
      error = run_stage1(*parser, batch_start);
8022
0
    }
8023
0
#else
8024
0
    error = run_stage1(*parser, batch_start);
8025
0
#endif
8026
0
    if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
8027
0
    // Run stage 2 on the first document in the batch
8028
0
    doc_index = batch_start + parser->implementation->structural_indexes[parser->implementation->next_structural_index];
8029
0
    error = parser->implementation->stage2_next(parser->doc);
8030
0
  }
8031
0
}
8032
0
inline size_t document_stream::size_in_bytes() const noexcept {
8033
0
  return len;
8034
0
}
8035
8036
0
inline size_t document_stream::truncated_bytes() const noexcept {
8037
0
  if(error == CAPACITY) { return len - batch_start; }
8038
0
  return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
8039
0
}
8040
8041
0
inline size_t document_stream::next_batch_start() const noexcept {
8042
0
  return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
8043
0
}
8044
8045
0
inline error_code document_stream::run_stage1(dom::parser &p, size_t _batch_start) noexcept {
8046
0
  size_t remaining = len - _batch_start;
8047
0
  if (remaining <= batch_size) {
8048
0
    return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
8049
0
  } else {
8050
0
    return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
8051
0
  }
8052
0
}
8053
8054
#ifdef SIMDJSON_THREADS_ENABLED
8055
8056
0
inline void document_stream::load_from_stage1_thread() noexcept {
8057
0
  worker->finish();
8058
0
  // Swap to the parser that was loaded up in the thread. Make sure the parser has
8059
0
  // enough memory to swap to, as well.
8060
0
  std::swap(*parser, stage1_thread_parser);
8061
0
  error = stage1_thread_error;
8062
0
  if (error) { return; }
8063
0
8064
0
  // If there's anything left, start the stage 1 thread!
8065
0
  if (next_batch_start() < len) {
8066
0
    start_stage1_thread();
8067
0
  }
8068
0
}
8069
8070
0
inline void document_stream::start_stage1_thread() noexcept {
8071
0
  // we call the thread on a lambda that will update
8072
0
  // this->stage1_thread_error
8073
0
  // there is only one thread that may write to this value
8074
0
  // TODO this is NOT exception-safe.
8075
0
  this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
8076
0
  size_t _next_batch_start = this->next_batch_start();
8077
0
8078
0
  worker->run(this, & this->stage1_thread_parser, _next_batch_start);
8079
0
}
8080
8081
#endif // SIMDJSON_THREADS_ENABLED
8082
8083
} // namespace dom
8084
8085
simdjson_inline simdjson_result<dom::document_stream>::simdjson_result() noexcept
8086
  : simdjson_result_base() {
8087
}
8088
simdjson_inline simdjson_result<dom::document_stream>::simdjson_result(error_code error) noexcept
8089
  : simdjson_result_base(error) {
8090
}
8091
simdjson_inline simdjson_result<dom::document_stream>::simdjson_result(dom::document_stream &&value) noexcept
8092
  : simdjson_result_base(std::forward<dom::document_stream>(value)) {
8093
}
8094
8095
#if SIMDJSON_EXCEPTIONS
8096
simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::begin() noexcept(false) {
8097
  if (error()) { throw simdjson_error(error()); }
8098
  return first.begin();
8099
}
8100
simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::end() noexcept(false) {
8101
  if (error()) { throw simdjson_error(error()); }
8102
  return first.end();
8103
}
8104
#else // SIMDJSON_EXCEPTIONS
8105
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
8106
0
simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::begin() noexcept {
8107
0
  first.error = error();
8108
0
  return first.begin();
8109
0
}
8110
0
simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::end() noexcept {
8111
0
  first.error = error();
8112
0
  return first.end();
8113
0
}
8114
#endif // SIMDJSON_DISABLE_DEPRECATED_API
8115
#endif // SIMDJSON_EXCEPTIONS
8116
8117
} // namespace simdjson
8118
#endif // SIMDJSON_DOCUMENT_STREAM_INL_H
8119
/* end file simdjson/dom/document_stream-inl.h */
8120
/* including simdjson/dom/document-inl.h: #include "simdjson/dom/document-inl.h" */
8121
/* begin file simdjson/dom/document-inl.h */
8122
#ifndef SIMDJSON_DOCUMENT_INL_H
8123
#define SIMDJSON_DOCUMENT_INL_H
8124
8125
// Inline implementations go in here.
8126
8127
/* skipped duplicate #include "simdjson/dom/base.h" */
8128
/* skipped duplicate #include "simdjson/dom/document.h" */
8129
/* skipped duplicate #include "simdjson/dom/element-inl.h" */
8130
/* skipped duplicate #include "simdjson/internal/tape_ref-inl.h" */
8131
/* including simdjson/internal/jsonformatutils.h: #include "simdjson/internal/jsonformatutils.h" */
8132
/* begin file simdjson/internal/jsonformatutils.h */
8133
#ifndef SIMDJSON_INTERNAL_JSONFORMATUTILS_H
8134
#define SIMDJSON_INTERNAL_JSONFORMATUTILS_H
8135
8136
/* skipped duplicate #include "simdjson/base.h" */
8137
#include <iomanip>
8138
#include <ostream>
8139
#include <sstream>
8140
8141
namespace simdjson {
8142
namespace internal {
8143
8144
inline std::ostream& operator<<(std::ostream& out, const escape_json_string &str);
8145
8146
class escape_json_string {
8147
public:
8148
0
  escape_json_string(std::string_view _str) noexcept : str{_str} {}
8149
0
  operator std::string() const noexcept { std::stringstream s; s << *this; return s.str(); }
8150
private:
8151
  std::string_view str;
8152
  friend std::ostream& operator<<(std::ostream& out, const escape_json_string &unescaped);
8153
};
8154
8155
0
inline std::ostream& operator<<(std::ostream& out, const escape_json_string &unescaped) {
8156
0
  for (size_t i=0; i<unescaped.str.length(); i++) {
8157
0
    switch (unescaped.str[i]) {
8158
0
    case '\b':
8159
0
      out << "\\b";
8160
0
      break;
8161
0
    case '\f':
8162
0
      out << "\\f";
8163
0
      break;
8164
0
    case '\n':
8165
0
      out << "\\n";
8166
0
      break;
8167
0
    case '\r':
8168
0
      out << "\\r";
8169
0
      break;
8170
0
    case '\"':
8171
0
      out << "\\\"";
8172
0
      break;
8173
0
    case '\t':
8174
0
      out << "\\t";
8175
0
      break;
8176
0
    case '\\':
8177
0
      out << "\\\\";
8178
0
      break;
8179
0
    default:
8180
0
      if (static_cast<unsigned char>(unescaped.str[i]) <= 0x1F) {
8181
0
        // TODO can this be done once at the beginning, or will it mess up << char?
8182
0
        std::ios::fmtflags f(out.flags());
8183
0
        out << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(unescaped.str[i]);
8184
0
        out.flags(f);
8185
0
      } else {
8186
0
        out << unescaped.str[i];
8187
0
      }
8188
0
    }
8189
0
  }
8190
0
  return out;
8191
0
}
8192
8193
} // namespace internal
8194
} // namespace simdjson
8195
8196
#endif // SIMDJSON_INTERNAL_JSONFORMATUTILS_H
8197
/* end file simdjson/internal/jsonformatutils.h */
8198
8199
#include <cstring>
8200
8201
namespace simdjson {
8202
namespace dom {
8203
8204
//
8205
// document inline implementation
8206
//
8207
0
inline element document::root() const noexcept {
8208
0
  return element(internal::tape_ref(this, 1));
8209
0
}
8210
simdjson_warn_unused
8211
0
inline size_t document::capacity() const noexcept {
8212
0
  return allocated_capacity;
8213
0
}
8214
8215
simdjson_warn_unused
8216
0
inline error_code document::allocate(size_t capacity) noexcept {
8217
0
  if (capacity == 0) {
8218
0
    string_buf.reset();
8219
0
    tape.reset();
8220
0
    allocated_capacity = 0;
8221
0
    return SUCCESS;
8222
0
  }
8223
0
8224
0
  // a pathological input like "[[[[..." would generate capacity tape elements, so
8225
0
  // need a capacity of at least capacity + 1, but it is also possible to do
8226
0
  // worse with "[7,7,7,7,6,7,7,7,6,7,7,6,[7,7,7,7,6,7,7,7,6,7,7,6,7,7,7,7,7,7,6"
8227
0
  //where capacity + 1 tape elements are
8228
0
  // generated, see issue https://github.com/simdjson/simdjson/issues/345
8229
0
  size_t tape_capacity = SIMDJSON_ROUNDUP_N(capacity + 3, 64);
8230
0
  // a document with only zero-length strings... could have capacity/3 string
8231
0
  // and we would need capacity/3 * 5 bytes on the string buffer
8232
0
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * capacity / 3 + SIMDJSON_PADDING, 64);
8233
0
  string_buf.reset( new (std::nothrow) uint8_t[string_capacity]);
8234
0
  tape.reset(new (std::nothrow) uint64_t[tape_capacity]);
8235
0
  if(!(string_buf && tape)) {
8236
0
    allocated_capacity = 0;
8237
0
    string_buf.reset();
8238
0
    tape.reset();
8239
0
    return MEMALLOC;
8240
0
  }
8241
0
  // Technically the allocated_capacity might be larger than capacity
8242
0
  // so the next line is pessimistic.
8243
0
  allocated_capacity = capacity;
8244
0
  return SUCCESS;
8245
0
}
8246
8247
0
inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
8248
0
  uint32_t string_length;
8249
0
  size_t tape_idx = 0;
8250
0
  uint64_t tape_val = tape[tape_idx];
8251
0
  uint8_t type = uint8_t(tape_val >> 56);
8252
0
  os << tape_idx << " : " << type;
8253
0
  tape_idx++;
8254
0
  size_t how_many = 0;
8255
0
  if (type == 'r') {
8256
0
    how_many = size_t(tape_val & internal::JSON_VALUE_MASK);
8257
0
  } else {
8258
0
    // Error: no starting root node?
8259
0
    return false;
8260
0
  }
8261
0
  os << "\t// pointing to " << how_many << " (right after last node)\n";
8262
0
  uint64_t payload;
8263
0
  for (; tape_idx < how_many; tape_idx++) {
8264
0
    os << tape_idx << " : ";
8265
0
    tape_val = tape[tape_idx];
8266
0
    payload = tape_val & internal::JSON_VALUE_MASK;
8267
0
    type = uint8_t(tape_val >> 56);
8268
0
    switch (type) {
8269
0
    case '"': // we have a string
8270
0
      os << "string \"";
8271
0
      std::memcpy(&string_length, string_buf.get() + payload, sizeof(uint32_t));
8272
0
      os << internal::escape_json_string(std::string_view(
8273
0
        reinterpret_cast<const char *>(string_buf.get() + payload + sizeof(uint32_t)),
8274
0
        string_length
8275
0
      ));
8276
0
      os << '"';
8277
0
      os << '\n';
8278
0
      break;
8279
0
    case 'l': // we have a long int
8280
0
      if (tape_idx + 1 >= how_many) {
8281
0
        return false;
8282
0
      }
8283
0
      os << "integer " << static_cast<int64_t>(tape[++tape_idx]) << "\n";
8284
0
      break;
8285
0
    case 'u': // we have a long uint
8286
0
      if (tape_idx + 1 >= how_many) {
8287
0
        return false;
8288
0
      }
8289
0
      os << "unsigned integer " << tape[++tape_idx] << "\n";
8290
0
      break;
8291
0
    case 'd': // we have a double
8292
0
      os << "float ";
8293
0
      if (tape_idx + 1 >= how_many) {
8294
0
        return false;
8295
0
      }
8296
0
      double answer;
8297
0
      std::memcpy(&answer, &tape[++tape_idx], sizeof(answer));
8298
0
      os << answer << '\n';
8299
0
      break;
8300
0
    case 'n': // we have a null
8301
0
      os << "null\n";
8302
0
      break;
8303
0
    case 't': // we have a true
8304
0
      os << "true\n";
8305
0
      break;
8306
0
    case 'f': // we have a false
8307
0
      os << "false\n";
8308
0
      break;
8309
0
    case '{': // we have an object
8310
0
      os << "{\t// pointing to next tape location " << uint32_t(payload)
8311
0
         << " (first node after the scope), "
8312
0
         << " saturated count "
8313
0
         << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
8314
0
      break;    case '}': // we end an object
8315
0
      os << "}\t// pointing to previous tape location " << uint32_t(payload)
8316
0
         << " (start of the scope)\n";
8317
0
      break;
8318
0
    case '[': // we start an array
8319
0
      os << "[\t// pointing to next tape location " << uint32_t(payload)
8320
0
         << " (first node after the scope), "
8321
0
         << " saturated count "
8322
0
         << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
8323
0
      break;
8324
0
    case ']': // we end an array
8325
0
      os << "]\t// pointing to previous tape location " << uint32_t(payload)
8326
0
         << " (start of the scope)\n";
8327
0
      break;
8328
0
    case 'r': // we start and end with the root node
8329
0
      // should we be hitting the root node?
8330
0
      return false;
8331
0
    default:
8332
0
      return false;
8333
0
    }
8334
0
  }
8335
0
  tape_val = tape[tape_idx];
8336
0
  payload = tape_val & internal::JSON_VALUE_MASK;
8337
0
  type = uint8_t(tape_val >> 56);
8338
0
  os << tape_idx << " : " << type << "\t// pointing to " << payload
8339
0
     << " (start root)\n";
8340
0
  return true;
8341
0
}
8342
8343
} // namespace dom
8344
} // namespace simdjson
8345
8346
#endif // SIMDJSON_DOCUMENT_INL_H
8347
/* end file simdjson/dom/document-inl.h */
8348
/* skipped duplicate #include "simdjson/dom/element-inl.h" */
8349
/* skipped duplicate #include "simdjson/dom/object-inl.h" */
8350
/* skipped duplicate #include "simdjson/dom/parser-inl.h" */
8351
/* skipped duplicate #include "simdjson/internal/tape_ref-inl.h" */
8352
/* including simdjson/dom/serialization-inl.h: #include "simdjson/dom/serialization-inl.h" */
8353
/* begin file simdjson/dom/serialization-inl.h */
8354
8355
#ifndef SIMDJSON_SERIALIZATION_INL_H
8356
#define SIMDJSON_SERIALIZATION_INL_H
8357
8358
/* skipped duplicate #include "simdjson/dom/base.h" */
8359
/* skipped duplicate #include "simdjson/dom/serialization.h" */
8360
/* skipped duplicate #include "simdjson/dom/parser.h" */
8361
/* skipped duplicate #include "simdjson/internal/tape_type.h" */
8362
8363
/* skipped duplicate #include "simdjson/dom/array-inl.h" */
8364
/* skipped duplicate #include "simdjson/dom/object-inl.h" */
8365
/* skipped duplicate #include "simdjson/internal/tape_ref-inl.h" */
8366
8367
#include <cstring>
8368
8369
namespace simdjson {
8370
namespace dom {
8371
0
inline bool parser::print_json(std::ostream &os) const noexcept {
8372
0
  if (!valid) { return false; }
8373
0
  simdjson::internal::string_builder<> sb;
8374
0
  sb.append(doc.root());
8375
0
  std::string_view answer = sb.str();
8376
0
  os << answer;
8377
0
  return true;
8378
0
}
8379
8380
0
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
8381
0
    simdjson::internal::string_builder<> sb;
8382
0
    sb.append(value);
8383
0
    return (out << sb.str());
8384
0
}
8385
#if SIMDJSON_EXCEPTIONS
8386
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
8387
    if (x.error()) { throw simdjson::simdjson_error(x.error()); }
8388
    return (out << x.value());
8389
}
8390
#endif
8391
0
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value)  {
8392
0
    simdjson::internal::string_builder<> sb;
8393
0
    sb.append(value);
8394
0
    return (out << sb.str());
8395
0
}
8396
#if SIMDJSON_EXCEPTIONS
8397
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
8398
    if (x.error()) { throw simdjson::simdjson_error(x.error()); }
8399
    return (out << x.value());
8400
}
8401
#endif
8402
0
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value)   {
8403
0
    simdjson::internal::string_builder<> sb;
8404
0
    sb.append(value);
8405
0
    return (out << sb.str());
8406
0
}
8407
#if SIMDJSON_EXCEPTIONS
8408
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::dom::object> x) {
8409
    if (x.error()) { throw  simdjson::simdjson_error(x.error()); }
8410
    return (out << x.value());
8411
}
8412
#endif
8413
8414
} // namespace dom
8415
8416
/***
8417
 * Number utility functions
8418
 **/
8419
namespace {
8420
/**@private
8421
 * Escape sequence like \b or \u0001
8422
 * We expect that most compilers will use 8 bytes for this data structure.
8423
 **/
8424
struct escape_sequence {
8425
    uint8_t length;
8426
    const char string[7]; // technically, we only ever need 6 characters, we pad to 8
8427
};
8428
/**@private
8429
 * This converts a signed integer into a character sequence.
8430
 * The caller is responsible for providing enough memory (at least
8431
 * 20 characters.)
8432
 * Though various runtime libraries provide itoa functions,
8433
 * it is not part of the C++ standard. The C++17 standard
8434
 * adds the to_chars functions which would do as well, but
8435
 * we want to support C++11.
8436
 */
8437
0
static char *fast_itoa(char *output, int64_t value) noexcept {
8438
0
  // This is a standard implementation of itoa.
8439
0
  char buffer[20];
8440
0
  uint64_t value_positive;
8441
0
  // In general, negating a signed integer is unsafe.
8442
0
  if(value < 0) {
8443
0
    *output++ = '-';
8444
0
    // Doing value_positive = -value; while avoiding
8445
0
    // undefined behavior warnings.
8446
0
    // It assumes two complement's which is universal at this
8447
0
    // point in time.
8448
0
    std::memcpy(&value_positive, &value, sizeof(value));
8449
0
    value_positive = (~value_positive) + 1; // this is a negation
8450
0
  } else {
8451
0
    value_positive = value;
8452
0
  }
8453
0
  // We work solely with value_positive. It *might* be easier
8454
0
  // for an optimizing compiler to deal with an unsigned variable
8455
0
  // as far as performance goes.
8456
0
  const char *const end_buffer = buffer + 20;
8457
0
  char *write_pointer = buffer + 19;
8458
0
  // A faster approach is possible if we expect large integers:
8459
0
  // unroll the loop (work in 100s, 1000s) and use some kind of
8460
0
  // memoization.
8461
0
  while(value_positive >= 10) {
8462
0
    *write_pointer-- = char('0' + (value_positive % 10));
8463
0
    value_positive /= 10;
8464
0
  }
8465
0
  *write_pointer = char('0' + value_positive);
8466
0
  size_t len = end_buffer - write_pointer;
8467
0
  std::memcpy(output, write_pointer, len);
8468
0
  return output + len;
8469
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::(anonymous namespace)::fast_itoa(char*, long)
Unexecuted instantiation: node_modules.cc:simdjson::(anonymous namespace)::fast_itoa(char*, long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::(anonymous namespace)::fast_itoa(char*, long)
8470
/**@private
8471
 * This converts an unsigned integer into a character sequence.
8472
 * The caller is responsible for providing enough memory (at least
8473
 * 19 characters.)
8474
 * Though various runtime libraries provide itoa functions,
8475
 * it is not part of the C++ standard. The C++17 standard
8476
 * adds the to_chars functions which would do as well, but
8477
 * we want to support C++11.
8478
 */
8479
0
static char *fast_itoa(char *output, uint64_t value) noexcept {
8480
0
  // This is a standard implementation of itoa.
8481
0
  char buffer[20];
8482
0
  const char *const end_buffer = buffer + 20;
8483
0
  char *write_pointer = buffer + 19;
8484
0
  // A faster approach is possible if we expect large integers:
8485
0
  // unroll the loop (work in 100s, 1000s) and use some kind of
8486
0
  // memoization.
8487
0
  while(value >= 10) {
8488
0
    *write_pointer-- = char('0' + (value % 10));
8489
0
    value /= 10;
8490
0
  };
8491
0
  *write_pointer = char('0' + value);
8492
0
  size_t len = end_buffer - write_pointer;
8493
0
  std::memcpy(output, write_pointer, len);
8494
0
  return output + len;
8495
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::(anonymous namespace)::fast_itoa(char*, unsigned long)
Unexecuted instantiation: node_modules.cc:simdjson::(anonymous namespace)::fast_itoa(char*, unsigned long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::(anonymous namespace)::fast_itoa(char*, unsigned long)
8496
8497
8498
} // anonymous namespace
8499
namespace internal {
8500
8501
/***
8502
 * Minifier/formatter code.
8503
 **/
8504
8505
template<class formatter>
8506
0
simdjson_inline void base_formatter<formatter>::number(uint64_t x) {
8507
0
  char number_buffer[24];
8508
0
  char *newp = fast_itoa(number_buffer, x);
8509
0
  buffer.insert(buffer.end(), number_buffer, newp);
8510
0
}
8511
8512
template<class formatter>
8513
0
simdjson_inline void base_formatter<formatter>::number(int64_t x) {
8514
0
  char number_buffer[24];
8515
0
  char *newp = fast_itoa(number_buffer, x);
8516
0
  buffer.insert(buffer.end(), number_buffer, newp);
8517
0
}
8518
8519
template<class formatter>
8520
0
simdjson_inline void base_formatter<formatter>::number(double x) {
8521
0
  char number_buffer[24];
8522
0
  // Currently, passing the nullptr to the second argument is
8523
0
  // safe because our implementation does not check the second
8524
0
  // argument.
8525
0
  char *newp = internal::to_chars(number_buffer, nullptr, x);
8526
0
  buffer.insert(buffer.end(), number_buffer, newp);
8527
0
}
8528
8529
template<class formatter>
8530
0
simdjson_inline void base_formatter<formatter>::start_array() { one_char('['); }
8531
8532
8533
template<class formatter>
8534
0
simdjson_inline void base_formatter<formatter>::end_array() { one_char(']'); }
8535
8536
template<class formatter>
8537
0
simdjson_inline void base_formatter<formatter>::start_object() { one_char('{'); }
8538
8539
template<class formatter>
8540
0
simdjson_inline void base_formatter<formatter>::end_object() { one_char('}'); }
8541
8542
template<class formatter>
8543
0
simdjson_inline void base_formatter<formatter>::comma() { one_char(','); }
8544
8545
template<class formatter>
8546
0
simdjson_inline void base_formatter<formatter>::true_atom() {
8547
0
  const char * s = "true";
8548
0
  buffer.insert(buffer.end(), s, s + 4);
8549
0
}
8550
8551
template<class formatter>
8552
0
simdjson_inline void base_formatter<formatter>::false_atom() {
8553
0
  const char * s = "false";
8554
0
  buffer.insert(buffer.end(), s, s + 5);
8555
0
}
8556
8557
template<class formatter>
8558
0
simdjson_inline void base_formatter<formatter>::null_atom() {
8559
0
  const char * s = "null";
8560
0
  buffer.insert(buffer.end(), s, s + 4);
8561
0
}
8562
8563
template<class formatter>
8564
0
simdjson_inline void base_formatter<formatter>::one_char(char c) { buffer.push_back(c); }
Unexecuted instantiation: simdjson::internal::base_formatter<simdjson::internal::mini_formatter>::one_char(char)
Unexecuted instantiation: simdjson::internal::base_formatter<simdjson::internal::pretty_formatter>::one_char(char)
8565
8566
template<class formatter>
8567
0
simdjson_inline void base_formatter<formatter>::key(std::string_view unescaped) {
8568
0
  string(unescaped);
8569
0
  one_char(':');
8570
0
}
8571
8572
template<class formatter>
8573
0
simdjson_inline void base_formatter<formatter>::string(std::string_view unescaped) {
8574
0
  one_char('\"');
8575
0
  size_t i = 0;
8576
0
  // Fast path for the case where we have no control character, no ", and no backslash.
8577
0
  // This should include most keys.
8578
0
  //
8579
0
  // We would like to use 'bool' but some compilers take offense to bitwise operation
8580
0
  // with bool types.
8581
0
  constexpr static char needs_escaping[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
8582
0
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
8583
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8584
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
8585
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8586
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8587
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8588
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8589
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8590
0
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
8591
0
  for(;i + 8 <= unescaped.length(); i += 8) {
8592
0
    // Poor's man vectorization. This could get much faster if we used SIMD.
8593
0
    //
8594
0
    // It is not the case that replacing '|' with '||' would be neutral performance-wise.
8595
0
    if(needs_escaping[uint8_t(unescaped[i])] | needs_escaping[uint8_t(unescaped[i+1])]
8596
0
      | needs_escaping[uint8_t(unescaped[i+2])] | needs_escaping[uint8_t(unescaped[i+3])]
8597
0
      | needs_escaping[uint8_t(unescaped[i+4])] | needs_escaping[uint8_t(unescaped[i+5])]
8598
0
      | needs_escaping[uint8_t(unescaped[i+6])] | needs_escaping[uint8_t(unescaped[i+7])]
8599
0
      ) { break; }
8600
0
  }
8601
0
  for(;i < unescaped.length(); i++) {
8602
0
    if(needs_escaping[uint8_t(unescaped[i])]) { break; }
8603
0
  }
8604
0
  // The following is also possible and omits a 256-byte table, but it is slower:
8605
0
  // for (; (i < unescaped.length()) && (uint8_t(unescaped[i]) > 0x1F)
8606
0
  //      && (unescaped[i] != '\"') && (unescaped[i] != '\\'); i++) {}
8607
0
8608
0
  // At least for long strings, the following should be fast. We could
8609
0
  // do better by integrating the checks and the insertion.
8610
0
  buffer.insert(buffer.end(), unescaped.data(), unescaped.data() + i);
8611
0
  // We caught a control character if we enter this loop (slow).
8612
0
  // Note that we are do not restart from the beginning, but rather we continue
8613
0
  // from the point where we encountered something that requires escaping.
8614
0
  for (; i < unescaped.length(); i++) {
8615
0
    switch (unescaped[i]) {
8616
0
    case '\"':
8617
0
      {
8618
0
        const char * s = "\\\"";
8619
0
        buffer.insert(buffer.end(), s, s + 2);
8620
0
      }
8621
0
      break;
8622
0
    case '\\':
8623
0
      {
8624
0
        const char * s = "\\\\";
8625
0
        buffer.insert(buffer.end(), s, s + 2);
8626
0
      }
8627
0
      break;
8628
0
    default:
8629
0
      if (uint8_t(unescaped[i]) <= 0x1F) {
8630
0
        // If packed, this uses 8 * 32 bytes.
8631
0
        // Note that we expect most compilers to embed this code in the data
8632
0
        // section.
8633
0
        constexpr static escape_sequence escaped[32] = {
8634
0
          {6, "\\u0000"}, {6, "\\u0001"}, {6, "\\u0002"}, {6, "\\u0003"},
8635
0
          {6, "\\u0004"}, {6, "\\u0005"}, {6, "\\u0006"}, {6, "\\u0007"},
8636
0
          {2, "\\b"},     {2, "\\t"},     {2, "\\n"},     {6, "\\u000b"},
8637
0
          {2, "\\f"},     {2, "\\r"},     {6, "\\u000e"}, {6, "\\u000f"},
8638
0
          {6, "\\u0010"}, {6, "\\u0011"}, {6, "\\u0012"}, {6, "\\u0013"},
8639
0
          {6, "\\u0014"}, {6, "\\u0015"}, {6, "\\u0016"}, {6, "\\u0017"},
8640
0
          {6, "\\u0018"}, {6, "\\u0019"}, {6, "\\u001a"}, {6, "\\u001b"},
8641
0
          {6, "\\u001c"}, {6, "\\u001d"}, {6, "\\u001e"}, {6, "\\u001f"}};
8642
0
        auto u = escaped[uint8_t(unescaped[i])];
8643
0
        buffer.insert(buffer.end(), u.string, u.string + u.length);
8644
0
      } else {
8645
0
        one_char(unescaped[i]);
8646
0
      }
8647
0
    } // switch
8648
0
  }   // for
8649
0
  one_char('\"');
8650
0
}
8651
8652
8653
template<class formatter>
8654
inline void base_formatter<formatter>::clear() {
8655
  buffer.clear();
8656
}
8657
8658
template<class formatter>
8659
0
simdjson_inline std::string_view base_formatter<formatter>::str() const {
8660
0
  return std::string_view(buffer.data(), buffer.size());
8661
0
}
8662
8663
0
simdjson_inline void mini_formatter::print_newline() {
8664
0
    return;
8665
0
}
8666
8667
0
simdjson_inline void mini_formatter::print_indents(size_t depth) {
8668
0
    (void)depth;
8669
0
    return;
8670
0
}
8671
8672
0
simdjson_inline void mini_formatter::print_space() {
8673
0
    return;
8674
0
}
8675
8676
0
simdjson_inline void pretty_formatter::print_newline() {
8677
0
    one_char('\n');
8678
0
}
8679
8680
0
simdjson_inline void pretty_formatter::print_indents(size_t depth) {
8681
0
    if(this->indent_step <= 0) {
8682
0
        return;
8683
0
    }
8684
0
    for(size_t i = 0; i < this->indent_step * depth; i++) {
8685
0
        one_char(' ');
8686
0
    }
8687
0
}
8688
8689
0
simdjson_inline void pretty_formatter::print_space() {
8690
0
    one_char(' ');
8691
0
}
8692
8693
/***
8694
 * String building code.
8695
 **/
8696
8697
template <class serializer>
8698
0
inline void string_builder<serializer>::append(simdjson::dom::element value) {
8699
0
  // using tape_type = simdjson::internal::tape_type;
8700
0
  size_t depth = 0;
8701
0
  constexpr size_t MAX_DEPTH = 16;
8702
0
  bool is_object[MAX_DEPTH];
8703
0
  is_object[0] = false;
8704
0
  bool after_value = false;
8705
0
8706
0
  internal::tape_ref iter(value.tape);
8707
0
  do {
8708
0
    // print commas after each value
8709
0
    if (after_value) {
8710
0
      format.comma();
8711
0
      format.print_newline();
8712
0
    }
8713
0
8714
0
    format.print_indents(depth);
8715
0
8716
0
    // If we are in an object, print the next key and :, and skip to the next
8717
0
    // value.
8718
0
    if (is_object[depth]) {
8719
0
      format.key(iter.get_string_view());
8720
0
      format.print_space();
8721
0
      iter.json_index++;
8722
0
    }
8723
0
    switch (iter.tape_ref_type()) {
8724
0
8725
0
    // Arrays
8726
0
    case tape_type::START_ARRAY: {
8727
0
      // If we're too deep, we need to recurse to go deeper.
8728
0
      depth++;
8729
0
      if (simdjson_unlikely(depth >= MAX_DEPTH)) {
8730
0
        append(simdjson::dom::array(iter));
8731
0
        iter.json_index = iter.matching_brace_index() - 1; // Jump to the ]
8732
0
        depth--;
8733
0
        break;
8734
0
      }
8735
0
8736
0
      // Output start [
8737
0
      format.start_array();
8738
0
      iter.json_index++;
8739
0
8740
0
      // Handle empty [] (we don't want to come back around and print commas)
8741
0
      if (iter.tape_ref_type() == tape_type::END_ARRAY) {
8742
0
        format.end_array();
8743
0
        depth--;
8744
0
        break;
8745
0
      }
8746
0
8747
0
      is_object[depth] = false;
8748
0
      after_value = false;
8749
0
      format.print_newline();
8750
0
      continue;
8751
0
    }
8752
0
8753
0
    // Objects
8754
0
    case tape_type::START_OBJECT: {
8755
0
      // If we're too deep, we need to recurse to go deeper.
8756
0
      depth++;
8757
0
      if (simdjson_unlikely(depth >= MAX_DEPTH)) {
8758
0
        append(simdjson::dom::object(iter));
8759
0
        iter.json_index = iter.matching_brace_index() - 1; // Jump to the }
8760
0
        depth--;
8761
0
        break;
8762
0
      }
8763
0
8764
0
      // Output start {
8765
0
      format.start_object();
8766
0
      iter.json_index++;
8767
0
8768
0
      // Handle empty {} (we don't want to come back around and print commas)
8769
0
      if (iter.tape_ref_type() == tape_type::END_OBJECT) {
8770
0
        format.end_object();
8771
0
        depth--;
8772
0
        break;
8773
0
      }
8774
0
8775
0
      is_object[depth] = true;
8776
0
      after_value = false;
8777
0
      format.print_newline();
8778
0
      continue;
8779
0
    }
8780
0
8781
0
    // Scalars
8782
0
    case tape_type::STRING:
8783
0
      format.string(iter.get_string_view());
8784
0
      break;
8785
0
    case tape_type::INT64:
8786
0
      format.number(iter.next_tape_value<int64_t>());
8787
0
      iter.json_index++; // numbers take up 2 spots, so we need to increment
8788
0
                         // extra
8789
0
      break;
8790
0
    case tape_type::UINT64:
8791
0
      format.number(iter.next_tape_value<uint64_t>());
8792
0
      iter.json_index++; // numbers take up 2 spots, so we need to increment
8793
0
                         // extra
8794
0
      break;
8795
0
    case tape_type::DOUBLE:
8796
0
      format.number(iter.next_tape_value<double>());
8797
0
      iter.json_index++; // numbers take up 2 spots, so we need to increment
8798
0
                         // extra
8799
0
      break;
8800
0
    case tape_type::TRUE_VALUE:
8801
0
      format.true_atom();
8802
0
      break;
8803
0
    case tape_type::FALSE_VALUE:
8804
0
      format.false_atom();
8805
0
      break;
8806
0
    case tape_type::NULL_VALUE:
8807
0
      format.null_atom();
8808
0
      break;
8809
0
8810
0
    // These are impossible
8811
0
    case tape_type::END_ARRAY:
8812
0
    case tape_type::END_OBJECT:
8813
0
    case tape_type::ROOT:
8814
0
      SIMDJSON_UNREACHABLE();
8815
0
    }
8816
0
    iter.json_index++;
8817
0
    after_value = true;
8818
0
8819
0
    // Handle multiple ends in a row
8820
0
    while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY ||
8821
0
                          iter.tape_ref_type() == tape_type::END_OBJECT)) {
8822
0
      format.print_newline();
8823
0
      depth--;
8824
0
      format.print_indents(depth);
8825
0
      if (iter.tape_ref_type() == tape_type::END_ARRAY) {
8826
0
        format.end_array();
8827
0
      } else {
8828
0
        format.end_object();
8829
0
      }
8830
0
      iter.json_index++;
8831
0
    }
8832
0
8833
0
    // Stop when we're at depth 0
8834
0
  } while (depth != 0);
8835
0
8836
0
  format.print_newline();
8837
0
}
8838
8839
template <class serializer>
8840
0
inline void string_builder<serializer>::append(simdjson::dom::object value) {
8841
0
  format.start_object();
8842
0
  auto pair = value.begin();
8843
0
  auto end = value.end();
8844
0
  if (pair != end) {
8845
0
    append(*pair);
8846
0
    for (++pair; pair != end; ++pair) {
8847
0
      format.comma();
8848
0
      append(*pair);
8849
0
    }
8850
0
  }
8851
0
  format.end_object();
8852
0
}
8853
8854
template <class serializer>
8855
0
inline void string_builder<serializer>::append(simdjson::dom::array value) {
8856
0
  format.start_array();
8857
0
  auto iter = value.begin();
8858
0
  auto end = value.end();
8859
0
  if (iter != end) {
8860
0
    append(*iter);
8861
0
    for (++iter; iter != end; ++iter) {
8862
0
      format.comma();
8863
0
      append(*iter);
8864
0
    }
8865
0
  }
8866
0
  format.end_array();
8867
0
}
8868
8869
template <class serializer>
8870
0
simdjson_inline void string_builder<serializer>::append(simdjson::dom::key_value_pair kv) {
8871
0
  format.key(kv.key);
8872
0
  append(kv.value);
8873
0
}
8874
8875
template <class serializer>
8876
simdjson_inline void string_builder<serializer>::clear() {
8877
  format.clear();
8878
}
8879
8880
template <class serializer>
8881
0
simdjson_inline std::string_view string_builder<serializer>::str() const {
8882
0
  return format.str();
8883
0
}
8884
8885
8886
} // namespace internal
8887
} // namespace simdjson
8888
8889
#endif
8890
/* end file simdjson/dom/serialization-inl.h */
8891
8892
#endif // SIMDJSON_DOM_H
8893
/* end file simdjson/dom.h */
8894
/* including simdjson/ondemand.h: #include "simdjson/ondemand.h" */
8895
/* begin file simdjson/ondemand.h */
8896
#ifndef SIMDJSON_ONDEMAND_H
8897
#define SIMDJSON_ONDEMAND_H
8898
8899
/* including simdjson/builtin/ondemand.h: #include "simdjson/builtin/ondemand.h" */
8900
/* begin file simdjson/builtin/ondemand.h */
8901
#ifndef SIMDJSON_BUILTIN_ONDEMAND_H
8902
#define SIMDJSON_BUILTIN_ONDEMAND_H
8903
8904
/* including simdjson/builtin.h: #include "simdjson/builtin.h" */
8905
/* begin file simdjson/builtin.h */
8906
#ifndef SIMDJSON_BUILTIN_H
8907
#define SIMDJSON_BUILTIN_H
8908
8909
/* including simdjson/builtin/base.h: #include "simdjson/builtin/base.h" */
8910
/* begin file simdjson/builtin/base.h */
8911
#ifndef SIMDJSON_BUILTIN_BASE_H
8912
#define SIMDJSON_BUILTIN_BASE_H
8913
8914
/* skipped duplicate #include "simdjson/base.h" */
8915
/* including simdjson/implementation_detection.h: #include "simdjson/implementation_detection.h" */
8916
/* begin file simdjson/implementation_detection.h */
8917
#ifndef SIMDJSON_IMPLEMENTATION_DETECTION_H
8918
#define SIMDJSON_IMPLEMENTATION_DETECTION_H
8919
8920
/* skipped duplicate #include "simdjson/base.h" */
8921
8922
// 0 is reserved, because undefined SIMDJSON_IMPLEMENTATION equals 0 in preprocessor macros.
8923
#define SIMDJSON_IMPLEMENTATION_ID_arm64 1
8924
#define SIMDJSON_IMPLEMENTATION_ID_fallback 2
8925
#define SIMDJSON_IMPLEMENTATION_ID_haswell 3
8926
#define SIMDJSON_IMPLEMENTATION_ID_icelake 4
8927
#define SIMDJSON_IMPLEMENTATION_ID_ppc64 5
8928
#define SIMDJSON_IMPLEMENTATION_ID_westmere 6
8929
8930
#define SIMDJSON_IMPLEMENTATION_ID_FOR(IMPL) SIMDJSON_CAT(SIMDJSON_IMPLEMENTATION_ID_, IMPL)
8931
#define SIMDJSON_IMPLEMENTATION_ID SIMDJSON_IMPLEMENTATION_ID_FOR(SIMDJSON_IMPLEMENTATION)
8932
8933
#define SIMDJSON_IMPLEMENTATION_IS(IMPL) SIMDJSON_IMPLEMENTATION_ID == SIMDJSON_IMPLEMENTATION_ID_FOR(IMPL)
8934
8935
//
8936
// First, figure out which implementations can be run. Doing it here makes it so we don't have to worry about the order
8937
// in which we include them.
8938
//
8939
8940
#ifndef SIMDJSON_IMPLEMENTATION_ARM64
8941
#define SIMDJSON_IMPLEMENTATION_ARM64 (SIMDJSON_IS_ARM64)
8942
#endif
8943
#define SIMDJSON_CAN_ALWAYS_RUN_ARM64 SIMDJSON_IMPLEMENTATION_ARM64 && SIMDJSON_IS_ARM64
8944
8945
// Default Icelake to on if this is x86-64. Even if we're not compiled for it, it could be selected
8946
// at runtime.
8947
#ifndef SIMDJSON_IMPLEMENTATION_ICELAKE
8948
#define SIMDJSON_IMPLEMENTATION_ICELAKE ((SIMDJSON_IS_X86_64) && (SIMDJSON_AVX512_ALLOWED) && (SIMDJSON_COMPILER_SUPPORTS_VBMI2))
8949
#endif
8950
8951
#ifdef _MSC_VER
8952
// To see why  (__BMI__) && (__PCLMUL__) && (__LZCNT__) are not part of this next line, see
8953
// https://github.com/simdjson/simdjson/issues/1247
8954
#define SIMDJSON_CAN_ALWAYS_RUN_ICELAKE ((SIMDJSON_IMPLEMENTATION_ICELAKE) && (__AVX2__) && (__AVX512F__) && (__AVX512DQ__) && (__AVX512CD__) && (__AVX512BW__) && (__AVX512VL__) && (__AVX512VBMI2__))
8955
#else
8956
#define SIMDJSON_CAN_ALWAYS_RUN_ICELAKE ((SIMDJSON_IMPLEMENTATION_ICELAKE) && (__AVX2__) && (__BMI__) && (__PCLMUL__) && (__LZCNT__) && (__AVX512F__) && (__AVX512DQ__) && (__AVX512CD__) && (__AVX512BW__) && (__AVX512VL__) && (__AVX512VBMI2__))
8957
#endif
8958
8959
// Default Haswell to on if this is x86-64. Even if we're not compiled for it, it could be selected
8960
// at runtime.
8961
#ifndef SIMDJSON_IMPLEMENTATION_HASWELL
8962
#if SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
8963
// if icelake is always available, never enable haswell.
8964
#define SIMDJSON_IMPLEMENTATION_HASWELL 0
8965
#else
8966
#define SIMDJSON_IMPLEMENTATION_HASWELL SIMDJSON_IS_X86_64
8967
#endif
8968
#endif
8969
#ifdef _MSC_VER
8970
// To see why  (__BMI__) && (__PCLMUL__) && (__LZCNT__) are not part of this next line, see
8971
// https://github.com/simdjson/simdjson/issues/1247
8972
#define SIMDJSON_CAN_ALWAYS_RUN_HASWELL ((SIMDJSON_IMPLEMENTATION_HASWELL) && (SIMDJSON_IS_X86_64) && (__AVX2__))
8973
#else
8974
#define SIMDJSON_CAN_ALWAYS_RUN_HASWELL ((SIMDJSON_IMPLEMENTATION_HASWELL) && (SIMDJSON_IS_X86_64) && (__AVX2__) && (__BMI__) && (__PCLMUL__) && (__LZCNT__))
8975
#endif
8976
8977
// Default Westmere to on if this is x86-64.
8978
#ifndef SIMDJSON_IMPLEMENTATION_WESTMERE
8979
#if SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL
8980
// if icelake or haswell are always available, never enable westmere.
8981
#define SIMDJSON_IMPLEMENTATION_WESTMERE 0
8982
#else
8983
#define SIMDJSON_IMPLEMENTATION_WESTMERE SIMDJSON_IS_X86_64
8984
#endif
8985
#endif
8986
#define SIMDJSON_CAN_ALWAYS_RUN_WESTMERE (SIMDJSON_IMPLEMENTATION_WESTMERE && SIMDJSON_IS_X86_64 && __SSE4_2__ && __PCLMUL__)
8987
8988
#ifndef SIMDJSON_IMPLEMENTATION_PPC64
8989
#define SIMDJSON_IMPLEMENTATION_PPC64 (SIMDJSON_IS_PPC64 && SIMDJSON_IS_PPC64_VMX)
8990
#endif
8991
#define SIMDJSON_CAN_ALWAYS_RUN_PPC64 SIMDJSON_IMPLEMENTATION_PPC64 && SIMDJSON_IS_PPC64 && SIMDJSON_IS_PPC64_VMX
8992
8993
// Default Fallback to on unless a builtin implementation has already been selected.
8994
#ifndef SIMDJSON_IMPLEMENTATION_FALLBACK
8995
#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64
8996
// if anything at all except fallback can always run, then disable fallback.
8997
#define SIMDJSON_IMPLEMENTATION_FALLBACK 0
8998
#else
8999
#define SIMDJSON_IMPLEMENTATION_FALLBACK 1
9000
#endif
9001
#endif
9002
#define SIMDJSON_CAN_ALWAYS_RUN_FALLBACK SIMDJSON_IMPLEMENTATION_FALLBACK
9003
9004
// Determine the best builtin implementation
9005
#ifndef SIMDJSON_BUILTIN_IMPLEMENTATION
9006
9007
#if SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
9008
#define SIMDJSON_BUILTIN_IMPLEMENTATION icelake
9009
#elif SIMDJSON_CAN_ALWAYS_RUN_HASWELL
9010
#define SIMDJSON_BUILTIN_IMPLEMENTATION haswell
9011
#elif SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
9012
#define SIMDJSON_BUILTIN_IMPLEMENTATION westmere
9013
#elif SIMDJSON_CAN_ALWAYS_RUN_ARM64
9014
#define SIMDJSON_BUILTIN_IMPLEMENTATION arm64
9015
#elif SIMDJSON_CAN_ALWAYS_RUN_PPC64
9016
#define SIMDJSON_BUILTIN_IMPLEMENTATION ppc64
9017
#elif SIMDJSON_CAN_ALWAYS_RUN_FALLBACK
9018
#define SIMDJSON_BUILTIN_IMPLEMENTATION fallback
9019
#else
9020
#error "All possible implementations (including fallback) have been disabled! simdjson will not run."
9021
#endif
9022
9023
#endif // SIMDJSON_BUILTIN_IMPLEMENTATION
9024
9025
#define SIMDJSON_BUILTIN_IMPLEMENTATION_ID SIMDJSON_IMPLEMENTATION_ID_FOR(SIMDJSON_BUILTIN_IMPLEMENTATION)
9026
#define SIMDJSON_BUILTIN_IMPLEMENTATION_IS(IMPL) SIMDJSON_BUILTIN_IMPLEMENTATION_ID == SIMDJSON_IMPLEMENTATION_ID_FOR(IMPL)
9027
9028
#endif // SIMDJSON_IMPLEMENTATION_DETECTION_H
9029
/* end file simdjson/implementation_detection.h */
9030
9031
namespace simdjson {
9032
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
9033
  namespace arm64 {}
9034
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
9035
  namespace fallback {}
9036
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
9037
  namespace haswell {}
9038
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
9039
  namespace icelake {}
9040
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
9041
  namespace ppc64 {}
9042
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
9043
  namespace westmere {}
9044
#else
9045
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
9046
#endif
9047
9048
  /**
9049
   * Represents the best statically linked simdjson implementation that can be used by the compiling
9050
   * program.
9051
   *
9052
   * Detects what options the program is compiled against, and picks the minimum implementation that
9053
   * will work on any computer that can run the program. For example, if you compile with g++
9054
   * -march=westmere, it will pick the westmere implementation. The haswell implementation will
9055
   * still be available, and can be selected at runtime, but the builtin implementation (and any
9056
   * code that uses it) will use westmere.
9057
   */
9058
  namespace builtin = SIMDJSON_BUILTIN_IMPLEMENTATION;
9059
} // namespace simdjson
9060
9061
#endif // SIMDJSON_BUILTIN_BASE_H
9062
/* end file simdjson/builtin/base.h */
9063
/* including simdjson/builtin/implementation.h: #include "simdjson/builtin/implementation.h" */
9064
/* begin file simdjson/builtin/implementation.h */
9065
#ifndef SIMDJSON_BUILTIN_IMPLEMENTATION_H
9066
#define SIMDJSON_BUILTIN_IMPLEMENTATION_H
9067
9068
/* skipped duplicate #include "simdjson/builtin/base.h" */
9069
9070
/* including simdjson/generic/dependencies.h: #include "simdjson/generic/dependencies.h" */
9071
/* begin file simdjson/generic/dependencies.h */
9072
#ifdef SIMDJSON_CONDITIONAL_INCLUDE
9073
#error simdjson/generic/dependencies.h must be included before defining SIMDJSON_CONDITIONAL_INCLUDE!
9074
#endif
9075
9076
#ifndef SIMDJSON_GENERIC_DEPENDENCIES_H
9077
#define SIMDJSON_GENERIC_DEPENDENCIES_H
9078
9079
// Internal headers needed for generics.
9080
// All includes referencing simdjson headers *not* under simdjson/generic must be here!
9081
// Otherwise, amalgamation will fail.
9082
/* skipped duplicate #include "simdjson/base.h" */
9083
/* skipped duplicate #include "simdjson/implementation.h" */
9084
/* skipped duplicate #include "simdjson/implementation_detection.h" */
9085
/* including simdjson/internal/instruction_set.h: #include "simdjson/internal/instruction_set.h" */
9086
/* begin file simdjson/internal/instruction_set.h */
9087
/* From
9088
https://github.com/endorno/pytorch/blob/master/torch/lib/TH/generic/simd/simd.h
9089
Highly modified.
9090
9091
Copyright (c) 2016-     Facebook, Inc            (Adam Paszke)
9092
Copyright (c) 2014-     Facebook, Inc            (Soumith Chintala)
9093
Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert)
9094
Copyright (c) 2012-2014 Deepmind Technologies    (Koray Kavukcuoglu)
9095
Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu)
9096
Copyright (c) 2011-2013 NYU                      (Clement Farabet)
9097
Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou,
9098
Iain Melvin, Jason Weston) Copyright (c) 2006      Idiap Research Institute
9099
(Samy Bengio) Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert,
9100
Samy Bengio, Johnny Mariethoz)
9101
9102
All rights reserved.
9103
9104
Redistribution and use in source and binary forms, with or without
9105
modification, are permitted provided that the following conditions are met:
9106
9107
1. Redistributions of source code must retain the above copyright
9108
   notice, this list of conditions and the following disclaimer.
9109
9110
2. Redistributions in binary form must reproduce the above copyright
9111
   notice, this list of conditions and the following disclaimer in the
9112
   documentation and/or other materials provided with the distribution.
9113
9114
3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories
9115
America and IDIAP Research Institute nor the names of its contributors may be
9116
   used to endorse or promote products derived from this software without
9117
   specific prior written permission.
9118
9119
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9120
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9121
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9122
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
9123
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
9124
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
9125
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
9126
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
9127
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
9128
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
9129
POSSIBILITY OF SUCH DAMAGE.
9130
*/
9131
9132
#ifndef SIMDJSON_INTERNAL_INSTRUCTION_SET_H
9133
#define SIMDJSON_INTERNAL_INSTRUCTION_SET_H
9134
9135
namespace simdjson {
9136
namespace internal {
9137
9138
enum instruction_set {
9139
  DEFAULT = 0x0,
9140
  NEON = 0x1,
9141
  AVX2 = 0x4,
9142
  SSE42 = 0x8,
9143
  PCLMULQDQ = 0x10,
9144
  BMI1 = 0x20,
9145
  BMI2 = 0x40,
9146
  ALTIVEC = 0x80,
9147
  AVX512F = 0x100,
9148
  AVX512DQ = 0x200,
9149
  AVX512IFMA = 0x400,
9150
  AVX512PF = 0x800,
9151
  AVX512ER = 0x1000,
9152
  AVX512CD = 0x2000,
9153
  AVX512BW = 0x4000,
9154
  AVX512VL = 0x8000,
9155
  AVX512VBMI2 = 0x10000
9156
};
9157
9158
} // namespace internal
9159
} // namespace simdjson
9160
9161
#endif // SIMDJSON_INTERNAL_INSTRUCTION_SET_H
9162
/* end file simdjson/internal/instruction_set.h */
9163
/* skipped duplicate #include "simdjson/internal/dom_parser_implementation.h" */
9164
/* including simdjson/internal/jsoncharutils_tables.h: #include "simdjson/internal/jsoncharutils_tables.h" */
9165
/* begin file simdjson/internal/jsoncharutils_tables.h */
9166
#ifndef SIMDJSON_INTERNAL_JSONCHARUTILS_TABLES_H
9167
#define SIMDJSON_INTERNAL_JSONCHARUTILS_TABLES_H
9168
9169
/* skipped duplicate #include "simdjson/base.h" */
9170
9171
#ifdef JSON_TEST_STRINGS
9172
void found_string(const uint8_t *buf, const uint8_t *parsed_begin,
9173
                  const uint8_t *parsed_end);
9174
void found_bad_string(const uint8_t *buf);
9175
#endif
9176
9177
namespace simdjson {
9178
namespace internal {
9179
// structural chars here are
9180
// they are { 0x7b } 0x7d : 0x3a [ 0x5b ] 0x5d , 0x2c (and NULL)
9181
// we are also interested in the four whitespace characters
9182
// space 0x20, linefeed 0x0a, horizontal tab 0x09 and carriage return 0x0d
9183
9184
extern SIMDJSON_DLLIMPORTEXPORT const bool structural_or_whitespace_negated[256];
9185
extern SIMDJSON_DLLIMPORTEXPORT const bool structural_or_whitespace[256];
9186
extern SIMDJSON_DLLIMPORTEXPORT const uint32_t digit_to_val32[886];
9187
9188
} // namespace internal
9189
} // namespace simdjson
9190
9191
#endif // SIMDJSON_INTERNAL_JSONCHARUTILS_TABLES_H
9192
/* end file simdjson/internal/jsoncharutils_tables.h */
9193
/* including simdjson/internal/numberparsing_tables.h: #include "simdjson/internal/numberparsing_tables.h" */
9194
/* begin file simdjson/internal/numberparsing_tables.h */
9195
#ifndef SIMDJSON_INTERNAL_NUMBERPARSING_TABLES_H
9196
#define SIMDJSON_INTERNAL_NUMBERPARSING_TABLES_H
9197
9198
/* skipped duplicate #include "simdjson/base.h" */
9199
9200
namespace simdjson {
9201
namespace internal {
9202
/**
9203
 * The smallest non-zero float (binary64) is 2^-1074.
9204
 * We take as input numbers of the form w x 10^q where w < 2^64.
9205
 * We have that w * 10^-343  <  2^(64-344) 5^-343 < 2^-1076.
9206
 * However, we have that
9207
 * (2^64-1) * 10^-342 =  (2^64-1) * 2^-342 * 5^-342 > 2^-1074.
9208
 * Thus it is possible for a number of the form w * 10^-342 where
9209
 * w is a 64-bit value to be a non-zero floating-point number.
9210
 *********
9211
 * Any number of form w * 10^309 where w>= 1 is going to be
9212
 * infinite in binary64 so we never need to worry about powers
9213
 * of 5 greater than 308.
9214
 */
9215
constexpr int smallest_power = -342;
9216
constexpr int largest_power = 308;
9217
9218
/**
9219
 * Represents a 128-bit value.
9220
 * low: least significant 64 bits.
9221
 * high: most significant 64 bits.
9222
 */
9223
struct value128 {
9224
  uint64_t low;
9225
  uint64_t high;
9226
};
9227
9228
9229
// Precomputed powers of ten from 10^0 to 10^22. These
9230
// can be represented exactly using the double type.
9231
extern SIMDJSON_DLLIMPORTEXPORT const double power_of_ten[];
9232
9233
9234
/**
9235
 * When mapping numbers from decimal to binary,
9236
 * we go from w * 10^q to m * 2^p but we have
9237
 * 10^q = 5^q * 2^q, so effectively
9238
 * we are trying to match
9239
 * w * 2^q * 5^q to m * 2^p. Thus the powers of two
9240
 * are not a concern since they can be represented
9241
 * exactly using the binary notation, only the powers of five
9242
 * affect the binary significand.
9243
 */
9244
9245
9246
// The truncated powers of five from 5^-342 all the way to 5^308
9247
// The mantissa is truncated to 128 bits, and
9248
// never rounded up. Uses about 10KB.
9249
extern SIMDJSON_DLLIMPORTEXPORT const uint64_t power_of_five_128[];
9250
} // namespace internal
9251
} // namespace simdjson
9252
9253
#endif // SIMDJSON_INTERNAL_NUMBERPARSING_TABLES_H
9254
/* end file simdjson/internal/numberparsing_tables.h */
9255
/* including simdjson/internal/simdprune_tables.h: #include "simdjson/internal/simdprune_tables.h" */
9256
/* begin file simdjson/internal/simdprune_tables.h */
9257
#ifndef SIMDJSON_INTERNAL_SIMDPRUNE_TABLES_H
9258
#define SIMDJSON_INTERNAL_SIMDPRUNE_TABLES_H
9259
9260
/* skipped duplicate #include "simdjson/base.h" */
9261
9262
#include <cstdint>
9263
9264
namespace simdjson { // table modified and copied from
9265
namespace internal { // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetTable
9266
9267
extern SIMDJSON_DLLIMPORTEXPORT const unsigned char BitsSetTable256mul2[256];
9268
9269
extern SIMDJSON_DLLIMPORTEXPORT const uint8_t pshufb_combine_table[272];
9270
9271
// 256 * 8 bytes = 2kB, easily fits in cache.
9272
extern SIMDJSON_DLLIMPORTEXPORT const uint64_t thintable_epi8[256];
9273
9274
} // namespace internal
9275
} // namespace simdjson
9276
9277
#endif // SIMDJSON_INTERNAL_SIMDPRUNE_TABLES_H
9278
/* end file simdjson/internal/simdprune_tables.h */
9279
9280
#endif // SIMDJSON_GENERIC_DEPENDENCIES_H
9281
/* end file simdjson/generic/dependencies.h */
9282
9283
/* defining SIMDJSON_CONDITIONAL_INCLUDE */
9284
#define SIMDJSON_CONDITIONAL_INCLUDE
9285
9286
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
9287
/* including simdjson/arm64/implementation.h: #include "simdjson/arm64/implementation.h" */
9288
/* begin file simdjson/arm64/implementation.h */
9289
#ifndef SIMDJSON_ARM64_IMPLEMENTATION_H
9290
#define SIMDJSON_ARM64_IMPLEMENTATION_H
9291
9292
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9293
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
9294
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
9295
/* amalgamation skipped (editor-only): #include "simdjson/internal/instruction_set.h" */
9296
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9297
9298
namespace simdjson {
9299
namespace arm64 {
9300
9301
/**
9302
 * @private
9303
 */
9304
class implementation final : public simdjson::implementation {
9305
public:
9306
  simdjson_inline implementation() : simdjson::implementation("arm64", "ARM NEON", internal::instruction_set::NEON) {}
9307
  simdjson_warn_unused error_code create_dom_parser_implementation(
9308
    size_t capacity,
9309
    size_t max_length,
9310
    std::unique_ptr<internal::dom_parser_implementation>& dst
9311
  ) const noexcept final;
9312
  simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
9313
  simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
9314
};
9315
9316
} // namespace arm64
9317
} // namespace simdjson
9318
9319
#endif // SIMDJSON_ARM64_IMPLEMENTATION_H
9320
/* end file simdjson/arm64/implementation.h */
9321
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
9322
/* including simdjson/fallback/implementation.h: #include "simdjson/fallback/implementation.h" */
9323
/* begin file simdjson/fallback/implementation.h */
9324
#ifndef SIMDJSON_FALLBACK_IMPLEMENTATION_H
9325
#define SIMDJSON_FALLBACK_IMPLEMENTATION_H
9326
9327
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9328
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
9329
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
9330
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9331
9332
namespace simdjson {
9333
namespace fallback {
9334
9335
/**
9336
 * @private
9337
 */
9338
class implementation final : public simdjson::implementation {
9339
public:
9340
  simdjson_inline implementation() : simdjson::implementation(
9341
      "fallback",
9342
      "Generic fallback implementation",
9343
      0
9344
0
  ) {}
9345
  simdjson_warn_unused error_code create_dom_parser_implementation(
9346
    size_t capacity,
9347
    size_t max_length,
9348
    std::unique_ptr<simdjson::internal::dom_parser_implementation>& dst
9349
  ) const noexcept final;
9350
  simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
9351
  simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
9352
};
9353
9354
} // namespace fallback
9355
} // namespace simdjson
9356
9357
#endif // SIMDJSON_FALLBACK_IMPLEMENTATION_H
9358
/* end file simdjson/fallback/implementation.h */
9359
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
9360
/* including simdjson/haswell/implementation.h: #include "simdjson/haswell/implementation.h" */
9361
/* begin file simdjson/haswell/implementation.h */
9362
#ifndef SIMDJSON_HASWELL_IMPLEMENTATION_H
9363
#define SIMDJSON_HASWELL_IMPLEMENTATION_H
9364
9365
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9366
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
9367
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
9368
/* amalgamation skipped (editor-only): #include "simdjson/internal/instruction_set.h" */
9369
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9370
9371
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_HASWELL
9372
namespace simdjson {
9373
namespace haswell {
9374
9375
/**
9376
 * @private
9377
 */
9378
class implementation final : public simdjson::implementation {
9379
public:
9380
  simdjson_inline implementation() : simdjson::implementation(
9381
      "haswell",
9382
      "Intel/AMD AVX2",
9383
      internal::instruction_set::AVX2 | internal::instruction_set::PCLMULQDQ | internal::instruction_set::BMI1 | internal::instruction_set::BMI2
9384
  ) {}
9385
  simdjson_warn_unused error_code create_dom_parser_implementation(
9386
    size_t capacity,
9387
    size_t max_length,
9388
    std::unique_ptr<internal::dom_parser_implementation>& dst
9389
  ) const noexcept final;
9390
  simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
9391
  simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
9392
};
9393
9394
} // namespace haswell
9395
} // namespace simdjson
9396
9397
#endif // SIMDJSON_HASWELL_IMPLEMENTATION_H
9398
/* end file simdjson/haswell/implementation.h */
9399
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
9400
/* including simdjson/icelake/implementation.h: #include "simdjson/icelake/implementation.h" */
9401
/* begin file simdjson/icelake/implementation.h */
9402
#ifndef SIMDJSON_ICELAKE_IMPLEMENTATION_H
9403
#define SIMDJSON_ICELAKE_IMPLEMENTATION_H
9404
9405
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9406
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
9407
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
9408
/* amalgamation skipped (editor-only): #include "simdjson/internal/instruction_set.h" */
9409
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9410
9411
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_ICELAKE
9412
namespace simdjson {
9413
namespace icelake {
9414
9415
/**
9416
 * @private
9417
 */
9418
class implementation final : public simdjson::implementation {
9419
public:
9420
  simdjson_inline implementation() : simdjson::implementation(
9421
      "icelake",
9422
      "Intel/AMD AVX512",
9423
      internal::instruction_set::AVX2 | internal::instruction_set::PCLMULQDQ | internal::instruction_set::BMI1 | internal::instruction_set::BMI2 | internal::instruction_set::AVX512F | internal::instruction_set::AVX512DQ | internal::instruction_set::AVX512CD | internal::instruction_set::AVX512BW | internal::instruction_set::AVX512VL | internal::instruction_set::AVX512VBMI2
9424
  ) {}
9425
  simdjson_warn_unused error_code create_dom_parser_implementation(
9426
    size_t capacity,
9427
    size_t max_length,
9428
    std::unique_ptr<internal::dom_parser_implementation>& dst
9429
  ) const noexcept final;
9430
  simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
9431
  simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
9432
};
9433
9434
} // namespace icelake
9435
} // namespace simdjson
9436
9437
#endif // SIMDJSON_ICELAKE_IMPLEMENTATION_H
9438
/* end file simdjson/icelake/implementation.h */
9439
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
9440
/* including simdjson/ppc64/implementation.h: #include "simdjson/ppc64/implementation.h" */
9441
/* begin file simdjson/ppc64/implementation.h */
9442
#ifndef SIMDJSON_PPC64_IMPLEMENTATION_H
9443
#define SIMDJSON_PPC64_IMPLEMENTATION_H
9444
9445
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9446
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
9447
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
9448
/* amalgamation skipped (editor-only): #include "simdjson/internal/instruction_set.h" */
9449
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9450
9451
namespace simdjson {
9452
9453
/**
9454
 * Implementation for ALTIVEC (PPC64).
9455
 */
9456
namespace ppc64 {
9457
9458
/**
9459
 * @private
9460
 */
9461
class implementation final : public simdjson::implementation {
9462
public:
9463
  simdjson_inline implementation()
9464
      : simdjson::implementation("ppc64", "PPC64 ALTIVEC",
9465
                                 internal::instruction_set::ALTIVEC) {}
9466
9467
  simdjson_warn_unused error_code create_dom_parser_implementation(
9468
      size_t capacity, size_t max_length,
9469
      std::unique_ptr<internal::dom_parser_implementation> &dst)
9470
      const noexcept final;
9471
  simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len,
9472
                                         uint8_t *dst,
9473
                                         size_t &dst_len) const noexcept final;
9474
  simdjson_warn_unused bool validate_utf8(const char *buf,
9475
                                          size_t len) const noexcept final;
9476
};
9477
9478
} // namespace ppc64
9479
} // namespace simdjson
9480
9481
#endif // SIMDJSON_PPC64_IMPLEMENTATION_H
9482
/* end file simdjson/ppc64/implementation.h */
9483
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
9484
/* including simdjson/westmere/implementation.h: #include "simdjson/westmere/implementation.h" */
9485
/* begin file simdjson/westmere/implementation.h */
9486
#ifndef SIMDJSON_WESTMERE_IMPLEMENTATION_H
9487
#define SIMDJSON_WESTMERE_IMPLEMENTATION_H
9488
9489
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9490
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
9491
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
9492
/* amalgamation skipped (editor-only): #include "simdjson/internal/instruction_set.h" */
9493
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9494
9495
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_WESTMERE
9496
namespace simdjson {
9497
namespace westmere {
9498
9499
/**
9500
 * @private
9501
 */
9502
class implementation final : public simdjson::implementation {
9503
public:
9504
  simdjson_inline implementation() : simdjson::implementation("westmere", "Intel/AMD SSE4.2", internal::instruction_set::SSE42 | internal::instruction_set::PCLMULQDQ) {}
9505
  simdjson_warn_unused error_code create_dom_parser_implementation(
9506
    size_t capacity,
9507
    size_t max_length,
9508
    std::unique_ptr<internal::dom_parser_implementation>& dst
9509
  ) const noexcept final;
9510
  simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
9511
  simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
9512
};
9513
9514
} // namespace westmere
9515
} // namespace simdjson
9516
9517
#endif // SIMDJSON_WESTMERE_IMPLEMENTATION_H
9518
/* end file simdjson/westmere/implementation.h */
9519
#else
9520
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
9521
#endif
9522
9523
/* undefining SIMDJSON_CONDITIONAL_INCLUDE */
9524
#undef SIMDJSON_CONDITIONAL_INCLUDE
9525
9526
namespace simdjson {
9527
  /**
9528
   * Function which returns a pointer to an implementation matching the "builtin" implementation.
9529
   * The builtin implementation is the best statically linked simdjson implementation that can be used by the compiling
9530
   * program. If you compile with g++ -march=haswell, this will return the haswell implementation.
9531
   * It is handy to be able to check what builtin was used: builtin_implementation()->name().
9532
   */
9533
  const implementation * builtin_implementation();
9534
} // namespace simdjson
9535
9536
#endif // SIMDJSON_BUILTIN_IMPLEMENTATION_H
9537
/* end file simdjson/builtin/implementation.h */
9538
9539
/* skipped duplicate #include "simdjson/generic/dependencies.h" */
9540
9541
/* defining SIMDJSON_CONDITIONAL_INCLUDE */
9542
#define SIMDJSON_CONDITIONAL_INCLUDE
9543
9544
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
9545
/* including simdjson/arm64.h: #include "simdjson/arm64.h" */
9546
/* begin file simdjson/arm64.h */
9547
#ifndef SIMDJSON_ARM64_H
9548
#define SIMDJSON_ARM64_H
9549
9550
/* including simdjson/arm64/begin.h: #include "simdjson/arm64/begin.h" */
9551
/* begin file simdjson/arm64/begin.h */
9552
/* defining SIMDJSON_IMPLEMENTATION to "arm64" */
9553
#define SIMDJSON_IMPLEMENTATION arm64
9554
/* including simdjson/arm64/base.h: #include "simdjson/arm64/base.h" */
9555
/* begin file simdjson/arm64/base.h */
9556
#ifndef SIMDJSON_ARM64_BASE_H
9557
#define SIMDJSON_ARM64_BASE_H
9558
9559
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9560
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
9561
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9562
9563
namespace simdjson {
9564
/**
9565
 * Implementation for NEON (ARMv8).
9566
 */
9567
namespace arm64 {
9568
9569
class implementation;
9570
9571
namespace {
9572
namespace simd {
9573
template <typename T> struct simd8;
9574
template <typename T> struct simd8x64;
9575
} // namespace simd
9576
} // unnamed namespace
9577
9578
} // namespace arm64
9579
} // namespace simdjson
9580
9581
#endif // SIMDJSON_ARM64_BASE_H
9582
/* end file simdjson/arm64/base.h */
9583
/* including simdjson/arm64/intrinsics.h: #include "simdjson/arm64/intrinsics.h" */
9584
/* begin file simdjson/arm64/intrinsics.h */
9585
#ifndef SIMDJSON_ARM64_INTRINSICS_H
9586
#define SIMDJSON_ARM64_INTRINSICS_H
9587
9588
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9589
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
9590
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9591
9592
// This should be the correct header whether
9593
// you use visual studio or other compilers.
9594
#include <arm_neon.h>
9595
9596
static_assert(sizeof(uint8x16_t) <= simdjson::SIMDJSON_PADDING, "insufficient padding for arm64");
9597
9598
#endif //  SIMDJSON_ARM64_INTRINSICS_H
9599
/* end file simdjson/arm64/intrinsics.h */
9600
/* including simdjson/arm64/bitmanipulation.h: #include "simdjson/arm64/bitmanipulation.h" */
9601
/* begin file simdjson/arm64/bitmanipulation.h */
9602
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
9603
#define SIMDJSON_ARM64_BITMANIPULATION_H
9604
9605
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9606
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
9607
/* amalgamation skipped (editor-only): #include "simdjson/arm64/intrinsics.h" */
9608
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9609
9610
namespace simdjson {
9611
namespace arm64 {
9612
namespace {
9613
9614
// We sometimes call trailing_zero on inputs that are zero,
9615
// but the algorithms do not end up using the returned value.
9616
// Sadly, sanitizers are not smart enough to figure it out.
9617
SIMDJSON_NO_SANITIZE_UNDEFINED
9618
// This function can be used safely even if not all bytes have been
9619
// initialized.
9620
// See issue https://github.com/simdjson/simdjson/issues/1965
9621
SIMDJSON_NO_SANITIZE_MEMORY
9622
simdjson_inline int trailing_zeroes(uint64_t input_num) {
9623
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
9624
  unsigned long ret;
9625
  // Search the mask data from least significant bit (LSB)
9626
  // to the most significant bit (MSB) for a set bit (1).
9627
  _BitScanForward64(&ret, input_num);
9628
  return (int)ret;
9629
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
9630
  return __builtin_ctzll(input_num);
9631
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
9632
}
9633
9634
/* result might be undefined when input_num is zero */
9635
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
9636
  return input_num & (input_num-1);
9637
}
9638
9639
/* result might be undefined when input_num is zero */
9640
simdjson_inline int leading_zeroes(uint64_t input_num) {
9641
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
9642
  unsigned long leading_zero = 0;
9643
  // Search the mask data from most significant bit (MSB)
9644
  // to least significant bit (LSB) for a set bit (1).
9645
  if (_BitScanReverse64(&leading_zero, input_num))
9646
    return (int)(63 - leading_zero);
9647
  else
9648
    return 64;
9649
#else
9650
  return __builtin_clzll(input_num);
9651
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
9652
}
9653
9654
/* result might be undefined when input_num is zero */
9655
simdjson_inline int count_ones(uint64_t input_num) {
9656
   return vaddv_u8(vcnt_u8(vcreate_u8(input_num)));
9657
}
9658
9659
9660
#if defined(__GNUC__) // catches clang and gcc
9661
/**
9662
 * ARM has a fast 64-bit "bit reversal function" that is handy. However,
9663
 * it is not generally available as an intrinsic function under Visual
9664
 * Studio (though this might be changing). Even under clang/gcc, we
9665
 * apparently need to invoke inline assembly.
9666
 */
9667
/*
9668
 * We use SIMDJSON_PREFER_REVERSE_BITS as a hint that algorithms that
9669
 * work well with bit reversal may use it.
9670
 */
9671
#define SIMDJSON_PREFER_REVERSE_BITS 1
9672
9673
/* reverse the bits */
9674
simdjson_inline uint64_t reverse_bits(uint64_t input_num) {
9675
  uint64_t rev_bits;
9676
  __asm("rbit %0, %1" : "=r"(rev_bits) : "r"(input_num));
9677
  return rev_bits;
9678
}
9679
9680
/**
9681
 * Flips bit at index 63 - lz. Thus if you have 'leading_zeroes' leading zeroes,
9682
 * then this will set to zero the leading bit. It is possible for leading_zeroes to be
9683
 * greating or equal to 63 in which case we trigger undefined behavior, but the output
9684
 * of such undefined behavior is never used.
9685
 **/
9686
SIMDJSON_NO_SANITIZE_UNDEFINED
9687
simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
9688
  return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
9689
}
9690
9691
#endif
9692
9693
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
9694
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
9695
  *result = value1 + value2;
9696
  return *result < value1;
9697
#else
9698
  return __builtin_uaddll_overflow(value1, value2,
9699
                                   reinterpret_cast<unsigned long long *>(result));
9700
#endif
9701
}
9702
9703
} // unnamed namespace
9704
} // namespace arm64
9705
} // namespace simdjson
9706
9707
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
9708
/* end file simdjson/arm64/bitmanipulation.h */
9709
/* including simdjson/arm64/bitmask.h: #include "simdjson/arm64/bitmask.h" */
9710
/* begin file simdjson/arm64/bitmask.h */
9711
#ifndef SIMDJSON_ARM64_BITMASK_H
9712
#define SIMDJSON_ARM64_BITMASK_H
9713
9714
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9715
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
9716
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9717
9718
namespace simdjson {
9719
namespace arm64 {
9720
namespace {
9721
9722
//
9723
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
9724
//
9725
// For example, prefix_xor(00100100) == 00011100
9726
//
9727
simdjson_inline uint64_t prefix_xor(uint64_t bitmask) {
9728
  /////////////
9729
  // We could do this with PMULL, but it is apparently slow.
9730
  //
9731
  //#ifdef __ARM_FEATURE_CRYPTO // some ARM processors lack this extension
9732
  //return vmull_p64(-1ULL, bitmask);
9733
  //#else
9734
  // Analysis by @sebpop:
9735
  // When diffing the assembly for src/stage1_find_marks.cpp I see that the eors are all spread out
9736
  // in between other vector code, so effectively the extra cycles of the sequence do not matter
9737
  // because the GPR units are idle otherwise and the critical path is on the FP side.
9738
  // Also the PMULL requires two extra fmovs: GPR->FP (3 cycles in N1, 5 cycles in A72 )
9739
  // and FP->GPR (2 cycles on N1 and 5 cycles on A72.)
9740
  ///////////
9741
  bitmask ^= bitmask << 1;
9742
  bitmask ^= bitmask << 2;
9743
  bitmask ^= bitmask << 4;
9744
  bitmask ^= bitmask << 8;
9745
  bitmask ^= bitmask << 16;
9746
  bitmask ^= bitmask << 32;
9747
  return bitmask;
9748
}
9749
9750
} // unnamed namespace
9751
} // namespace arm64
9752
} // namespace simdjson
9753
9754
#endif
9755
/* end file simdjson/arm64/bitmask.h */
9756
/* including simdjson/arm64/numberparsing_defs.h: #include "simdjson/arm64/numberparsing_defs.h" */
9757
/* begin file simdjson/arm64/numberparsing_defs.h */
9758
#ifndef SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
9759
#define SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
9760
9761
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9762
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
9763
/* amalgamation skipped (editor-only): #include "simdjson/arm64/intrinsics.h" */
9764
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
9765
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9766
9767
#include <cstring>
9768
9769
#if _M_ARM64
9770
// __umulh requires intrin.h
9771
#include <intrin.h>
9772
#endif // _M_ARM64
9773
9774
namespace simdjson {
9775
namespace arm64 {
9776
namespace numberparsing {
9777
9778
// we don't have SSE, so let us use a scalar function
9779
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
9780
/** @private */
9781
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
9782
  uint64_t val;
9783
  std::memcpy(&val, chars, sizeof(uint64_t));
9784
  val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
9785
  val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
9786
  return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
9787
}
9788
9789
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
9790
  internal::value128 answer;
9791
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
9792
#ifdef _M_ARM64
9793
  // ARM64 has native support for 64-bit multiplications, no need to emultate
9794
  answer.high = __umulh(value1, value2);
9795
  answer.low = value1 * value2;
9796
#else
9797
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
9798
#endif // _M_ARM64
9799
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
9800
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
9801
  answer.low = uint64_t(r);
9802
  answer.high = uint64_t(r >> 64);
9803
#endif
9804
  return answer;
9805
}
9806
9807
} // namespace numberparsing
9808
} // namespace arm64
9809
} // namespace simdjson
9810
9811
#define SIMDJSON_SWAR_NUMBER_PARSING 1
9812
9813
#endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
9814
/* end file simdjson/arm64/numberparsing_defs.h */
9815
/* including simdjson/arm64/simd.h: #include "simdjson/arm64/simd.h" */
9816
/* begin file simdjson/arm64/simd.h */
9817
#ifndef SIMDJSON_ARM64_SIMD_H
9818
#define SIMDJSON_ARM64_SIMD_H
9819
9820
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
9821
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
9822
/* amalgamation skipped (editor-only): #include "simdjson/arm64/bitmanipulation.h" */
9823
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
9824
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
9825
9826
namespace simdjson {
9827
namespace arm64 {
9828
namespace {
9829
namespace simd {
9830
9831
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
9832
namespace {
9833
// Start of private section with Visual Studio workaround
9834
9835
9836
#ifndef simdjson_make_uint8x16_t
9837
#define simdjson_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
9838
                             x13, x14, x15, x16)                                   \
9839
   ([=]() {                                                                        \
9840
     uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,                    \
9841
                                 x9, x10, x11, x12, x13, x14, x15, x16};           \
9842
     return vld1q_u8(array);                                                       \
9843
   }())
9844
#endif
9845
#ifndef simdjson_make_int8x16_t
9846
#define simdjson_make_int8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
9847
                             x13, x14, x15, x16)                                  \
9848
   ([=]() {                                                                       \
9849
     int8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,                    \
9850
                                 x9, x10, x11, x12, x13, x14, x15, x16};          \
9851
     return vld1q_s8(array);                                                      \
9852
   }())
9853
#endif
9854
9855
#ifndef simdjson_make_uint8x8_t
9856
#define simdjson_make_uint8x8_t(x1, x2, x3, x4, x5, x6, x7, x8)                \
9857
   ([=]() {                                                                    \
9858
     uint8_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};                \
9859
     return vld1_u8(array);                                                    \
9860
   }())
9861
#endif
9862
#ifndef simdjson_make_int8x8_t
9863
#define simdjson_make_int8x8_t(x1, x2, x3, x4, x5, x6, x7, x8)                 \
9864
   ([=]() {                                                                    \
9865
     int8_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};                 \
9866
     return vld1_s8(array);                                                    \
9867
   }())
9868
#endif
9869
#ifndef simdjson_make_uint16x8_t
9870
#define simdjson_make_uint16x8_t(x1, x2, x3, x4, x5, x6, x7, x8)               \
9871
   ([=]() {                                                                    \
9872
     uint16_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};               \
9873
     return vld1q_u16(array);                                                  \
9874
   }())
9875
#endif
9876
#ifndef simdjson_make_int16x8_t
9877
#define simdjson_make_int16x8_t(x1, x2, x3, x4, x5, x6, x7, x8)                \
9878
   ([=]() {                                                                    \
9879
     int16_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};                \
9880
     return vld1q_s16(array);                                                  \
9881
   }())
9882
#endif
9883
9884
// End of private section with Visual Studio workaround
9885
} // namespace
9886
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
9887
9888
9889
  template<typename T>
9890
  struct simd8;
9891
9892
  //
9893
  // Base class of simd8<uint8_t> and simd8<bool>, both of which use uint8x16_t internally.
9894
  //
9895
  template<typename T, typename Mask=simd8<bool>>
9896
  struct base_u8 {
9897
    uint8x16_t value;
9898
    static const int SIZE = sizeof(value);
9899
9900
    // Conversion from/to SIMD register
9901
    simdjson_inline base_u8(const uint8x16_t _value) : value(_value) {}
9902
    simdjson_inline operator const uint8x16_t&() const { return this->value; }
9903
    simdjson_inline operator uint8x16_t&() { return this->value; }
9904
9905
    // Bit operations
9906
    simdjson_inline simd8<T> operator|(const simd8<T> other) const { return vorrq_u8(*this, other); }
9907
    simdjson_inline simd8<T> operator&(const simd8<T> other) const { return vandq_u8(*this, other); }
9908
    simdjson_inline simd8<T> operator^(const simd8<T> other) const { return veorq_u8(*this, other); }
9909
    simdjson_inline simd8<T> bit_andnot(const simd8<T> other) const { return vbicq_u8(*this, other); }
9910
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
9911
    simdjson_inline simd8<T>& operator|=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast | other; return *this_cast; }
9912
    simdjson_inline simd8<T>& operator&=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast & other; return *this_cast; }
9913
    simdjson_inline simd8<T>& operator^=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
9914
9915
    friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return vceqq_u8(lhs, rhs); }
9916
9917
    template<int N=1>
9918
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
9919
      return vextq_u8(prev_chunk, *this, 16 - N);
9920
    }
9921
  };
9922
9923
  // SIMD byte mask type (returned by things like eq and gt)
9924
  template<>
9925
  struct simd8<bool>: base_u8<bool> {
9926
    typedef uint16_t bitmask_t;
9927
    typedef uint32_t bitmask2_t;
9928
9929
    static simdjson_inline simd8<bool> splat(bool _value) { return vmovq_n_u8(uint8_t(-(!!_value))); }
9930
9931
    simdjson_inline simd8(const uint8x16_t _value) : base_u8<bool>(_value) {}
9932
    // False constructor
9933
    simdjson_inline simd8() : simd8(vdupq_n_u8(0)) {}
9934
    // Splat constructor
9935
    simdjson_inline simd8(bool _value) : simd8(splat(_value)) {}
9936
9937
    // We return uint32_t instead of uint16_t because that seems to be more efficient for most
9938
    // purposes (cutting it down to uint16_t costs performance in some compilers).
9939
    simdjson_inline uint32_t to_bitmask() const {
9940
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
9941
      const uint8x16_t bit_mask =  simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
9942
                                                   0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
9943
#else
9944
      const uint8x16_t bit_mask =  {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
9945
                                    0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
9946
#endif
9947
      auto minput = *this & bit_mask;
9948
      uint8x16_t tmp = vpaddq_u8(minput, minput);
9949
      tmp = vpaddq_u8(tmp, tmp);
9950
      tmp = vpaddq_u8(tmp, tmp);
9951
      return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
9952
    }
9953
    simdjson_inline bool any() const { return vmaxvq_u8(*this) != 0; }
9954
  };
9955
9956
  // Unsigned bytes
9957
  template<>
9958
  struct simd8<uint8_t>: base_u8<uint8_t> {
9959
    static simdjson_inline uint8x16_t splat(uint8_t _value) { return vmovq_n_u8(_value); }
9960
    static simdjson_inline uint8x16_t zero() { return vdupq_n_u8(0); }
9961
    static simdjson_inline uint8x16_t load(const uint8_t* values) { return vld1q_u8(values); }
9962
9963
    simdjson_inline simd8(const uint8x16_t _value) : base_u8<uint8_t>(_value) {}
9964
    // Zero constructor
9965
    simdjson_inline simd8() : simd8(zero()) {}
9966
    // Array constructor
9967
    simdjson_inline simd8(const uint8_t values[16]) : simd8(load(values)) {}
9968
    // Splat constructor
9969
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
9970
    // Member-by-member initialization
9971
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
9972
    simdjson_inline simd8(
9973
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
9974
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
9975
    ) : simd8(simdjson_make_uint8x16_t(
9976
      v0, v1, v2, v3, v4, v5, v6, v7,
9977
      v8, v9, v10,v11,v12,v13,v14,v15
9978
    )) {}
9979
#else
9980
    simdjson_inline simd8(
9981
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
9982
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
9983
    ) : simd8(uint8x16_t{
9984
      v0, v1, v2, v3, v4, v5, v6, v7,
9985
      v8, v9, v10,v11,v12,v13,v14,v15
9986
    }) {}
9987
#endif
9988
9989
    // Repeat 16 values as many times as necessary (usually for lookup tables)
9990
    simdjson_inline static simd8<uint8_t> repeat_16(
9991
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
9992
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
9993
    ) {
9994
      return simd8<uint8_t>(
9995
        v0, v1, v2, v3, v4, v5, v6, v7,
9996
        v8, v9, v10,v11,v12,v13,v14,v15
9997
      );
9998
    }
9999
10000
    // Store to array
10001
    simdjson_inline void store(uint8_t dst[16]) const { return vst1q_u8(dst, *this); }
10002
10003
    // Saturated math
10004
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return vqaddq_u8(*this, other); }
10005
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return vqsubq_u8(*this, other); }
10006
10007
    // Addition/subtraction are the same for signed and unsigned
10008
    simdjson_inline simd8<uint8_t> operator+(const simd8<uint8_t> other) const { return vaddq_u8(*this, other); }
10009
    simdjson_inline simd8<uint8_t> operator-(const simd8<uint8_t> other) const { return vsubq_u8(*this, other); }
10010
    simdjson_inline simd8<uint8_t>& operator+=(const simd8<uint8_t> other) { *this = *this + other; return *this; }
10011
    simdjson_inline simd8<uint8_t>& operator-=(const simd8<uint8_t> other) { *this = *this - other; return *this; }
10012
10013
    // Order-specific operations
10014
    simdjson_inline uint8_t max_val() const { return vmaxvq_u8(*this); }
10015
    simdjson_inline uint8_t min_val() const { return vminvq_u8(*this); }
10016
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return vmaxq_u8(*this, other); }
10017
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return vminq_u8(*this, other); }
10018
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return vcleq_u8(*this, other); }
10019
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return vcgeq_u8(*this, other); }
10020
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return vcltq_u8(*this, other); }
10021
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return vcgtq_u8(*this, other); }
10022
    // Same as >, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero. For ARM, returns all 1's.
10023
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return simd8<uint8_t>(*this > other); }
10024
    // Same as <, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero. For ARM, returns all 1's.
10025
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return simd8<uint8_t>(*this < other); }
10026
10027
    // Bit-specific operations
10028
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return vtstq_u8(*this, bits); }
10029
    simdjson_inline bool any_bits_set_anywhere() const { return this->max_val() != 0; }
10030
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return (*this & bits).any_bits_set_anywhere(); }
10031
    template<int N>
10032
    simdjson_inline simd8<uint8_t> shr() const { return vshrq_n_u8(*this, N); }
10033
    template<int N>
10034
    simdjson_inline simd8<uint8_t> shl() const { return vshlq_n_u8(*this, N); }
10035
10036
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
10037
    template<typename L>
10038
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
10039
      return lookup_table.apply_lookup_16_to(*this);
10040
    }
10041
10042
10043
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
10044
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
10045
    // Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
10046
    // get written.
10047
    // Design consideration: it seems like a function with the
10048
    // signature simd8<L> compress(uint16_t mask) would be
10049
    // sensible, but the AVX ISA makes this kind of approach difficult.
10050
    template<typename L>
10051
    simdjson_inline void compress(uint16_t mask, L * output) const {
10052
      using internal::thintable_epi8;
10053
      using internal::BitsSetTable256mul2;
10054
      using internal::pshufb_combine_table;
10055
      // this particular implementation was inspired by work done by @animetosho
10056
      // we do it in two steps, first 8 bytes and then second 8 bytes
10057
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
10058
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
10059
      // next line just loads the 64-bit values thintable_epi8[mask1] and
10060
      // thintable_epi8[mask2] into a 128-bit register, using only
10061
      // two instructions on most compilers.
10062
      uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]};
10063
      uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64);
10064
      // we increment by 0x08 the second half of the mask
10065
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
10066
      uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
10067
#else
10068
      uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
10069
#endif
10070
      shufmask = vaddq_u8(shufmask, inc);
10071
      // this is the version "nearly pruned"
10072
      uint8x16_t pruned = vqtbl1q_u8(*this, shufmask);
10073
      // we still need to put the two halves together.
10074
      // we compute the popcount of the first half:
10075
      int pop1 = BitsSetTable256mul2[mask1];
10076
      // then load the corresponding mask, what it does is to write
10077
      // only the first pop1 bytes from the first 8 bytes, and then
10078
      // it fills in with the bytes from the second 8 bytes + some filling
10079
      // at the end.
10080
      uint8x16_t compactmask = vld1q_u8(reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
10081
      uint8x16_t answer = vqtbl1q_u8(pruned, compactmask);
10082
      vst1q_u8(reinterpret_cast<uint8_t*>(output), answer);
10083
    }
10084
10085
    // Copies all bytes corresponding to a 0 in the low half of the mask (interpreted as a
10086
    // bitset) to output1, then those corresponding to a 0 in the high half to output2.
10087
    template<typename L>
10088
    simdjson_inline void compress_halves(uint16_t mask, L *output1, L *output2) const {
10089
      using internal::thintable_epi8;
10090
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
10091
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
10092
      uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]);
10093
      uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]);
10094
      // we increment by 0x08 the second half of the mask
10095
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
10096
      uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
10097
#else
10098
      uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
10099
#endif
10100
      compactmask2 = vadd_u8(compactmask2, inc);
10101
      // store each result (with the second store possibly overlapping the first)
10102
      vst1_u8((uint8_t*)output1, vqtbl1_u8(*this, compactmask1));
10103
      vst1_u8((uint8_t*)output2, vqtbl1_u8(*this, compactmask2));
10104
    }
10105
10106
    template<typename L>
10107
    simdjson_inline simd8<L> lookup_16(
10108
        L replace0,  L replace1,  L replace2,  L replace3,
10109
        L replace4,  L replace5,  L replace6,  L replace7,
10110
        L replace8,  L replace9,  L replace10, L replace11,
10111
        L replace12, L replace13, L replace14, L replace15) const {
10112
      return lookup_16(simd8<L>::repeat_16(
10113
        replace0,  replace1,  replace2,  replace3,
10114
        replace4,  replace5,  replace6,  replace7,
10115
        replace8,  replace9,  replace10, replace11,
10116
        replace12, replace13, replace14, replace15
10117
      ));
10118
    }
10119
10120
    template<typename T>
10121
    simdjson_inline simd8<uint8_t> apply_lookup_16_to(const simd8<T> original) {
10122
      return vqtbl1q_u8(*this, simd8<uint8_t>(original));
10123
    }
10124
  };
10125
10126
  // Signed bytes
10127
  template<>
10128
  struct simd8<int8_t> {
10129
    int8x16_t value;
10130
10131
    static simdjson_inline simd8<int8_t> splat(int8_t _value) { return vmovq_n_s8(_value); }
10132
    static simdjson_inline simd8<int8_t> zero() { return vdupq_n_s8(0); }
10133
    static simdjson_inline simd8<int8_t> load(const int8_t values[16]) { return vld1q_s8(values); }
10134
10135
    // Conversion from/to SIMD register
10136
    simdjson_inline simd8(const int8x16_t _value) : value{_value} {}
10137
    simdjson_inline operator const int8x16_t&() const { return this->value; }
10138
    simdjson_inline operator int8x16_t&() { return this->value; }
10139
10140
    // Zero constructor
10141
    simdjson_inline simd8() : simd8(zero()) {}
10142
    // Splat constructor
10143
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
10144
    // Array constructor
10145
    simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {}
10146
    // Member-by-member initialization
10147
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
10148
    simdjson_inline simd8(
10149
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3, int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
10150
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
10151
    ) : simd8(simdjson_make_int8x16_t(
10152
      v0, v1, v2, v3, v4, v5, v6, v7,
10153
      v8, v9, v10,v11,v12,v13,v14,v15
10154
    )) {}
10155
#else
10156
    simdjson_inline simd8(
10157
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3, int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
10158
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
10159
    ) : simd8(int8x16_t{
10160
      v0, v1, v2, v3, v4, v5, v6, v7,
10161
      v8, v9, v10,v11,v12,v13,v14,v15
10162
    }) {}
10163
#endif
10164
    // Repeat 16 values as many times as necessary (usually for lookup tables)
10165
    simdjson_inline static simd8<int8_t> repeat_16(
10166
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
10167
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
10168
    ) {
10169
      return simd8<int8_t>(
10170
        v0, v1, v2, v3, v4, v5, v6, v7,
10171
        v8, v9, v10,v11,v12,v13,v14,v15
10172
      );
10173
    }
10174
10175
    // Store to array
10176
    simdjson_inline void store(int8_t dst[16]) const { return vst1q_s8(dst, *this); }
10177
10178
    // Explicit conversion to/from unsigned
10179
    //
10180
    // Under Visual Studio/ARM64 uint8x16_t and int8x16_t are apparently the same type.
10181
    // In theory, we could check this occurrence with std::same_as and std::enabled_if but it is C++14
10182
    // and relatively ugly and hard to read.
10183
#ifndef SIMDJSON_REGULAR_VISUAL_STUDIO
10184
    simdjson_inline explicit simd8(const uint8x16_t other): simd8(vreinterpretq_s8_u8(other)) {}
10185
#endif
10186
    simdjson_inline explicit operator simd8<uint8_t>() const { return vreinterpretq_u8_s8(this->value); }
10187
10188
    // Math
10189
    simdjson_inline simd8<int8_t> operator+(const simd8<int8_t> other) const { return vaddq_s8(*this, other); }
10190
    simdjson_inline simd8<int8_t> operator-(const simd8<int8_t> other) const { return vsubq_s8(*this, other); }
10191
    simdjson_inline simd8<int8_t>& operator+=(const simd8<int8_t> other) { *this = *this + other; return *this; }
10192
    simdjson_inline simd8<int8_t>& operator-=(const simd8<int8_t> other) { *this = *this - other; return *this; }
10193
10194
    // Order-sensitive comparisons
10195
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return vmaxq_s8(*this, other); }
10196
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return vminq_s8(*this, other); }
10197
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return vcgtq_s8(*this, other); }
10198
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return vcltq_s8(*this, other); }
10199
    simdjson_inline simd8<bool> operator==(const simd8<int8_t> other) const { return vceqq_s8(*this, other); }
10200
10201
    template<int N=1>
10202
    simdjson_inline simd8<int8_t> prev(const simd8<int8_t> prev_chunk) const {
10203
      return vextq_s8(prev_chunk, *this, 16 - N);
10204
    }
10205
10206
    // Perform a lookup assuming no value is larger than 16
10207
    template<typename L>
10208
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
10209
      return lookup_table.apply_lookup_16_to(*this);
10210
    }
10211
    template<typename L>
10212
    simdjson_inline simd8<L> lookup_16(
10213
        L replace0,  L replace1,  L replace2,  L replace3,
10214
        L replace4,  L replace5,  L replace6,  L replace7,
10215
        L replace8,  L replace9,  L replace10, L replace11,
10216
        L replace12, L replace13, L replace14, L replace15) const {
10217
      return lookup_16(simd8<L>::repeat_16(
10218
        replace0,  replace1,  replace2,  replace3,
10219
        replace4,  replace5,  replace6,  replace7,
10220
        replace8,  replace9,  replace10, replace11,
10221
        replace12, replace13, replace14, replace15
10222
      ));
10223
    }
10224
10225
    template<typename T>
10226
    simdjson_inline simd8<int8_t> apply_lookup_16_to(const simd8<T> original) {
10227
      return vqtbl1q_s8(*this, simd8<uint8_t>(original));
10228
    }
10229
  };
10230
10231
  template<typename T>
10232
  struct simd8x64 {
10233
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
10234
    static_assert(NUM_CHUNKS == 4, "ARM kernel should use four registers per 64-byte block.");
10235
    const simd8<T> chunks[NUM_CHUNKS];
10236
10237
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
10238
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
10239
    simd8x64() = delete; // no default constructor allowed
10240
10241
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
10242
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
10243
10244
    simdjson_inline void store(T ptr[64]) const {
10245
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
10246
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
10247
      this->chunks[2].store(ptr+sizeof(simd8<T>)*2);
10248
      this->chunks[3].store(ptr+sizeof(simd8<T>)*3);
10249
    }
10250
10251
    simdjson_inline simd8<T> reduce_or() const {
10252
      return (this->chunks[0] | this->chunks[1]) | (this->chunks[2] | this->chunks[3]);
10253
    }
10254
10255
10256
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
10257
      uint64_t popcounts = vget_lane_u64(vreinterpret_u64_u8(vcnt_u8(vcreate_u8(~mask))), 0);
10258
      // compute the prefix sum of the popcounts of each byte
10259
      uint64_t offsets = popcounts * 0x0101010101010101;
10260
      this->chunks[0].compress_halves(uint16_t(mask), output, &output[popcounts & 0xFF]);
10261
      this->chunks[1].compress_halves(uint16_t(mask >> 16), &output[(offsets >> 8) & 0xFF], &output[(offsets >> 16) & 0xFF]);
10262
      this->chunks[2].compress_halves(uint16_t(mask >> 32), &output[(offsets >> 24) & 0xFF], &output[(offsets >> 32) & 0xFF]);
10263
      this->chunks[3].compress_halves(uint16_t(mask >> 48), &output[(offsets >> 40) & 0xFF], &output[(offsets >> 48) & 0xFF]);
10264
      return offsets >> 56;
10265
    }
10266
10267
    simdjson_inline uint64_t to_bitmask() const {
10268
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
10269
      const uint8x16_t bit_mask = simdjson_make_uint8x16_t(
10270
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
10271
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
10272
      );
10273
#else
10274
      const uint8x16_t bit_mask = {
10275
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
10276
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
10277
      };
10278
#endif
10279
      // Add each of the elements next to each other, successively, to stuff each 8 byte mask into one.
10280
      uint8x16_t sum0 = vpaddq_u8(this->chunks[0] & bit_mask, this->chunks[1] & bit_mask);
10281
      uint8x16_t sum1 = vpaddq_u8(this->chunks[2] & bit_mask, this->chunks[3] & bit_mask);
10282
      sum0 = vpaddq_u8(sum0, sum1);
10283
      sum0 = vpaddq_u8(sum0, sum0);
10284
      return vgetq_lane_u64(vreinterpretq_u64_u8(sum0), 0);
10285
    }
10286
10287
    simdjson_inline uint64_t eq(const T m) const {
10288
      const simd8<T> mask = simd8<T>::splat(m);
10289
      return  simd8x64<bool>(
10290
        this->chunks[0] == mask,
10291
        this->chunks[1] == mask,
10292
        this->chunks[2] == mask,
10293
        this->chunks[3] == mask
10294
      ).to_bitmask();
10295
    }
10296
10297
    simdjson_inline uint64_t lteq(const T m) const {
10298
      const simd8<T> mask = simd8<T>::splat(m);
10299
      return  simd8x64<bool>(
10300
        this->chunks[0] <= mask,
10301
        this->chunks[1] <= mask,
10302
        this->chunks[2] <= mask,
10303
        this->chunks[3] <= mask
10304
      ).to_bitmask();
10305
    }
10306
  }; // struct simd8x64<T>
10307
10308
} // namespace simd
10309
} // unnamed namespace
10310
} // namespace arm64
10311
} // namespace simdjson
10312
10313
#endif // SIMDJSON_ARM64_SIMD_H
10314
/* end file simdjson/arm64/simd.h */
10315
/* including simdjson/arm64/stringparsing_defs.h: #include "simdjson/arm64/stringparsing_defs.h" */
10316
/* begin file simdjson/arm64/stringparsing_defs.h */
10317
#ifndef SIMDJSON_ARM64_STRINGPARSING_DEFS_H
10318
#define SIMDJSON_ARM64_STRINGPARSING_DEFS_H
10319
10320
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
10321
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
10322
/* amalgamation skipped (editor-only): #include "simdjson/arm64/simd.h" */
10323
/* amalgamation skipped (editor-only): #include "simdjson/arm64/bitmanipulation.h" */
10324
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
10325
10326
namespace simdjson {
10327
namespace arm64 {
10328
namespace {
10329
10330
using namespace simd;
10331
10332
// Holds backslashes and quotes locations.
10333
struct backslash_and_quote {
10334
public:
10335
  static constexpr uint32_t BYTES_PROCESSED = 32;
10336
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
10337
10338
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
10339
  simdjson_inline bool has_backslash() { return bs_bits != 0; }
10340
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
10341
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
10342
10343
  uint32_t bs_bits;
10344
  uint32_t quote_bits;
10345
}; // struct backslash_and_quote
10346
10347
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
10348
  // this can read up to 31 bytes beyond the buffer size, but we require
10349
  // SIMDJSON_PADDING of padding
10350
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
10351
  simd8<uint8_t> v0(src);
10352
  simd8<uint8_t> v1(src + sizeof(v0));
10353
  v0.store(dst);
10354
  v1.store(dst + sizeof(v0));
10355
10356
  // Getting a 64-bit bitmask is much cheaper than multiple 16-bit bitmasks on ARM; therefore, we
10357
  // smash them together into a 64-byte mask and get the bitmask from there.
10358
  uint64_t bs_and_quote = simd8x64<bool>(v0 == '\\', v1 == '\\', v0 == '"', v1 == '"').to_bitmask();
10359
  return {
10360
    uint32_t(bs_and_quote),      // bs_bits
10361
    uint32_t(bs_and_quote >> 32) // quote_bits
10362
  };
10363
}
10364
10365
} // unnamed namespace
10366
} // namespace arm64
10367
} // namespace simdjson
10368
10369
#endif // SIMDJSON_ARM64_STRINGPARSING_DEFS_H
10370
/* end file simdjson/arm64/stringparsing_defs.h */
10371
10372
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
10373
/* end file simdjson/arm64/begin.h */
10374
/* including simdjson/generic/amalgamated.h for arm64: #include "simdjson/generic/amalgamated.h" */
10375
/* begin file simdjson/generic/amalgamated.h for arm64 */
10376
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
10377
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
10378
#endif
10379
10380
/* including simdjson/generic/base.h for arm64: #include "simdjson/generic/base.h" */
10381
/* begin file simdjson/generic/base.h for arm64 */
10382
#ifndef SIMDJSON_GENERIC_BASE_H
10383
10384
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
10385
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_BASE_H */
10386
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
10387
/* amalgamation skipped (editor-only): // If we haven't got an implementation yet, we're in the editor, editing a generic file! Just */
10388
/* amalgamation skipped (editor-only): // use the most advanced one we can so the most possible stuff can be tested. */
10389
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_IMPLEMENTATION */
10390
/* amalgamation skipped (editor-only): #include "simdjson/implementation_detection.h" */
10391
/* amalgamation skipped (editor-only): #if SIMDJSON_IMPLEMENTATION_ICELAKE */
10392
/* amalgamation skipped (editor-only): #include "simdjson/icelake/begin.h" */
10393
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_HASWELL */
10394
/* amalgamation skipped (editor-only): #include "simdjson/haswell/begin.h" */
10395
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_WESTMERE */
10396
/* amalgamation skipped (editor-only): #include "simdjson/westmere/begin.h" */
10397
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_ARM64 */
10398
/* amalgamation skipped (editor-only): #include "simdjson/arm64/begin.h" */
10399
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_PPC64 */
10400
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/begin.h" */
10401
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_FALLBACK */
10402
/* amalgamation skipped (editor-only): #include "simdjson/fallback/begin.h" */
10403
/* amalgamation skipped (editor-only): #else */
10404
/* amalgamation skipped (editor-only): #error "All possible implementations (including fallback) have been disabled! simdjson will not run." */
10405
/* amalgamation skipped (editor-only): #endif */
10406
/* amalgamation skipped (editor-only): #endif // SIMDJSON_IMPLEMENTATION */
10407
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
10408
10409
namespace simdjson {
10410
namespace arm64 {
10411
10412
struct open_container;
10413
class dom_parser_implementation;
10414
10415
/**
10416
 * The type of a JSON number
10417
 */
10418
enum class number_type {
10419
    floating_point_number=1, /// a binary64 number
10420
    signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
10421
    unsigned_integer,        /// a positive integer larger or equal to 1<<63
10422
    big_integer              /// a big integer that does not fit in a 64-bit word
10423
};
10424
10425
} // namespace arm64
10426
} // namespace simdjson
10427
10428
#endif // SIMDJSON_GENERIC_BASE_H
10429
/* end file simdjson/generic/base.h for arm64 */
10430
/* including simdjson/generic/jsoncharutils.h for arm64: #include "simdjson/generic/jsoncharutils.h" */
10431
/* begin file simdjson/generic/jsoncharutils.h for arm64 */
10432
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
10433
10434
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
10435
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_JSONCHARUTILS_H */
10436
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
10437
/* amalgamation skipped (editor-only): #include "simdjson/internal/jsoncharutils_tables.h" */
10438
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
10439
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
10440
10441
namespace simdjson {
10442
namespace arm64 {
10443
namespace {
10444
namespace jsoncharutils {
10445
10446
// return non-zero if not a structural or whitespace char
10447
// zero otherwise
10448
simdjson_inline uint32_t is_not_structural_or_whitespace(uint8_t c) {
10449
  return internal::structural_or_whitespace_negated[c];
10450
}
10451
10452
simdjson_inline uint32_t is_structural_or_whitespace(uint8_t c) {
10453
  return internal::structural_or_whitespace[c];
10454
}
10455
10456
// returns a value with the high 16 bits set if not valid
10457
// otherwise returns the conversion of the 4 hex digits at src into the bottom
10458
// 16 bits of the 32-bit return register
10459
//
10460
// see
10461
// https://lemire.me/blog/2019/04/17/parsing-short-hexadecimal-strings-efficiently/
10462
static inline uint32_t hex_to_u32_nocheck(
10463
    const uint8_t *src) { // strictly speaking, static inline is a C-ism
10464
  uint32_t v1 = internal::digit_to_val32[630 + src[0]];
10465
  uint32_t v2 = internal::digit_to_val32[420 + src[1]];
10466
  uint32_t v3 = internal::digit_to_val32[210 + src[2]];
10467
  uint32_t v4 = internal::digit_to_val32[0 + src[3]];
10468
  return v1 | v2 | v3 | v4;
10469
}
10470
10471
// given a code point cp, writes to c
10472
// the utf-8 code, outputting the length in
10473
// bytes, if the length is zero, the code point
10474
// is invalid
10475
//
10476
// This can possibly be made faster using pdep
10477
// and clz and table lookups, but JSON documents
10478
// have few escaped code points, and the following
10479
// function looks cheap.
10480
//
10481
// Note: we assume that surrogates are treated separately
10482
//
10483
simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
10484
  if (cp <= 0x7F) {
10485
    c[0] = uint8_t(cp);
10486
    return 1; // ascii
10487
  }
10488
  if (cp <= 0x7FF) {
10489
    c[0] = uint8_t((cp >> 6) + 192);
10490
    c[1] = uint8_t((cp & 63) + 128);
10491
    return 2; // universal plane
10492
    //  Surrogates are treated elsewhere...
10493
    //} //else if (0xd800 <= cp && cp <= 0xdfff) {
10494
    //  return 0; // surrogates // could put assert here
10495
  } else if (cp <= 0xFFFF) {
10496
    c[0] = uint8_t((cp >> 12) + 224);
10497
    c[1] = uint8_t(((cp >> 6) & 63) + 128);
10498
    c[2] = uint8_t((cp & 63) + 128);
10499
    return 3;
10500
  } else if (cp <= 0x10FFFF) { // if you know you have a valid code point, this
10501
                               // is not needed
10502
    c[0] = uint8_t((cp >> 18) + 240);
10503
    c[1] = uint8_t(((cp >> 12) & 63) + 128);
10504
    c[2] = uint8_t(((cp >> 6) & 63) + 128);
10505
    c[3] = uint8_t((cp & 63) + 128);
10506
    return 4;
10507
  }
10508
  // will return 0 when the code point was too large.
10509
  return 0; // bad r
10510
}
10511
10512
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
10513
// this is a slow emulation routine for 32-bit
10514
//
10515
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
10516
  return x * (uint64_t)y;
10517
}
10518
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
10519
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
10520
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
10521
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
10522
  uint64_t adbc_carry = !!(adbc < ad);
10523
  uint64_t lo = bd + (adbc << 32);
10524
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
10525
        (adbc_carry << 32) + !!(lo < bd);
10526
  return lo;
10527
}
10528
#endif
10529
10530
} // namespace jsoncharutils
10531
} // unnamed namespace
10532
} // namespace arm64
10533
} // namespace simdjson
10534
10535
#endif // SIMDJSON_GENERIC_JSONCHARUTILS_H
10536
/* end file simdjson/generic/jsoncharutils.h for arm64 */
10537
/* including simdjson/generic/atomparsing.h for arm64: #include "simdjson/generic/atomparsing.h" */
10538
/* begin file simdjson/generic/atomparsing.h for arm64 */
10539
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
10540
10541
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
10542
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ATOMPARSING_H */
10543
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
10544
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
10545
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
10546
10547
#include <cstring>
10548
10549
namespace simdjson {
10550
namespace arm64 {
10551
namespace {
10552
/// @private
10553
namespace atomparsing {
10554
10555
// The string_to_uint32 is exclusively used to map literal strings to 32-bit values.
10556
// We use memcpy instead of a pointer cast to avoid undefined behaviors since we cannot
10557
// be certain that the character pointer will be properly aligned.
10558
// You might think that using memcpy makes this function expensive, but you'd be wrong.
10559
// All decent optimizing compilers (GCC, clang, Visual Studio) will compile string_to_uint32("false");
10560
// to the compile-time constant 1936482662.
10561
simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(&val, str, sizeof(uint32_t)); return val; }
10562
10563
10564
// Again in str4ncmp we use a memcpy to avoid undefined behavior. The memcpy may appear expensive.
10565
// Yet all decent optimizing compilers will compile memcpy to a single instruction, just about.
10566
simdjson_warn_unused
10567
simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) {
10568
  uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++)
10569
  static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes");
10570
  std::memcpy(&srcval, src, sizeof(uint32_t));
10571
  return srcval ^ string_to_uint32(atom);
10572
}
10573
10574
simdjson_warn_unused
10575
simdjson_inline bool is_valid_true_atom(const uint8_t *src) {
10576
  return (str4ncmp(src, "true") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
10577
}
10578
10579
simdjson_warn_unused
10580
simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) {
10581
  if (len > 4) { return is_valid_true_atom(src); }
10582
  else if (len == 4) { return !str4ncmp(src, "true"); }
10583
  else { return false; }
10584
}
10585
10586
simdjson_warn_unused
10587
simdjson_inline bool is_valid_false_atom(const uint8_t *src) {
10588
  return (str4ncmp(src+1, "alse") | jsoncharutils::is_not_structural_or_whitespace(src[5])) == 0;
10589
}
10590
10591
simdjson_warn_unused
10592
simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) {
10593
  if (len > 5) { return is_valid_false_atom(src); }
10594
  else if (len == 5) { return !str4ncmp(src+1, "alse"); }
10595
  else { return false; }
10596
}
10597
10598
simdjson_warn_unused
10599
simdjson_inline bool is_valid_null_atom(const uint8_t *src) {
10600
  return (str4ncmp(src, "null") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
10601
}
10602
10603
simdjson_warn_unused
10604
simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
10605
  if (len > 4) { return is_valid_null_atom(src); }
10606
  else if (len == 4) { return !str4ncmp(src, "null"); }
10607
  else { return false; }
10608
}
10609
10610
} // namespace atomparsing
10611
} // unnamed namespace
10612
} // namespace arm64
10613
} // namespace simdjson
10614
10615
#endif // SIMDJSON_GENERIC_ATOMPARSING_H
10616
/* end file simdjson/generic/atomparsing.h for arm64 */
10617
/* including simdjson/generic/dom_parser_implementation.h for arm64: #include "simdjson/generic/dom_parser_implementation.h" */
10618
/* begin file simdjson/generic/dom_parser_implementation.h for arm64 */
10619
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
10620
10621
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
10622
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H */
10623
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
10624
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
10625
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
10626
10627
namespace simdjson {
10628
namespace arm64 {
10629
10630
// expectation: sizeof(open_container) = 64/8.
10631
struct open_container {
10632
  uint32_t tape_index; // where, on the tape, does the scope ([,{) begins
10633
  uint32_t count; // how many elements in the scope
10634
}; // struct open_container
10635
10636
static_assert(sizeof(open_container) == 64/8, "Open container must be 64 bits");
10637
10638
class dom_parser_implementation final : public internal::dom_parser_implementation {
10639
public:
10640
  /** Tape location of each open { or [ */
10641
  std::unique_ptr<open_container[]> open_containers{};
10642
  /** Whether each open container is a [ or { */
10643
  std::unique_ptr<bool[]> is_array{};
10644
  /** Buffer passed to stage 1 */
10645
  const uint8_t *buf{};
10646
  /** Length passed to stage 1 */
10647
  size_t len{0};
10648
  /** Document passed to stage 2 */
10649
  dom::document *doc{};
10650
10651
  inline dom_parser_implementation() noexcept;
10652
  inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
10653
  inline dom_parser_implementation &operator=(dom_parser_implementation &&other) noexcept;
10654
  dom_parser_implementation(const dom_parser_implementation &) = delete;
10655
  dom_parser_implementation &operator=(const dom_parser_implementation &) = delete;
10656
10657
  simdjson_warn_unused error_code parse(const uint8_t *buf, size_t len, dom::document &doc) noexcept final;
10658
  simdjson_warn_unused error_code stage1(const uint8_t *buf, size_t len, stage1_mode partial) noexcept final;
10659
  simdjson_warn_unused error_code stage2(dom::document &doc) noexcept final;
10660
  simdjson_warn_unused error_code stage2_next(dom::document &doc) noexcept final;
10661
  simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept final;
10662
  simdjson_warn_unused uint8_t *parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept final;
10663
  inline simdjson_warn_unused error_code set_capacity(size_t capacity) noexcept final;
10664
  inline simdjson_warn_unused error_code set_max_depth(size_t max_depth) noexcept final;
10665
private:
10666
  simdjson_inline simdjson_warn_unused error_code set_capacity_stage1(size_t capacity);
10667
10668
};
10669
10670
} // namespace arm64
10671
} // namespace simdjson
10672
10673
namespace simdjson {
10674
namespace arm64 {
10675
10676
inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
10677
inline dom_parser_implementation::dom_parser_implementation(dom_parser_implementation &&other) noexcept = default;
10678
inline dom_parser_implementation &dom_parser_implementation::operator=(dom_parser_implementation &&other) noexcept = default;
10679
10680
// Leaving these here so they can be inlined if so desired
10681
inline simdjson_warn_unused error_code dom_parser_implementation::set_capacity(size_t capacity) noexcept {
10682
  if(capacity > SIMDJSON_MAXSIZE_BYTES) { return CAPACITY; }
10683
  // Stage 1 index output
10684
  size_t max_structures = SIMDJSON_ROUNDUP_N(capacity, 64) + 2 + 7;
10685
  structural_indexes.reset( new (std::nothrow) uint32_t[max_structures] );
10686
  if (!structural_indexes) { _capacity = 0; return MEMALLOC; }
10687
  structural_indexes[0] = 0;
10688
  n_structural_indexes = 0;
10689
10690
  _capacity = capacity;
10691
  return SUCCESS;
10692
}
10693
10694
inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(size_t max_depth) noexcept {
10695
  // Stage 2 stacks
10696
  open_containers.reset(new (std::nothrow) open_container[max_depth]);
10697
  is_array.reset(new (std::nothrow) bool[max_depth]);
10698
  if (!is_array || !open_containers) { _max_depth = 0; return MEMALLOC; }
10699
10700
  _max_depth = max_depth;
10701
  return SUCCESS;
10702
}
10703
10704
} // namespace arm64
10705
} // namespace simdjson
10706
10707
#endif // SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
10708
/* end file simdjson/generic/dom_parser_implementation.h for arm64 */
10709
/* including simdjson/generic/implementation_simdjson_result_base.h for arm64: #include "simdjson/generic/implementation_simdjson_result_base.h" */
10710
/* begin file simdjson/generic/implementation_simdjson_result_base.h for arm64 */
10711
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
10712
10713
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
10714
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H */
10715
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
10716
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
10717
10718
namespace simdjson {
10719
namespace arm64 {
10720
10721
// This is a near copy of include/error.h's implementation_simdjson_result_base, except it doesn't use std::pair
10722
// so we can avoid inlining errors
10723
// TODO reconcile these!
10724
/**
10725
 * The result of a simdjson operation that could fail.
10726
 *
10727
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
10728
 *
10729
 * This is a base class for implementations that want to add functions to the result type for
10730
 * chaining.
10731
 *
10732
 * Override like:
10733
 *
10734
 *   struct simdjson_result<T> : public internal::implementation_simdjson_result_base<T> {
10735
 *     simdjson_result() noexcept : internal::implementation_simdjson_result_base<T>() {}
10736
 *     simdjson_result(error_code error) noexcept : internal::implementation_simdjson_result_base<T>(error) {}
10737
 *     simdjson_result(T &&value) noexcept : internal::implementation_simdjson_result_base<T>(std::forward(value)) {}
10738
 *     simdjson_result(T &&value, error_code error) noexcept : internal::implementation_simdjson_result_base<T>(value, error) {}
10739
 *     // Your extra methods here
10740
 *   }
10741
 *
10742
 * Then any method returning simdjson_result<T> will be chainable with your methods.
10743
 */
10744
template<typename T>
10745
struct implementation_simdjson_result_base {
10746
10747
  /**
10748
   * Create a new empty result with error = UNINITIALIZED.
10749
   */
10750
  simdjson_inline implementation_simdjson_result_base() noexcept = default;
10751
10752
  /**
10753
   * Create a new error result.
10754
   */
10755
  simdjson_inline implementation_simdjson_result_base(error_code error) noexcept;
10756
10757
  /**
10758
   * Create a new successful result.
10759
   */
10760
  simdjson_inline implementation_simdjson_result_base(T &&value) noexcept;
10761
10762
  /**
10763
   * Create a new result with both things (use if you don't want to branch when creating the result).
10764
   */
10765
  simdjson_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
10766
10767
  /**
10768
   * Move the value and the error to the provided variables.
10769
   *
10770
   * @param value The variable to assign the value to. May not be set if there is an error.
10771
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
10772
   */
10773
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
10774
10775
  /**
10776
   * Move the value to the provided variable.
10777
   *
10778
   * @param value The variable to assign the value to. May not be set if there is an error.
10779
   */
10780
  simdjson_inline error_code get(T &value) && noexcept;
10781
10782
  /**
10783
   * The error.
10784
   */
10785
  simdjson_inline error_code error() const noexcept;
10786
10787
#if SIMDJSON_EXCEPTIONS
10788
10789
  /**
10790
   * Get the result value.
10791
   *
10792
   * @throw simdjson_error if there was an error.
10793
   */
10794
  simdjson_inline T& value() & noexcept(false);
10795
10796
  /**
10797
   * Take the result value (move it).
10798
   *
10799
   * @throw simdjson_error if there was an error.
10800
   */
10801
  simdjson_inline T&& value() && noexcept(false);
10802
10803
  /**
10804
   * Take the result value (move it).
10805
   *
10806
   * @throw simdjson_error if there was an error.
10807
   */
10808
  simdjson_inline T&& take_value() && noexcept(false);
10809
10810
  /**
10811
   * Cast to the value (will throw on error).
10812
   *
10813
   * @throw simdjson_error if there was an error.
10814
   */
10815
  simdjson_inline operator T&&() && noexcept(false);
10816
10817
10818
#endif // SIMDJSON_EXCEPTIONS
10819
10820
  /**
10821
   * Get the result value. This function is safe if and only
10822
   * the error() method returns a value that evaluates to false.
10823
   */
10824
  simdjson_inline const T& value_unsafe() const& noexcept;
10825
  /**
10826
   * Get the result value. This function is safe if and only
10827
   * the error() method returns a value that evaluates to false.
10828
   */
10829
  simdjson_inline T& value_unsafe() & noexcept;
10830
  /**
10831
   * Take the result value (move it). This function is safe if and only
10832
   * the error() method returns a value that evaluates to false.
10833
   */
10834
  simdjson_inline T&& value_unsafe() && noexcept;
10835
protected:
10836
  /** users should never directly access first and second. **/
10837
  T first{}; /** Users should never directly access 'first'. **/
10838
  error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
10839
}; // struct implementation_simdjson_result_base
10840
10841
} // namespace arm64
10842
} // namespace simdjson
10843
10844
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
10845
/* end file simdjson/generic/implementation_simdjson_result_base.h for arm64 */
10846
/* including simdjson/generic/numberparsing.h for arm64: #include "simdjson/generic/numberparsing.h" */
10847
/* begin file simdjson/generic/numberparsing.h for arm64 */
10848
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
10849
10850
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
10851
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_NUMBERPARSING_H */
10852
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
10853
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
10854
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
10855
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
10856
10857
#include <limits>
10858
#include <ostream>
10859
#include <cstring>
10860
10861
namespace simdjson {
10862
namespace arm64 {
10863
namespace numberparsing {
10864
10865
#ifdef JSON_TEST_NUMBERS
10866
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
10867
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
10868
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
10869
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
10870
#define BIGINT_NUMBER(SRC) (found_invalid_number((SRC)), BIGINT_ERROR)
10871
#else
10872
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
10873
#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
10874
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
10875
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
10876
#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
10877
#endif
10878
10879
namespace {
10880
10881
// Convert a mantissa, an exponent and a sign bit into an ieee64 double.
10882
// The real_exponent needs to be in [0, 2046] (technically real_exponent = 2047 would be acceptable).
10883
// The mantissa should be in [0,1<<53). The bit at index (1ULL << 52) while be zeroed.
10884
simdjson_inline double to_double(uint64_t mantissa, uint64_t real_exponent, bool negative) {
10885
    double d;
10886
    mantissa &= ~(1ULL << 52);
10887
    mantissa |= real_exponent << 52;
10888
    mantissa |= ((static_cast<uint64_t>(negative)) << 63);
10889
    std::memcpy(&d, &mantissa, sizeof(d));
10890
    return d;
10891
}
10892
10893
// Attempts to compute i * 10^(power) exactly; and if "negative" is
10894
// true, negate the result.
10895
// This function will only work in some cases, when it does not work, success is
10896
// set to false. This should work *most of the time* (like 99% of the time).
10897
// We assume that power is in the [smallest_power,
10898
// largest_power] interval: the caller is responsible for this check.
10899
simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, double &d) {
10900
  // we start with a fast path
10901
  // It was described in
10902
  // Clinger WD. How to read floating point numbers accurately.
10903
  // ACM SIGPLAN Notices. 1990
10904
#ifndef FLT_EVAL_METHOD
10905
#error "FLT_EVAL_METHOD should be defined, please include cfloat."
10906
#endif
10907
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
10908
  // We cannot be certain that x/y is rounded to nearest.
10909
  if (0 <= power && power <= 22 && i <= 9007199254740991)
10910
#else
10911
  if (-22 <= power && power <= 22 && i <= 9007199254740991)
10912
#endif
10913
  {
10914
    // convert the integer into a double. This is lossless since
10915
    // 0 <= i <= 2^53 - 1.
10916
    d = double(i);
10917
    //
10918
    // The general idea is as follows.
10919
    // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
10920
    // 1) Both s and p can be represented exactly as 64-bit floating-point
10921
    // values
10922
    // (binary64).
10923
    // 2) Because s and p can be represented exactly as floating-point values,
10924
    // then s * p
10925
    // and s / p will produce correctly rounded values.
10926
    //
10927
    if (power < 0) {
10928
      d = d / simdjson::internal::power_of_ten[-power];
10929
    } else {
10930
      d = d * simdjson::internal::power_of_ten[power];
10931
    }
10932
    if (negative) {
10933
      d = -d;
10934
    }
10935
    return true;
10936
  }
10937
  // When 22 < power && power <  22 + 16, we could
10938
  // hope for another, secondary fast path.  It was
10939
  // described by David M. Gay in  "Correctly rounded
10940
  // binary-decimal and decimal-binary conversions." (1990)
10941
  // If you need to compute i * 10^(22 + x) for x < 16,
10942
  // first compute i * 10^x, if you know that result is exact
10943
  // (e.g., when i * 10^x < 2^53),
10944
  // then you can still proceed and do (i * 10^x) * 10^22.
10945
  // Is this worth your time?
10946
  // You need  22 < power *and* power <  22 + 16 *and* (i * 10^(x-22) < 2^53)
10947
  // for this second fast path to work.
10948
  // If you you have 22 < power *and* power <  22 + 16, and then you
10949
  // optimistically compute "i * 10^(x-22)", there is still a chance that you
10950
  // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
10951
  // this optimization maybe less common than we would like. Source:
10952
  // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
10953
  // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
10954
10955
  // The fast path has now failed, so we are failing back on the slower path.
10956
10957
  // In the slow path, we need to adjust i so that it is > 1<<63 which is always
10958
  // possible, except if i == 0, so we handle i == 0 separately.
10959
  if(i == 0) {
10960
    d = negative ? -0.0 : 0.0;
10961
    return true;
10962
  }
10963
10964
10965
  // The exponent is 1024 + 63 + power
10966
  //     + floor(log(5**power)/log(2)).
10967
  // The 1024 comes from the ieee64 standard.
10968
  // The 63 comes from the fact that we use a 64-bit word.
10969
  //
10970
  // Computing floor(log(5**power)/log(2)) could be
10971
  // slow. Instead we use a fast function.
10972
  //
10973
  // For power in (-400,350), we have that
10974
  // (((152170 + 65536) * power ) >> 16);
10975
  // is equal to
10976
  //  floor(log(5**power)/log(2)) + power when power >= 0
10977
  // and it is equal to
10978
  //  ceil(log(5**-power)/log(2)) + power when power < 0
10979
  //
10980
  // The 65536 is (1<<16) and corresponds to
10981
  // (65536 * power) >> 16 ---> power
10982
  //
10983
  // ((152170 * power ) >> 16) is equal to
10984
  // floor(log(5**power)/log(2))
10985
  //
10986
  // Note that this is not magic: 152170/(1<<16) is
10987
  // approximatively equal to log(5)/log(2).
10988
  // The 1<<16 value is a power of two; we could use a
10989
  // larger power of 2 if we wanted to.
10990
  //
10991
  int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
10992
10993
10994
  // We want the most significant bit of i to be 1. Shift if needed.
10995
  int lz = leading_zeroes(i);
10996
  i <<= lz;
10997
10998
10999
  // We are going to need to do some 64-bit arithmetic to get a precise product.
11000
  // We use a table lookup approach.
11001
  // It is safe because
11002
  // power >= smallest_power
11003
  // and power <= largest_power
11004
  // We recover the mantissa of the power, it has a leading 1. It is always
11005
  // rounded down.
11006
  //
11007
  // We want the most significant 64 bits of the product. We know
11008
  // this will be non-zero because the most significant bit of i is
11009
  // 1.
11010
  const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
11011
  // Optimization: It may be that materializing the index as a variable might confuse some compilers and prevent effective complex-addressing loads. (Done for code clarity.)
11012
  //
11013
  // The full_multiplication function computes the 128-bit product of two 64-bit words
11014
  // with a returned value of type value128 with a "low component" corresponding to the
11015
  // 64-bit least significant bits of the product and with a "high component" corresponding
11016
  // to the 64-bit most significant bits of the product.
11017
  simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
11018
  // Both i and power_of_five_128[index] have their most significant bit set to 1 which
11019
  // implies that the either the most or the second most significant bit of the product
11020
  // is 1. We pack values in this manner for efficiency reasons: it maximizes the use
11021
  // we make of the product. It also makes it easy to reason about the product: there
11022
  // is 0 or 1 leading zero in the product.
11023
11024
  // Unless the least significant 9 bits of the high (64-bit) part of the full
11025
  // product are all 1s, then we know that the most significant 55 bits are
11026
  // exact and no further work is needed. Having 55 bits is necessary because
11027
  // we need 53 bits for the mantissa but we have to have one rounding bit and
11028
  // we can waste a bit if the most significant bit of the product is zero.
11029
  if((firstproduct.high & 0x1FF) == 0x1FF) {
11030
    // We want to compute i * 5^q, but only care about the top 55 bits at most.
11031
    // Consider the scenario where q>=0. Then 5^q may not fit in 64-bits. Doing
11032
    // the full computation is wasteful. So we do what is called a "truncated
11033
    // multiplication".
11034
    // We take the most significant 64-bits, and we put them in
11035
    // power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
11036
    // to the desired approximation using one multiplication. Sometimes it does not suffice.
11037
    // Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
11038
    // then we get a better approximation to i * 5^q.
11039
    //
11040
    // That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
11041
    // more complicated.
11042
    //
11043
    // There is an extra layer of complexity in that we need more than 55 bits of
11044
    // accuracy in the round-to-even scenario.
11045
    //
11046
    // The full_multiplication function computes the 128-bit product of two 64-bit words
11047
    // with a returned value of type value128 with a "low component" corresponding to the
11048
    // 64-bit least significant bits of the product and with a "high component" corresponding
11049
    // to the 64-bit most significant bits of the product.
11050
    simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
11051
    firstproduct.low += secondproduct.high;
11052
    if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
11053
    // As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
11054
    // Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
11055
    // is sufficiently accurate, and more computation is not needed.
11056
  }
11057
  uint64_t lower = firstproduct.low;
11058
  uint64_t upper = firstproduct.high;
11059
  // The final mantissa should be 53 bits with a leading 1.
11060
  // We shift it so that it occupies 54 bits with a leading 1.
11061
  ///////
11062
  uint64_t upperbit = upper >> 63;
11063
  uint64_t mantissa = upper >> (upperbit + 9);
11064
  lz += int(1 ^ upperbit);
11065
11066
  // Here we have mantissa < (1<<54).
11067
  int64_t real_exponent = exponent - lz;
11068
  if (simdjson_unlikely(real_exponent <= 0)) { // we have a subnormal?
11069
    // Here have that real_exponent <= 0 so -real_exponent >= 0
11070
    if(-real_exponent + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
11071
      d = negative ? -0.0 : 0.0;
11072
      return true;
11073
    }
11074
    // next line is safe because -real_exponent + 1 < 0
11075
    mantissa >>= -real_exponent + 1;
11076
    // Thankfully, we can't have both "round-to-even" and subnormals because
11077
    // "round-to-even" only occurs for powers close to 0.
11078
    mantissa += (mantissa & 1); // round up
11079
    mantissa >>= 1;
11080
    // There is a weird scenario where we don't have a subnormal but just.
11081
    // Suppose we start with 2.2250738585072013e-308, we end up
11082
    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
11083
    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
11084
    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
11085
    // subnormal, but we can only know this after rounding.
11086
    // So we only declare a subnormal if we are smaller than the threshold.
11087
    real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
11088
    d = to_double(mantissa, real_exponent, negative);
11089
    return true;
11090
  }
11091
  // We have to round to even. The "to even" part
11092
  // is only a problem when we are right in between two floats
11093
  // which we guard against.
11094
  // If we have lots of trailing zeros, we may fall right between two
11095
  // floating-point values.
11096
  //
11097
  // The round-to-even cases take the form of a number 2m+1 which is in (2^53,2^54]
11098
  // times a power of two. That is, it is right between a number with binary significand
11099
  // m and another number with binary significand m+1; and it must be the case
11100
  // that it cannot be represented by a float itself.
11101
  //
11102
  // We must have that w * 10 ^q == (2m+1) * 2^p for some power of two 2^p.
11103
  // Recall that 10^q = 5^q * 2^q.
11104
  // When q >= 0, we must have that (2m+1) is divible by 5^q, so 5^q <= 2^54. We have that
11105
  //  5^23 <=  2^54 and it is the last power of five to qualify, so q <= 23.
11106
  // When q<0, we have  w  >=  (2m+1) x 5^{-q}.  We must have that w<2^{64} so
11107
  // (2m+1) x 5^{-q} < 2^{64}. We have that 2m+1>2^{53}. Hence, we must have
11108
  // 2^{53} x 5^{-q} < 2^{64}.
11109
  // Hence we have 5^{-q} < 2^{11}$ or q>= -4.
11110
  //
11111
  // We require lower <= 1 and not lower == 0 because we could not prove that
11112
  // that lower == 0 is implied; but we could prove that lower <= 1 is a necessary and sufficient test.
11113
  if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
11114
    if((mantissa  << (upperbit + 64 - 53 - 2)) ==  upper) {
11115
      mantissa &= ~1;             // flip it so that we do not round up
11116
    }
11117
  }
11118
11119
  mantissa += mantissa & 1;
11120
  mantissa >>= 1;
11121
11122
  // Here we have mantissa < (1<<53), unless there was an overflow
11123
  if (mantissa >= (1ULL << 53)) {
11124
    //////////
11125
    // This will happen when parsing values such as 7.2057594037927933e+16
11126
    ////////
11127
    mantissa = (1ULL << 52);
11128
    real_exponent++;
11129
  }
11130
  mantissa &= ~(1ULL << 52);
11131
  // we have to check that real_exponent is in range, otherwise we bail out
11132
  if (simdjson_unlikely(real_exponent > 2046)) {
11133
    // We have an infinite value!!! We could actually throw an error here if we could.
11134
    return false;
11135
  }
11136
  d = to_double(mantissa, real_exponent, negative);
11137
  return true;
11138
}
11139
11140
// We call a fallback floating-point parser that might be slow. Note
11141
// it will accept JSON numbers, but the JSON spec. is more restrictive so
11142
// before you call parse_float_fallback, you need to have validated the input
11143
// string with the JSON grammar.
11144
// It will return an error (false) if the parsed number is infinite.
11145
// The string parsing itself always succeeds. We know that there is at least
11146
// one digit.
11147
static bool parse_float_fallback(const uint8_t *ptr, double *outDouble) {
11148
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr));
11149
  // We do not accept infinite values.
11150
11151
  // Detecting finite values in a portable manner is ridiculously hard, ideally
11152
  // we would want to do:
11153
  // return !std::isfinite(*outDouble);
11154
  // but that mysteriously fails under legacy/old libc++ libraries, see
11155
  // https://github.com/simdjson/simdjson/issues/1286
11156
  //
11157
  // Therefore, fall back to this solution (the extra parens are there
11158
  // to handle that max may be a macro on windows).
11159
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
11160
}
11161
11162
static bool parse_float_fallback(const uint8_t *ptr, const uint8_t *end_ptr, double *outDouble) {
11163
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr), reinterpret_cast<const char *>(end_ptr));
11164
  // We do not accept infinite values.
11165
11166
  // Detecting finite values in a portable manner is ridiculously hard, ideally
11167
  // we would want to do:
11168
  // return !std::isfinite(*outDouble);
11169
  // but that mysteriously fails under legacy/old libc++ libraries, see
11170
  // https://github.com/simdjson/simdjson/issues/1286
11171
  //
11172
  // Therefore, fall back to this solution (the extra parens are there
11173
  // to handle that max may be a macro on windows).
11174
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
11175
}
11176
11177
// check quickly whether the next 8 chars are made of digits
11178
// at a glance, it looks better than Mula's
11179
// http://0x80.pl/articles/swar-digits-validate.html
11180
simdjson_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
11181
  uint64_t val;
11182
  // this can read up to 7 bytes beyond the buffer size, but we require
11183
  // SIMDJSON_PADDING of padding
11184
  static_assert(7 <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be bigger than 7");
11185
  std::memcpy(&val, chars, 8);
11186
  // a branchy method might be faster:
11187
  // return (( val & 0xF0F0F0F0F0F0F0F0 ) == 0x3030303030303030)
11188
  //  && (( (val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0 ) ==
11189
  //  0x3030303030303030);
11190
  return (((val & 0xF0F0F0F0F0F0F0F0) |
11191
           (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
11192
          0x3333333333333333);
11193
}
11194
11195
template<typename I>
11196
SIMDJSON_NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
11197
simdjson_inline bool parse_digit(const uint8_t c, I &i) {
11198
  const uint8_t digit = static_cast<uint8_t>(c - '0');
11199
  if (digit > 9) {
11200
    return false;
11201
  }
11202
  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
11203
  i = 10 * i + digit; // might overflow, we will handle the overflow later
11204
  return true;
11205
}
11206
11207
simdjson_inline bool is_digit(const uint8_t c) {
11208
  return static_cast<uint8_t>(c - '0') <= 9;
11209
}
11210
11211
simdjson_inline error_code parse_decimal_after_separator(simdjson_unused const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
11212
  // we continue with the fiction that we have an integer. If the
11213
  // floating point number is representable as x * 10^z for some integer
11214
  // z that fits in 53 bits, then we will be able to convert back the
11215
  // the integer into a float in a lossless manner.
11216
  const uint8_t *const first_after_period = p;
11217
11218
#ifdef SIMDJSON_SWAR_NUMBER_PARSING
11219
#if SIMDJSON_SWAR_NUMBER_PARSING
11220
  // this helps if we have lots of decimals!
11221
  // this turns out to be frequent enough.
11222
  if (is_made_of_eight_digits_fast(p)) {
11223
    i = i * 100000000 + parse_eight_digits_unrolled(p);
11224
    p += 8;
11225
  }
11226
#endif // SIMDJSON_SWAR_NUMBER_PARSING
11227
#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
11228
  // Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
11229
  if (parse_digit(*p, i)) { ++p; }
11230
  while (parse_digit(*p, i)) { p++; }
11231
  exponent = first_after_period - p;
11232
  // Decimal without digits (123.) is illegal
11233
  if (exponent == 0) {
11234
    return INVALID_NUMBER(src);
11235
  }
11236
  return SUCCESS;
11237
}
11238
11239
simdjson_inline error_code parse_exponent(simdjson_unused const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
11240
  // Exp Sign: -123.456e[-]78
11241
  bool neg_exp = ('-' == *p);
11242
  if (neg_exp || '+' == *p) { p++; } // Skip + as well
11243
11244
  // Exponent: -123.456e-[78]
11245
  auto start_exp = p;
11246
  int64_t exp_number = 0;
11247
  while (parse_digit(*p, exp_number)) { ++p; }
11248
  // It is possible for parse_digit to overflow.
11249
  // In particular, it could overflow to INT64_MIN, and we cannot do - INT64_MIN.
11250
  // Thus we *must* check for possible overflow before we negate exp_number.
11251
11252
  // Performance notes: it may seem like combining the two "simdjson_unlikely checks" below into
11253
  // a single simdjson_unlikely path would be faster. The reasoning is sound, but the compiler may
11254
  // not oblige and may, in fact, generate two distinct paths in any case. It might be
11255
  // possible to do uint64_t(p - start_exp - 1) >= 18 but it could end up trading off
11256
  // instructions for a simdjson_likely branch, an unconclusive gain.
11257
11258
  // If there were no digits, it's an error.
11259
  if (simdjson_unlikely(p == start_exp)) {
11260
    return INVALID_NUMBER(src);
11261
  }
11262
  // We have a valid positive exponent in exp_number at this point, except that
11263
  // it may have overflowed.
11264
11265
  // If there were more than 18 digits, we may have overflowed the integer. We have to do
11266
  // something!!!!
11267
  if (simdjson_unlikely(p > start_exp+18)) {
11268
    // Skip leading zeroes: 1e000000000000000000001 is technically valid and does not overflow
11269
    while (*start_exp == '0') { start_exp++; }
11270
    // 19 digits could overflow int64_t and is kind of absurd anyway. We don't
11271
    // support exponents smaller than -999,999,999,999,999,999 and bigger
11272
    // than 999,999,999,999,999,999.
11273
    // We can truncate.
11274
    // Note that 999999999999999999 is assuredly too large. The maximal ieee64 value before
11275
    // infinity is ~1.8e308. The smallest subnormal is ~5e-324. So, actually, we could
11276
    // truncate at 324.
11277
    // Note that there is no reason to fail per se at this point in time.
11278
    // E.g., 0e999999999999999999999 is a fine number.
11279
    if (p > start_exp+18) { exp_number = 999999999999999999; }
11280
  }
11281
  // At this point, we know that exp_number is a sane, positive, signed integer.
11282
  // It is <= 999,999,999,999,999,999. As long as 'exponent' is in
11283
  // [-8223372036854775808, 8223372036854775808], we won't overflow. Because 'exponent'
11284
  // is bounded in magnitude by the size of the JSON input, we are fine in this universe.
11285
  // To sum it up: the next line should never overflow.
11286
  exponent += (neg_exp ? -exp_number : exp_number);
11287
  return SUCCESS;
11288
}
11289
11290
simdjson_inline bool check_if_integer(const uint8_t *const src, size_t max_length) {
11291
  const uint8_t *const srcend = src + max_length;
11292
  bool negative = (*src == '-'); // we can always read at least one character after the '-'
11293
  const uint8_t *p = src + uint8_t(negative);
11294
  if(p == srcend) { return false; }
11295
  if(*p == '0') {
11296
    ++p;
11297
    if(p == srcend) { return true; }
11298
    if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
11299
    return true;
11300
  }
11301
  while(p != srcend && is_digit(*p)) { ++p; }
11302
  if(p == srcend) { return true; }
11303
  if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
11304
  return true;
11305
}
11306
11307
simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
11308
  // It is possible that the integer had an overflow.
11309
  // We have to handle the case where we have 0.0000somenumber.
11310
  const uint8_t *start = start_digits;
11311
  while ((*start == '0') || (*start == '.')) { ++start; }
11312
  // we over-decrement by one when there is a '.'
11313
  return digit_count - size_t(start - start_digits);
11314
}
11315
11316
} // unnamed namespace
11317
11318
/** @private */
11319
static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
11320
  if (parse_float_fallback(src, answer)) {
11321
    return SUCCESS;
11322
  }
11323
  return INVALID_NUMBER(src);
11324
}
11325
11326
/** @private */
11327
template<typename W>
11328
simdjson_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
11329
  // If we frequently had to deal with long strings of digits,
11330
  // we could extend our code by using a 128-bit integer instead
11331
  // of a 64-bit integer. However, this is uncommon in practice.
11332
  //
11333
  // 9999999999999999999 < 2**64 so we can accommodate 19 digits.
11334
  // If we have a decimal separator, then digit_count - 1 is the number of digits, but we
11335
  // may not have a decimal separator!
11336
  if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
11337
    // Ok, chances are good that we had an overflow!
11338
    // this is almost never going to get called!!!
11339
    // we start anew, going slowly!!!
11340
    // This will happen in the following examples:
11341
    // 10000000000000000000000000000000000000000000e+308
11342
    // 3.1415926535897932384626433832795028841971693993751
11343
    //
11344
    // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
11345
    // reference to it, it would force it to be stored in memory, preventing the compiler from
11346
    // picking it apart and putting into registers. i.e. if we pass it as reference,
11347
    // it gets slow.
11348
    double d;
11349
    error_code error = slow_float_parsing(src, &d);
11350
    writer.append_double(d);
11351
    return error;
11352
  }
11353
  // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
11354
  // way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331
11355
  // To future reader: we'd love if someone found a better way, or at least could explain this result!
11356
  if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
11357
    //
11358
    // Important: smallest_power is such that it leads to a zero value.
11359
    // Observe that 18446744073709551615e-343 == 0, i.e. (2**64 - 1) e -343 is zero
11360
    // so something x 10^-343 goes to zero, but not so with  something x 10^-342.
11361
    static_assert(simdjson::internal::smallest_power <= -342, "smallest_power is not small enough");
11362
    //
11363
    if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
11364
      // E.g. Parse "-0.0e-999" into the same value as "-0.0". See https://en.wikipedia.org/wiki/Signed_zero
11365
      WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
11366
      return SUCCESS;
11367
    } else { // (exponent > largest_power) and (i != 0)
11368
      // We have, for sure, an infinite value and simdjson refuses to parse infinite values.
11369
      return INVALID_NUMBER(src);
11370
    }
11371
  }
11372
  double d;
11373
  if (!compute_float_64(exponent, i, negative, d)) {
11374
    // we are almost never going to get here.
11375
    if (!parse_float_fallback(src, &d)) { return INVALID_NUMBER(src); }
11376
  }
11377
  WRITE_DOUBLE(d, src, writer);
11378
  return SUCCESS;
11379
}
11380
11381
// parse the number at src
11382
// define JSON_TEST_NUMBERS for unit testing
11383
//
11384
// It is assumed that the number is followed by a structural ({,},],[) character
11385
// or a white space character. If that is not the case (e.g., when the JSON
11386
// document is made of a single number), then it is necessary to copy the
11387
// content and append a space before calling this function.
11388
//
11389
// Our objective is accurate parsing (ULP of 0) at high speed.
11390
template<typename W>
11391
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer);
11392
11393
// for performance analysis, it is sometimes  useful to skip parsing
11394
#ifdef SIMDJSON_SKIPNUMBERPARSING
11395
11396
template<typename W>
11397
simdjson_inline error_code parse_number(const uint8_t *const, W &writer) {
11398
  writer.append_s64(0);        // always write zero
11399
  return SUCCESS;              // always succeeds
11400
}
11401
11402
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
11403
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
11404
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
11405
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept { return 0; }
11406
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t * const src) noexcept { return 0; }
11407
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * const src) noexcept { return 0; }
11408
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept  { return false; }
11409
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept  { return false; }
11410
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept { return number_type::signed_integer; }
11411
#else
11412
11413
// parse the number at src
11414
// define JSON_TEST_NUMBERS for unit testing
11415
//
11416
// It is assumed that the number is followed by a structural ({,},],[) character
11417
// or a white space character. If that is not the case (e.g., when the JSON
11418
// document is made of a single number), then it is necessary to copy the
11419
// content and append a space before calling this function.
11420
//
11421
// Our objective is accurate parsing (ULP of 0) at high speed.
11422
template<typename W>
11423
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) {
11424
11425
  //
11426
  // Check for minus sign
11427
  //
11428
  bool negative = (*src == '-');
11429
  const uint8_t *p = src + uint8_t(negative);
11430
11431
  //
11432
  // Parse the integer part.
11433
  //
11434
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
11435
  const uint8_t *const start_digits = p;
11436
  uint64_t i = 0;
11437
  while (parse_digit(*p, i)) { p++; }
11438
11439
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
11440
  // Optimization note: size_t is expected to be unsigned.
11441
  size_t digit_count = size_t(p - start_digits);
11442
  if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
11443
11444
  //
11445
  // Handle floats if there is a . or e (or both)
11446
  //
11447
  int64_t exponent = 0;
11448
  bool is_float = false;
11449
  if ('.' == *p) {
11450
    is_float = true;
11451
    ++p;
11452
    SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
11453
    digit_count = int(p - start_digits); // used later to guard against overflows
11454
  }
11455
  if (('e' == *p) || ('E' == *p)) {
11456
    is_float = true;
11457
    ++p;
11458
    SIMDJSON_TRY( parse_exponent(src, p, exponent) );
11459
  }
11460
  if (is_float) {
11461
    const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
11462
    SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
11463
    if (dirty_end) { return INVALID_NUMBER(src); }
11464
    return SUCCESS;
11465
  }
11466
11467
  // The longest negative 64-bit number is 19 digits.
11468
  // The longest positive 64-bit number is 20 digits.
11469
  // We do it this way so we don't trigger this branch unless we must.
11470
  size_t longest_digit_count = negative ? 19 : 20;
11471
  if (digit_count > longest_digit_count) { return BIGINT_NUMBER(src); }
11472
  if (digit_count == longest_digit_count) {
11473
    if (negative) {
11474
      // Anything negative above INT64_MAX+1 is invalid
11475
      if (i > uint64_t(INT64_MAX)+1) { return BIGINT_NUMBER(src);  }
11476
      WRITE_INTEGER(~i+1, src, writer);
11477
      if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
11478
      return SUCCESS;
11479
    // Positive overflow check:
11480
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
11481
    //   biggest uint64_t.
11482
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
11483
    //   If we got here, it's a 20 digit number starting with the digit "1".
11484
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
11485
    //   than 1,553,255,926,290,448,384.
11486
    // - That is smaller than the smallest possible 20-digit number the user could write:
11487
    //   10,000,000,000,000,000,000.
11488
    // - Therefore, if the number is positive and lower than that, it's overflow.
11489
    // - The value we are looking at is less than or equal to INT64_MAX.
11490
    //
11491
    }  else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
11492
  }
11493
11494
  // Write unsigned if it does not fit in a signed integer.
11495
  if (i > uint64_t(INT64_MAX)) {
11496
    WRITE_UNSIGNED(i, src, writer);
11497
  } else {
11498
    WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
11499
  }
11500
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
11501
  return SUCCESS;
11502
}
11503
11504
// Inlineable functions
11505
namespace {
11506
11507
// This table can be used to characterize the final character of an integer
11508
// string. For JSON structural character and allowable white space characters,
11509
// we return SUCCESS. For 'e', '.' and 'E', we return INCORRECT_TYPE. Otherwise
11510
// we return NUMBER_ERROR.
11511
// Optimization note: we could easily reduce the size of the table by half (to 128)
11512
// at the cost of an extra branch.
11513
// Optimization note: we want the values to use at most 8 bits (not, e.g., 32 bits):
11514
static_assert(error_code(uint8_t(NUMBER_ERROR))== NUMBER_ERROR, "bad NUMBER_ERROR cast");
11515
static_assert(error_code(uint8_t(SUCCESS))== SUCCESS, "bad NUMBER_ERROR cast");
11516
static_assert(error_code(uint8_t(INCORRECT_TYPE))== INCORRECT_TYPE, "bad NUMBER_ERROR cast");
11517
11518
const uint8_t integer_string_finisher[256] = {
11519
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11520
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
11521
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
11522
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11523
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11524
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11525
    NUMBER_ERROR, NUMBER_ERROR,   SUCCESS,      NUMBER_ERROR, NUMBER_ERROR,
11526
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11527
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
11528
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11529
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11530
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
11531
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11532
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, INCORRECT_TYPE,
11533
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11534
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11535
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11536
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11537
    NUMBER_ERROR, SUCCESS,        NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
11538
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11539
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11540
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11541
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11542
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11543
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
11544
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11545
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11546
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11547
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11548
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11549
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11550
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11551
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11552
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11553
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11554
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11555
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11556
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11557
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11558
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11559
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11560
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11561
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11562
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11563
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11564
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11565
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11566
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11567
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11568
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11569
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
11570
    NUMBER_ERROR};
11571
11572
// Parse any number from 0 to 18,446,744,073,709,551,615
11573
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept {
11574
  const uint8_t *p = src;
11575
  //
11576
  // Parse the integer part.
11577
  //
11578
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
11579
  const uint8_t *const start_digits = p;
11580
  uint64_t i = 0;
11581
  while (parse_digit(*p, i)) { p++; }
11582
11583
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
11584
  // Optimization note: size_t is expected to be unsigned.
11585
  size_t digit_count = size_t(p - start_digits);
11586
  // The longest positive 64-bit number is 20 digits.
11587
  // We do it this way so we don't trigger this branch unless we must.
11588
  // Optimization note: the compiler can probably merge
11589
  // ((digit_count == 0) || (digit_count > 20))
11590
  // into a single  branch since digit_count is unsigned.
11591
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
11592
  // Here digit_count > 0.
11593
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
11594
  // We can do the following...
11595
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
11596
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
11597
  // }
11598
  // as a single table lookup:
11599
  if (integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
11600
11601
  if (digit_count == 20) {
11602
    // Positive overflow check:
11603
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
11604
    //   biggest uint64_t.
11605
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
11606
    //   If we got here, it's a 20 digit number starting with the digit "1".
11607
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
11608
    //   than 1,553,255,926,290,448,384.
11609
    // - That is smaller than the smallest possible 20-digit number the user could write:
11610
    //   10,000,000,000,000,000,000.
11611
    // - Therefore, if the number is positive and lower than that, it's overflow.
11612
    // - The value we are looking at is less than or equal to INT64_MAX.
11613
    //
11614
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
11615
  }
11616
11617
  return i;
11618
}
11619
11620
11621
// Parse any number from 0 to 18,446,744,073,709,551,615
11622
// Never read at src_end or beyond
11623
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src, const uint8_t * const src_end) noexcept {
11624
  const uint8_t *p = src;
11625
  //
11626
  // Parse the integer part.
11627
  //
11628
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
11629
  const uint8_t *const start_digits = p;
11630
  uint64_t i = 0;
11631
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
11632
11633
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
11634
  // Optimization note: size_t is expected to be unsigned.
11635
  size_t digit_count = size_t(p - start_digits);
11636
  // The longest positive 64-bit number is 20 digits.
11637
  // We do it this way so we don't trigger this branch unless we must.
11638
  // Optimization note: the compiler can probably merge
11639
  // ((digit_count == 0) || (digit_count > 20))
11640
  // into a single  branch since digit_count is unsigned.
11641
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
11642
  // Here digit_count > 0.
11643
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
11644
  // We can do the following...
11645
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
11646
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
11647
  // }
11648
  // as a single table lookup:
11649
  if ((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
11650
11651
  if (digit_count == 20) {
11652
    // Positive overflow check:
11653
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
11654
    //   biggest uint64_t.
11655
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
11656
    //   If we got here, it's a 20 digit number starting with the digit "1".
11657
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
11658
    //   than 1,553,255,926,290,448,384.
11659
    // - That is smaller than the smallest possible 20-digit number the user could write:
11660
    //   10,000,000,000,000,000,000.
11661
    // - Therefore, if the number is positive and lower than that, it's overflow.
11662
    // - The value we are looking at is less than or equal to INT64_MAX.
11663
    //
11664
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
11665
  }
11666
11667
  return i;
11668
}
11669
11670
// Parse any number from 0 to 18,446,744,073,709,551,615
11671
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept {
11672
  const uint8_t *p = src + 1;
11673
  //
11674
  // Parse the integer part.
11675
  //
11676
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
11677
  const uint8_t *const start_digits = p;
11678
  uint64_t i = 0;
11679
  while (parse_digit(*p, i)) { p++; }
11680
11681
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
11682
  // Optimization note: size_t is expected to be unsigned.
11683
  size_t digit_count = size_t(p - start_digits);
11684
  // The longest positive 64-bit number is 20 digits.
11685
  // We do it this way so we don't trigger this branch unless we must.
11686
  // Optimization note: the compiler can probably merge
11687
  // ((digit_count == 0) || (digit_count > 20))
11688
  // into a single  branch since digit_count is unsigned.
11689
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
11690
  // Here digit_count > 0.
11691
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
11692
  // We can do the following...
11693
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
11694
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
11695
  // }
11696
  // as a single table lookup:
11697
  if (*p != '"') { return NUMBER_ERROR; }
11698
11699
  if (digit_count == 20) {
11700
    // Positive overflow check:
11701
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
11702
    //   biggest uint64_t.
11703
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
11704
    //   If we got here, it's a 20 digit number starting with the digit "1".
11705
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
11706
    //   than 1,553,255,926,290,448,384.
11707
    // - That is smaller than the smallest possible 20-digit number the user could write:
11708
    //   10,000,000,000,000,000,000.
11709
    // - Therefore, if the number is positive and lower than that, it's overflow.
11710
    // - The value we are looking at is less than or equal to INT64_MAX.
11711
    //
11712
    // Note: we use src[1] and not src[0] because src[0] is the quote character in this
11713
    // instance.
11714
    if (src[1] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
11715
  }
11716
11717
  return i;
11718
}
11719
11720
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
11721
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
11722
  //
11723
  // Check for minus sign
11724
  //
11725
  bool negative = (*src == '-');
11726
  const uint8_t *p = src + uint8_t(negative);
11727
11728
  //
11729
  // Parse the integer part.
11730
  //
11731
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
11732
  const uint8_t *const start_digits = p;
11733
  uint64_t i = 0;
11734
  while (parse_digit(*p, i)) { p++; }
11735
11736
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
11737
  // Optimization note: size_t is expected to be unsigned.
11738
  size_t digit_count = size_t(p - start_digits);
11739
  // We go from
11740
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
11741
  // so we can never represent numbers that have more than 19 digits.
11742
  size_t longest_digit_count = 19;
11743
  // Optimization note: the compiler can probably merge
11744
  // ((digit_count == 0) || (digit_count > longest_digit_count))
11745
  // into a single  branch since digit_count is unsigned.
11746
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
11747
  // Here digit_count > 0.
11748
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
11749
  // We can do the following...
11750
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
11751
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
11752
  // }
11753
  // as a single table lookup:
11754
  if(integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
11755
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
11756
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
11757
  // so cheap that we might as well always make it.
11758
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
11759
  return negative ? (~i+1) : i;
11760
}
11761
11762
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
11763
// Never read at src_end or beyond
11764
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src, const uint8_t * const src_end) noexcept {
11765
  //
11766
  // Check for minus sign
11767
  //
11768
  if(src == src_end) { return NUMBER_ERROR; }
11769
  bool negative = (*src == '-');
11770
  const uint8_t *p = src + uint8_t(negative);
11771
11772
  //
11773
  // Parse the integer part.
11774
  //
11775
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
11776
  const uint8_t *const start_digits = p;
11777
  uint64_t i = 0;
11778
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
11779
11780
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
11781
  // Optimization note: size_t is expected to be unsigned.
11782
  size_t digit_count = size_t(p - start_digits);
11783
  // We go from
11784
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
11785
  // so we can never represent numbers that have more than 19 digits.
11786
  size_t longest_digit_count = 19;
11787
  // Optimization note: the compiler can probably merge
11788
  // ((digit_count == 0) || (digit_count > longest_digit_count))
11789
  // into a single  branch since digit_count is unsigned.
11790
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
11791
  // Here digit_count > 0.
11792
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
11793
  // We can do the following...
11794
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
11795
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
11796
  // }
11797
  // as a single table lookup:
11798
  if((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
11799
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
11800
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
11801
  // so cheap that we might as well always make it.
11802
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
11803
  return negative ? (~i+1) : i;
11804
}
11805
11806
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
11807
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t *src) noexcept {
11808
  //
11809
  // Check for minus sign
11810
  //
11811
  bool negative = (*(src + 1) == '-');
11812
  src += uint8_t(negative) + 1;
11813
11814
  //
11815
  // Parse the integer part.
11816
  //
11817
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
11818
  const uint8_t *const start_digits = src;
11819
  uint64_t i = 0;
11820
  while (parse_digit(*src, i)) { src++; }
11821
11822
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
11823
  // Optimization note: size_t is expected to be unsigned.
11824
  size_t digit_count = size_t(src - start_digits);
11825
  // We go from
11826
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
11827
  // so we can never represent numbers that have more than 19 digits.
11828
  size_t longest_digit_count = 19;
11829
  // Optimization note: the compiler can probably merge
11830
  // ((digit_count == 0) || (digit_count > longest_digit_count))
11831
  // into a single  branch since digit_count is unsigned.
11832
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
11833
  // Here digit_count > 0.
11834
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
11835
  // We can do the following...
11836
  // if (!jsoncharutils::is_structural_or_whitespace(*src)) {
11837
  //  return (*src == '.' || *src == 'e' || *src == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
11838
  // }
11839
  // as a single table lookup:
11840
  if(*src != '"') { return NUMBER_ERROR; }
11841
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
11842
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
11843
  // so cheap that we might as well always make it.
11844
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
11845
  return negative ? (~i+1) : i;
11846
}
11847
11848
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
11849
  //
11850
  // Check for minus sign
11851
  //
11852
  bool negative = (*src == '-');
11853
  src += uint8_t(negative);
11854
11855
  //
11856
  // Parse the integer part.
11857
  //
11858
  uint64_t i = 0;
11859
  const uint8_t *p = src;
11860
  p += parse_digit(*p, i);
11861
  bool leading_zero = (i == 0);
11862
  while (parse_digit(*p, i)) { p++; }
11863
  // no integer digits, or 0123 (zero must be solo)
11864
  if ( p == src ) { return INCORRECT_TYPE; }
11865
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
11866
11867
  //
11868
  // Parse the decimal part.
11869
  //
11870
  int64_t exponent = 0;
11871
  bool overflow;
11872
  if (simdjson_likely(*p == '.')) {
11873
    p++;
11874
    const uint8_t *start_decimal_digits = p;
11875
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
11876
    p++;
11877
    while (parse_digit(*p, i)) { p++; }
11878
    exponent = -(p - start_decimal_digits);
11879
11880
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
11881
    overflow = p-src-1 > 19;
11882
    if (simdjson_unlikely(overflow && leading_zero)) {
11883
      // Skip leading 0.00000 and see if it still overflows
11884
      const uint8_t *start_digits = src + 2;
11885
      while (*start_digits == '0') { start_digits++; }
11886
      overflow = p-start_digits > 19;
11887
    }
11888
  } else {
11889
    overflow = p-src > 19;
11890
  }
11891
11892
  //
11893
  // Parse the exponent
11894
  //
11895
  if (*p == 'e' || *p == 'E') {
11896
    p++;
11897
    bool exp_neg = *p == '-';
11898
    p += exp_neg || *p == '+';
11899
11900
    uint64_t exp = 0;
11901
    const uint8_t *start_exp_digits = p;
11902
    while (parse_digit(*p, exp)) { p++; }
11903
    // no exp digits, or 20+ exp digits
11904
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
11905
11906
    exponent += exp_neg ? 0-exp : exp;
11907
  }
11908
11909
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
11910
11911
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
11912
11913
  //
11914
  // Assemble (or slow-parse) the float
11915
  //
11916
  double d;
11917
  if (simdjson_likely(!overflow)) {
11918
    if (compute_float_64(exponent, i, negative, d)) { return d; }
11919
  }
11920
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
11921
    return NUMBER_ERROR;
11922
  }
11923
  return d;
11924
}
11925
11926
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept {
11927
  return (*src == '-');
11928
}
11929
11930
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept {
11931
  bool negative = (*src == '-');
11932
  src += uint8_t(negative);
11933
  const uint8_t *p = src;
11934
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
11935
  if ( p == src ) { return NUMBER_ERROR; }
11936
  if (jsoncharutils::is_structural_or_whitespace(*p)) { return true; }
11937
  return false;
11938
}
11939
11940
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept {
11941
  bool negative = (*src == '-');
11942
  src += uint8_t(negative);
11943
  const uint8_t *p = src;
11944
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
11945
  size_t digit_count = size_t(p - src);
11946
  if ( p == src ) { return NUMBER_ERROR; }
11947
  if (jsoncharutils::is_structural_or_whitespace(*p)) {
11948
    static const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
11949
    // We have an integer.
11950
    if(simdjson_unlikely(digit_count > 20)) {
11951
      return number_type::big_integer;
11952
    }
11953
    // If the number is negative and valid, it must be a signed integer.
11954
    if(negative) {
11955
      if (simdjson_unlikely(digit_count > 19)) return number_type::big_integer;
11956
      if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) {
11957
        return number_type::big_integer;
11958
      }
11959
      return number_type::signed_integer;
11960
    }
11961
    // Let us check if we have a big integer (>=2**64).
11962
    static const uint8_t * two_to_sixtyfour = reinterpret_cast<const uint8_t *>("18446744073709551616");
11963
    if((digit_count > 20) || (digit_count == 20 && memcmp(src, two_to_sixtyfour, 20) >= 0)) {
11964
      return number_type::big_integer;
11965
    }
11966
    // The number is positive and smaller than 18446744073709551616 (or 2**64).
11967
    // We want values larger or equal to 9223372036854775808 to be unsigned
11968
    // integers, and the other values to be signed integers.
11969
    if((digit_count == 20) || (digit_count >= 19 && memcmp(src, smaller_big_integer, 19) >= 0)) {
11970
      return number_type::unsigned_integer;
11971
    }
11972
    return number_type::signed_integer;
11973
  }
11974
  // Hopefully, we have 'e' or 'E' or '.'.
11975
  return number_type::floating_point_number;
11976
}
11977
11978
// Never read at src_end or beyond
11979
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
11980
  if(src == src_end) { return NUMBER_ERROR; }
11981
  //
11982
  // Check for minus sign
11983
  //
11984
  bool negative = (*src == '-');
11985
  src += uint8_t(negative);
11986
11987
  //
11988
  // Parse the integer part.
11989
  //
11990
  uint64_t i = 0;
11991
  const uint8_t *p = src;
11992
  if(p == src_end) { return NUMBER_ERROR; }
11993
  p += parse_digit(*p, i);
11994
  bool leading_zero = (i == 0);
11995
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
11996
  // no integer digits, or 0123 (zero must be solo)
11997
  if ( p == src ) { return INCORRECT_TYPE; }
11998
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
11999
12000
  //
12001
  // Parse the decimal part.
12002
  //
12003
  int64_t exponent = 0;
12004
  bool overflow;
12005
  if (simdjson_likely((p != src_end) && (*p == '.'))) {
12006
    p++;
12007
    const uint8_t *start_decimal_digits = p;
12008
    if ((p == src_end) || !parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
12009
    p++;
12010
    while ((p != src_end) && parse_digit(*p, i)) { p++; }
12011
    exponent = -(p - start_decimal_digits);
12012
12013
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
12014
    overflow = p-src-1 > 19;
12015
    if (simdjson_unlikely(overflow && leading_zero)) {
12016
      // Skip leading 0.00000 and see if it still overflows
12017
      const uint8_t *start_digits = src + 2;
12018
      while (*start_digits == '0') { start_digits++; }
12019
      overflow = start_digits-src > 19;
12020
    }
12021
  } else {
12022
    overflow = p-src > 19;
12023
  }
12024
12025
  //
12026
  // Parse the exponent
12027
  //
12028
  if ((p != src_end) && (*p == 'e' || *p == 'E')) {
12029
    p++;
12030
    if(p == src_end) { return NUMBER_ERROR; }
12031
    bool exp_neg = *p == '-';
12032
    p += exp_neg || *p == '+';
12033
12034
    uint64_t exp = 0;
12035
    const uint8_t *start_exp_digits = p;
12036
    while ((p != src_end) && parse_digit(*p, exp)) { p++; }
12037
    // no exp digits, or 20+ exp digits
12038
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
12039
12040
    exponent += exp_neg ? 0-exp : exp;
12041
  }
12042
12043
  if ((p != src_end) && jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
12044
12045
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
12046
12047
  //
12048
  // Assemble (or slow-parse) the float
12049
  //
12050
  double d;
12051
  if (simdjson_likely(!overflow)) {
12052
    if (compute_float_64(exponent, i, negative, d)) { return d; }
12053
  }
12054
  if (!parse_float_fallback(src - uint8_t(negative), src_end, &d)) {
12055
    return NUMBER_ERROR;
12056
  }
12057
  return d;
12058
}
12059
12060
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * src) noexcept {
12061
  //
12062
  // Check for minus sign
12063
  //
12064
  bool negative = (*(src + 1) == '-');
12065
  src += uint8_t(negative) + 1;
12066
12067
  //
12068
  // Parse the integer part.
12069
  //
12070
  uint64_t i = 0;
12071
  const uint8_t *p = src;
12072
  p += parse_digit(*p, i);
12073
  bool leading_zero = (i == 0);
12074
  while (parse_digit(*p, i)) { p++; }
12075
  // no integer digits, or 0123 (zero must be solo)
12076
  if ( p == src ) { return INCORRECT_TYPE; }
12077
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
12078
12079
  //
12080
  // Parse the decimal part.
12081
  //
12082
  int64_t exponent = 0;
12083
  bool overflow;
12084
  if (simdjson_likely(*p == '.')) {
12085
    p++;
12086
    const uint8_t *start_decimal_digits = p;
12087
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
12088
    p++;
12089
    while (parse_digit(*p, i)) { p++; }
12090
    exponent = -(p - start_decimal_digits);
12091
12092
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
12093
    overflow = p-src-1 > 19;
12094
    if (simdjson_unlikely(overflow && leading_zero)) {
12095
      // Skip leading 0.00000 and see if it still overflows
12096
      const uint8_t *start_digits = src + 2;
12097
      while (*start_digits == '0') { start_digits++; }
12098
      overflow = p-start_digits > 19;
12099
    }
12100
  } else {
12101
    overflow = p-src > 19;
12102
  }
12103
12104
  //
12105
  // Parse the exponent
12106
  //
12107
  if (*p == 'e' || *p == 'E') {
12108
    p++;
12109
    bool exp_neg = *p == '-';
12110
    p += exp_neg || *p == '+';
12111
12112
    uint64_t exp = 0;
12113
    const uint8_t *start_exp_digits = p;
12114
    while (parse_digit(*p, exp)) { p++; }
12115
    // no exp digits, or 20+ exp digits
12116
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
12117
12118
    exponent += exp_neg ? 0-exp : exp;
12119
  }
12120
12121
  if (*p != '"') { return NUMBER_ERROR; }
12122
12123
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
12124
12125
  //
12126
  // Assemble (or slow-parse) the float
12127
  //
12128
  double d;
12129
  if (simdjson_likely(!overflow)) {
12130
    if (compute_float_64(exponent, i, negative, d)) { return d; }
12131
  }
12132
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
12133
    return NUMBER_ERROR;
12134
  }
12135
  return d;
12136
}
12137
12138
} // unnamed namespace
12139
#endif // SIMDJSON_SKIPNUMBERPARSING
12140
12141
} // namespace numberparsing
12142
12143
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
12144
    switch (type) {
12145
        case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
12146
        case number_type::unsigned_integer: out << "unsigned integer in [9223372036854775808,18446744073709551616)"; break;
12147
        case number_type::floating_point_number: out << "floating-point number (binary64)"; break;
12148
        case number_type::big_integer: out << "big integer"; break;
12149
        default: SIMDJSON_UNREACHABLE();
12150
    }
12151
    return out;
12152
}
12153
12154
} // namespace arm64
12155
} // namespace simdjson
12156
12157
#endif // SIMDJSON_GENERIC_NUMBERPARSING_H
12158
/* end file simdjson/generic/numberparsing.h for arm64 */
12159
12160
/* including simdjson/generic/implementation_simdjson_result_base-inl.h for arm64: #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
12161
/* begin file simdjson/generic/implementation_simdjson_result_base-inl.h for arm64 */
12162
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
12163
12164
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12165
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H */
12166
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
12167
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
12168
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12169
12170
namespace simdjson {
12171
namespace arm64 {
12172
12173
//
12174
// internal::implementation_simdjson_result_base<T> inline implementation
12175
//
12176
12177
template<typename T>
12178
simdjson_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
12179
  error = this->second;
12180
  if (!error) {
12181
    value = std::forward<implementation_simdjson_result_base<T>>(*this).first;
12182
  }
12183
}
12184
12185
template<typename T>
12186
simdjson_warn_unused simdjson_inline error_code implementation_simdjson_result_base<T>::get(T &value) && noexcept {
12187
  error_code error;
12188
  std::forward<implementation_simdjson_result_base<T>>(*this).tie(value, error);
12189
  return error;
12190
}
12191
12192
template<typename T>
12193
simdjson_inline error_code implementation_simdjson_result_base<T>::error() const noexcept {
12194
  return this->second;
12195
}
12196
12197
#if SIMDJSON_EXCEPTIONS
12198
12199
template<typename T>
12200
simdjson_inline T& implementation_simdjson_result_base<T>::value() & noexcept(false) {
12201
  if (error()) { throw simdjson_error(error()); }
12202
  return this->first;
12203
}
12204
12205
template<typename T>
12206
simdjson_inline T&& implementation_simdjson_result_base<T>::value() && noexcept(false) {
12207
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
12208
}
12209
12210
template<typename T>
12211
simdjson_inline T&& implementation_simdjson_result_base<T>::take_value() && noexcept(false) {
12212
  if (error()) { throw simdjson_error(error()); }
12213
  return std::forward<T>(this->first);
12214
}
12215
12216
template<typename T>
12217
simdjson_inline implementation_simdjson_result_base<T>::operator T&&() && noexcept(false) {
12218
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
12219
}
12220
12221
#endif // SIMDJSON_EXCEPTIONS
12222
12223
template<typename T>
12224
simdjson_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
12225
  return this->first;
12226
}
12227
12228
template<typename T>
12229
simdjson_inline T& implementation_simdjson_result_base<T>::value_unsafe() & noexcept {
12230
  return this->first;
12231
}
12232
12233
template<typename T>
12234
simdjson_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
12235
  return std::forward<T>(this->first);
12236
}
12237
12238
template<typename T>
12239
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
12240
    : first{std::forward<T>(value)}, second{error} {}
12241
template<typename T>
12242
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(error_code error) noexcept
12243
    : implementation_simdjson_result_base(T{}, error) {}
12244
template<typename T>
12245
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
12246
    : implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
12247
12248
} // namespace arm64
12249
} // namespace simdjson
12250
12251
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
12252
/* end file simdjson/generic/implementation_simdjson_result_base-inl.h for arm64 */
12253
/* end file simdjson/generic/amalgamated.h for arm64 */
12254
/* including simdjson/arm64/end.h: #include "simdjson/arm64/end.h" */
12255
/* begin file simdjson/arm64/end.h */
12256
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12257
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
12258
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12259
12260
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
12261
/* undefining SIMDJSON_IMPLEMENTATION from "arm64" */
12262
#undef SIMDJSON_IMPLEMENTATION
12263
/* end file simdjson/arm64/end.h */
12264
12265
#endif // SIMDJSON_ARM64_H
12266
/* end file simdjson/arm64.h */
12267
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
12268
/* including simdjson/fallback.h: #include "simdjson/fallback.h" */
12269
/* begin file simdjson/fallback.h */
12270
#ifndef SIMDJSON_FALLBACK_H
12271
#define SIMDJSON_FALLBACK_H
12272
12273
/* including simdjson/fallback/begin.h: #include "simdjson/fallback/begin.h" */
12274
/* begin file simdjson/fallback/begin.h */
12275
/* defining SIMDJSON_IMPLEMENTATION to "fallback" */
12276
#define SIMDJSON_IMPLEMENTATION fallback
12277
/* including simdjson/fallback/base.h: #include "simdjson/fallback/base.h" */
12278
/* begin file simdjson/fallback/base.h */
12279
#ifndef SIMDJSON_FALLBACK_BASE_H
12280
#define SIMDJSON_FALLBACK_BASE_H
12281
12282
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12283
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
12284
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12285
12286
namespace simdjson {
12287
/**
12288
 * Fallback implementation (runs on any machine).
12289
 */
12290
namespace fallback {
12291
12292
class implementation;
12293
12294
} // namespace fallback
12295
} // namespace simdjson
12296
12297
#endif // SIMDJSON_FALLBACK_BASE_H
12298
/* end file simdjson/fallback/base.h */
12299
/* including simdjson/fallback/bitmanipulation.h: #include "simdjson/fallback/bitmanipulation.h" */
12300
/* begin file simdjson/fallback/bitmanipulation.h */
12301
#ifndef SIMDJSON_FALLBACK_BITMANIPULATION_H
12302
#define SIMDJSON_FALLBACK_BITMANIPULATION_H
12303
12304
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12305
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
12306
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12307
12308
namespace simdjson {
12309
namespace fallback {
12310
namespace {
12311
12312
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
12313
static inline unsigned char _BitScanForward64(unsigned long* ret, uint64_t x) {
12314
  unsigned long x0 = (unsigned long)x, top, bottom;
12315
  _BitScanForward(&top, (unsigned long)(x >> 32));
12316
  _BitScanForward(&bottom, x0);
12317
  *ret = x0 ? bottom : 32 + top;
12318
  return x != 0;
12319
}
12320
static unsigned char _BitScanReverse64(unsigned long* ret, uint64_t x) {
12321
  unsigned long x1 = (unsigned long)(x >> 32), top, bottom;
12322
  _BitScanReverse(&top, x1);
12323
  _BitScanReverse(&bottom, (unsigned long)x);
12324
  *ret = x1 ? top + 32 : bottom;
12325
  return x != 0;
12326
}
12327
#endif
12328
12329
/* result might be undefined when input_num is zero */
12330
0
simdjson_inline int leading_zeroes(uint64_t input_num) {
12331
0
#ifdef _MSC_VER
12332
0
  unsigned long leading_zero = 0;
12333
0
  // Search the mask data from most significant bit (MSB)
12334
0
  // to least significant bit (LSB) for a set bit (1).
12335
0
  if (_BitScanReverse64(&leading_zero, input_num))
12336
0
    return (int)(63 - leading_zero);
12337
0
  else
12338
0
    return 64;
12339
0
#else
12340
0
  return __builtin_clzll(input_num);
12341
0
#endif// _MSC_VER
12342
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::leading_zeroes(unsigned long)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::leading_zeroes(unsigned long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::leading_zeroes(unsigned long)
12343
12344
} // unnamed namespace
12345
} // namespace fallback
12346
} // namespace simdjson
12347
12348
#endif // SIMDJSON_FALLBACK_BITMANIPULATION_H
12349
/* end file simdjson/fallback/bitmanipulation.h */
12350
/* including simdjson/fallback/stringparsing_defs.h: #include "simdjson/fallback/stringparsing_defs.h" */
12351
/* begin file simdjson/fallback/stringparsing_defs.h */
12352
#ifndef SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
12353
#define SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
12354
12355
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12356
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
12357
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12358
12359
namespace simdjson {
12360
namespace fallback {
12361
namespace {
12362
12363
// Holds backslashes and quotes locations.
12364
struct backslash_and_quote {
12365
public:
12366
  static constexpr uint32_t BYTES_PROCESSED = 1;
12367
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
12368
12369
0
  simdjson_inline bool has_quote_first() { return c == '"'; }
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::has_quote_first()
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::has_quote_first()
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::has_quote_first()
12370
0
  simdjson_inline bool has_backslash() { return c == '\\'; }
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::has_backslash()
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::has_backslash()
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::has_backslash()
12371
0
  simdjson_inline int quote_index() { return c == '"' ? 0 : 1; }
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::quote_index()
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::quote_index()
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::quote_index()
12372
0
  simdjson_inline int backslash_index() { return c == '\\' ? 0 : 1; }
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::backslash_index()
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::backslash_index()
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::backslash_index()
12373
12374
  uint8_t c;
12375
}; // struct backslash_and_quote
12376
12377
0
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
12378
0
  // store to dest unconditionally - we can overwrite the bits we don't like later
12379
0
  dst[0] = src[0];
12380
0
  return { src[0] };
12381
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::copy_and_find(unsigned char const*, unsigned char*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::copy_and_find(unsigned char const*, unsigned char*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::backslash_and_quote::copy_and_find(unsigned char const*, unsigned char*)
12382
12383
} // unnamed namespace
12384
} // namespace fallback
12385
} // namespace simdjson
12386
12387
#endif // SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
12388
/* end file simdjson/fallback/stringparsing_defs.h */
12389
/* including simdjson/fallback/numberparsing_defs.h: #include "simdjson/fallback/numberparsing_defs.h" */
12390
/* begin file simdjson/fallback/numberparsing_defs.h */
12391
#ifndef SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
12392
#define SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
12393
12394
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12395
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
12396
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
12397
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12398
12399
#include <cstring>
12400
12401
#ifdef JSON_TEST_NUMBERS // for unit testing
12402
void found_invalid_number(const uint8_t *buf);
12403
void found_integer(int64_t result, const uint8_t *buf);
12404
void found_unsigned_integer(uint64_t result, const uint8_t *buf);
12405
void found_float(double result, const uint8_t *buf);
12406
#endif
12407
12408
namespace simdjson {
12409
namespace fallback {
12410
namespace numberparsing {
12411
12412
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
12413
/** @private */
12414
0
static simdjson_inline uint32_t parse_eight_digits_unrolled(const char *chars) {
12415
0
  uint64_t val;
12416
0
  memcpy(&val, chars, sizeof(uint64_t));
12417
0
  val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
12418
0
  val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
12419
0
  return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
12420
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::parse_eight_digits_unrolled(char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::parse_eight_digits_unrolled(char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::parse_eight_digits_unrolled(char const*)
12421
12422
/** @private */
12423
0
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
12424
0
  return parse_eight_digits_unrolled(reinterpret_cast<const char *>(chars));
12425
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::parse_eight_digits_unrolled(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::parse_eight_digits_unrolled(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::parse_eight_digits_unrolled(unsigned char const*)
12426
12427
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
12428
// this is a slow emulation routine for 32-bit
12429
//
12430
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
12431
  return x * (uint64_t)y;
12432
}
12433
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
12434
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
12435
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
12436
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
12437
  uint64_t adbc_carry = !!(adbc < ad);
12438
  uint64_t lo = bd + (adbc << 32);
12439
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
12440
        (adbc_carry << 32) + !!(lo < bd);
12441
  return lo;
12442
}
12443
#endif
12444
12445
/** @private */
12446
0
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
12447
0
  internal::value128 answer;
12448
0
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
12449
0
#ifdef _M_ARM64
12450
0
  // ARM64 has native support for 64-bit multiplications, no need to emultate
12451
0
  answer.high = __umulh(value1, value2);
12452
0
  answer.low = value1 * value2;
12453
0
#else
12454
0
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
12455
0
#endif // _M_ARM64
12456
0
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
12457
0
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
12458
0
  answer.low = uint64_t(r);
12459
0
  answer.high = uint64_t(r >> 64);
12460
0
#endif
12461
0
  return answer;
12462
0
}
12463
12464
} // namespace numberparsing
12465
} // namespace fallback
12466
} // namespace simdjson
12467
12468
#define SIMDJSON_SWAR_NUMBER_PARSING 1
12469
12470
#endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
12471
/* end file simdjson/fallback/numberparsing_defs.h */
12472
/* end file simdjson/fallback/begin.h */
12473
/* including simdjson/generic/amalgamated.h for fallback: #include "simdjson/generic/amalgamated.h" */
12474
/* begin file simdjson/generic/amalgamated.h for fallback */
12475
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
12476
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
12477
#endif
12478
12479
/* including simdjson/generic/base.h for fallback: #include "simdjson/generic/base.h" */
12480
/* begin file simdjson/generic/base.h for fallback */
12481
#ifndef SIMDJSON_GENERIC_BASE_H
12482
12483
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12484
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_BASE_H */
12485
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
12486
/* amalgamation skipped (editor-only): // If we haven't got an implementation yet, we're in the editor, editing a generic file! Just */
12487
/* amalgamation skipped (editor-only): // use the most advanced one we can so the most possible stuff can be tested. */
12488
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_IMPLEMENTATION */
12489
/* amalgamation skipped (editor-only): #include "simdjson/implementation_detection.h" */
12490
/* amalgamation skipped (editor-only): #if SIMDJSON_IMPLEMENTATION_ICELAKE */
12491
/* amalgamation skipped (editor-only): #include "simdjson/icelake/begin.h" */
12492
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_HASWELL */
12493
/* amalgamation skipped (editor-only): #include "simdjson/haswell/begin.h" */
12494
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_WESTMERE */
12495
/* amalgamation skipped (editor-only): #include "simdjson/westmere/begin.h" */
12496
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_ARM64 */
12497
/* amalgamation skipped (editor-only): #include "simdjson/arm64/begin.h" */
12498
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_PPC64 */
12499
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/begin.h" */
12500
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_FALLBACK */
12501
/* amalgamation skipped (editor-only): #include "simdjson/fallback/begin.h" */
12502
/* amalgamation skipped (editor-only): #else */
12503
/* amalgamation skipped (editor-only): #error "All possible implementations (including fallback) have been disabled! simdjson will not run." */
12504
/* amalgamation skipped (editor-only): #endif */
12505
/* amalgamation skipped (editor-only): #endif // SIMDJSON_IMPLEMENTATION */
12506
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12507
12508
namespace simdjson {
12509
namespace fallback {
12510
12511
struct open_container;
12512
class dom_parser_implementation;
12513
12514
/**
12515
 * The type of a JSON number
12516
 */
12517
enum class number_type {
12518
    floating_point_number=1, /// a binary64 number
12519
    signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
12520
    unsigned_integer,        /// a positive integer larger or equal to 1<<63
12521
    big_integer              /// a big integer that does not fit in a 64-bit word
12522
};
12523
12524
} // namespace fallback
12525
} // namespace simdjson
12526
12527
#endif // SIMDJSON_GENERIC_BASE_H
12528
/* end file simdjson/generic/base.h for fallback */
12529
/* including simdjson/generic/jsoncharutils.h for fallback: #include "simdjson/generic/jsoncharutils.h" */
12530
/* begin file simdjson/generic/jsoncharutils.h for fallback */
12531
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
12532
12533
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12534
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_JSONCHARUTILS_H */
12535
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
12536
/* amalgamation skipped (editor-only): #include "simdjson/internal/jsoncharutils_tables.h" */
12537
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
12538
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12539
12540
namespace simdjson {
12541
namespace fallback {
12542
namespace {
12543
namespace jsoncharutils {
12544
12545
// return non-zero if not a structural or whitespace char
12546
// zero otherwise
12547
0
simdjson_inline uint32_t is_not_structural_or_whitespace(uint8_t c) {
12548
0
  return internal::structural_or_whitespace_negated[c];
12549
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::is_not_structural_or_whitespace(unsigned char)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::is_not_structural_or_whitespace(unsigned char)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::is_not_structural_or_whitespace(unsigned char)
12550
12551
0
simdjson_inline uint32_t is_structural_or_whitespace(uint8_t c) {
12552
0
  return internal::structural_or_whitespace[c];
12553
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::is_structural_or_whitespace(unsigned char)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::is_structural_or_whitespace(unsigned char)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::is_structural_or_whitespace(unsigned char)
12554
12555
// returns a value with the high 16 bits set if not valid
12556
// otherwise returns the conversion of the 4 hex digits at src into the bottom
12557
// 16 bits of the 32-bit return register
12558
//
12559
// see
12560
// https://lemire.me/blog/2019/04/17/parsing-short-hexadecimal-strings-efficiently/
12561
static inline uint32_t hex_to_u32_nocheck(
12562
0
    const uint8_t *src) { // strictly speaking, static inline is a C-ism
12563
0
  uint32_t v1 = internal::digit_to_val32[630 + src[0]];
12564
0
  uint32_t v2 = internal::digit_to_val32[420 + src[1]];
12565
0
  uint32_t v3 = internal::digit_to_val32[210 + src[2]];
12566
0
  uint32_t v4 = internal::digit_to_val32[0 + src[3]];
12567
0
  return v1 | v2 | v3 | v4;
12568
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::hex_to_u32_nocheck(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::hex_to_u32_nocheck(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::hex_to_u32_nocheck(unsigned char const*)
12569
12570
// given a code point cp, writes to c
12571
// the utf-8 code, outputting the length in
12572
// bytes, if the length is zero, the code point
12573
// is invalid
12574
//
12575
// This can possibly be made faster using pdep
12576
// and clz and table lookups, but JSON documents
12577
// have few escaped code points, and the following
12578
// function looks cheap.
12579
//
12580
// Note: we assume that surrogates are treated separately
12581
//
12582
0
simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
12583
0
  if (cp <= 0x7F) {
12584
0
    c[0] = uint8_t(cp);
12585
0
    return 1; // ascii
12586
0
  }
12587
0
  if (cp <= 0x7FF) {
12588
0
    c[0] = uint8_t((cp >> 6) + 192);
12589
0
    c[1] = uint8_t((cp & 63) + 128);
12590
0
    return 2; // universal plane
12591
0
    //  Surrogates are treated elsewhere...
12592
0
    //} //else if (0xd800 <= cp && cp <= 0xdfff) {
12593
0
    //  return 0; // surrogates // could put assert here
12594
0
  } else if (cp <= 0xFFFF) {
12595
0
    c[0] = uint8_t((cp >> 12) + 224);
12596
0
    c[1] = uint8_t(((cp >> 6) & 63) + 128);
12597
0
    c[2] = uint8_t((cp & 63) + 128);
12598
0
    return 3;
12599
0
  } else if (cp <= 0x10FFFF) { // if you know you have a valid code point, this
12600
0
                               // is not needed
12601
0
    c[0] = uint8_t((cp >> 18) + 240);
12602
0
    c[1] = uint8_t(((cp >> 12) & 63) + 128);
12603
0
    c[2] = uint8_t(((cp >> 6) & 63) + 128);
12604
0
    c[3] = uint8_t((cp & 63) + 128);
12605
0
    return 4;
12606
0
  }
12607
0
  // will return 0 when the code point was too large.
12608
0
  return 0; // bad r
12609
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::codepoint_to_utf8(unsigned int, unsigned char*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::codepoint_to_utf8(unsigned int, unsigned char*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::jsoncharutils::codepoint_to_utf8(unsigned int, unsigned char*)
12610
12611
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
12612
// this is a slow emulation routine for 32-bit
12613
//
12614
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
12615
  return x * (uint64_t)y;
12616
}
12617
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
12618
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
12619
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
12620
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
12621
  uint64_t adbc_carry = !!(adbc < ad);
12622
  uint64_t lo = bd + (adbc << 32);
12623
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
12624
        (adbc_carry << 32) + !!(lo < bd);
12625
  return lo;
12626
}
12627
#endif
12628
12629
} // namespace jsoncharutils
12630
} // unnamed namespace
12631
} // namespace fallback
12632
} // namespace simdjson
12633
12634
#endif // SIMDJSON_GENERIC_JSONCHARUTILS_H
12635
/* end file simdjson/generic/jsoncharutils.h for fallback */
12636
/* including simdjson/generic/atomparsing.h for fallback: #include "simdjson/generic/atomparsing.h" */
12637
/* begin file simdjson/generic/atomparsing.h for fallback */
12638
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
12639
12640
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12641
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ATOMPARSING_H */
12642
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
12643
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
12644
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12645
12646
#include <cstring>
12647
12648
namespace simdjson {
12649
namespace fallback {
12650
namespace {
12651
/// @private
12652
namespace atomparsing {
12653
12654
// The string_to_uint32 is exclusively used to map literal strings to 32-bit values.
12655
// We use memcpy instead of a pointer cast to avoid undefined behaviors since we cannot
12656
// be certain that the character pointer will be properly aligned.
12657
// You might think that using memcpy makes this function expensive, but you'd be wrong.
12658
// All decent optimizing compilers (GCC, clang, Visual Studio) will compile string_to_uint32("false");
12659
// to the compile-time constant 1936482662.
12660
0
simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(&val, str, sizeof(uint32_t)); return val; }
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::string_to_uint32(char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::string_to_uint32(char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::string_to_uint32(char const*)
12661
12662
12663
// Again in str4ncmp we use a memcpy to avoid undefined behavior. The memcpy may appear expensive.
12664
// Yet all decent optimizing compilers will compile memcpy to a single instruction, just about.
12665
simdjson_warn_unused
12666
0
simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) {
12667
0
  uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++)
12668
0
  static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes");
12669
0
  std::memcpy(&srcval, src, sizeof(uint32_t));
12670
0
  return srcval ^ string_to_uint32(atom);
12671
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::str4ncmp(unsigned char const*, char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::str4ncmp(unsigned char const*, char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::str4ncmp(unsigned char const*, char const*)
12672
12673
simdjson_warn_unused
12674
0
simdjson_inline bool is_valid_true_atom(const uint8_t *src) {
12675
0
  return (str4ncmp(src, "true") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
12676
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_true_atom(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_true_atom(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_true_atom(unsigned char const*)
12677
12678
simdjson_warn_unused
12679
0
simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) {
12680
0
  if (len > 4) { return is_valid_true_atom(src); }
12681
0
  else if (len == 4) { return !str4ncmp(src, "true"); }
12682
0
  else { return false; }
12683
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_true_atom(unsigned char const*, unsigned long)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_true_atom(unsigned char const*, unsigned long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_true_atom(unsigned char const*, unsigned long)
12684
12685
simdjson_warn_unused
12686
0
simdjson_inline bool is_valid_false_atom(const uint8_t *src) {
12687
0
  return (str4ncmp(src+1, "alse") | jsoncharutils::is_not_structural_or_whitespace(src[5])) == 0;
12688
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_false_atom(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_false_atom(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_false_atom(unsigned char const*)
12689
12690
simdjson_warn_unused
12691
0
simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) {
12692
0
  if (len > 5) { return is_valid_false_atom(src); }
12693
0
  else if (len == 5) { return !str4ncmp(src+1, "alse"); }
12694
0
  else { return false; }
12695
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_false_atom(unsigned char const*, unsigned long)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_false_atom(unsigned char const*, unsigned long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_false_atom(unsigned char const*, unsigned long)
12696
12697
simdjson_warn_unused
12698
0
simdjson_inline bool is_valid_null_atom(const uint8_t *src) {
12699
0
  return (str4ncmp(src, "null") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
12700
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_null_atom(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_null_atom(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_null_atom(unsigned char const*)
12701
12702
simdjson_warn_unused
12703
0
simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
12704
0
  if (len > 4) { return is_valid_null_atom(src); }
12705
0
  else if (len == 4) { return !str4ncmp(src, "null"); }
12706
0
  else { return false; }
12707
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_null_atom(unsigned char const*, unsigned long)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_null_atom(unsigned char const*, unsigned long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::(anonymous namespace)::atomparsing::is_valid_null_atom(unsigned char const*, unsigned long)
12708
12709
} // namespace atomparsing
12710
} // unnamed namespace
12711
} // namespace fallback
12712
} // namespace simdjson
12713
12714
#endif // SIMDJSON_GENERIC_ATOMPARSING_H
12715
/* end file simdjson/generic/atomparsing.h for fallback */
12716
/* including simdjson/generic/dom_parser_implementation.h for fallback: #include "simdjson/generic/dom_parser_implementation.h" */
12717
/* begin file simdjson/generic/dom_parser_implementation.h for fallback */
12718
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
12719
12720
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12721
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H */
12722
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
12723
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
12724
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12725
12726
namespace simdjson {
12727
namespace fallback {
12728
12729
// expectation: sizeof(open_container) = 64/8.
12730
struct open_container {
12731
  uint32_t tape_index; // where, on the tape, does the scope ([,{) begins
12732
  uint32_t count; // how many elements in the scope
12733
}; // struct open_container
12734
12735
static_assert(sizeof(open_container) == 64/8, "Open container must be 64 bits");
12736
12737
class dom_parser_implementation final : public internal::dom_parser_implementation {
12738
public:
12739
  /** Tape location of each open { or [ */
12740
  std::unique_ptr<open_container[]> open_containers{};
12741
  /** Whether each open container is a [ or { */
12742
  std::unique_ptr<bool[]> is_array{};
12743
  /** Buffer passed to stage 1 */
12744
  const uint8_t *buf{};
12745
  /** Length passed to stage 1 */
12746
  size_t len{0};
12747
  /** Document passed to stage 2 */
12748
  dom::document *doc{};
12749
12750
  inline dom_parser_implementation() noexcept;
12751
  inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
12752
  inline dom_parser_implementation &operator=(dom_parser_implementation &&other) noexcept;
12753
  dom_parser_implementation(const dom_parser_implementation &) = delete;
12754
  dom_parser_implementation &operator=(const dom_parser_implementation &) = delete;
12755
12756
  simdjson_warn_unused error_code parse(const uint8_t *buf, size_t len, dom::document &doc) noexcept final;
12757
  simdjson_warn_unused error_code stage1(const uint8_t *buf, size_t len, stage1_mode partial) noexcept final;
12758
  simdjson_warn_unused error_code stage2(dom::document &doc) noexcept final;
12759
  simdjson_warn_unused error_code stage2_next(dom::document &doc) noexcept final;
12760
  simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept final;
12761
  simdjson_warn_unused uint8_t *parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept final;
12762
  inline simdjson_warn_unused error_code set_capacity(size_t capacity) noexcept final;
12763
  inline simdjson_warn_unused error_code set_max_depth(size_t max_depth) noexcept final;
12764
private:
12765
  simdjson_inline simdjson_warn_unused error_code set_capacity_stage1(size_t capacity);
12766
12767
};
12768
12769
} // namespace fallback
12770
} // namespace simdjson
12771
12772
namespace simdjson {
12773
namespace fallback {
12774
12775
inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
12776
inline dom_parser_implementation::dom_parser_implementation(dom_parser_implementation &&other) noexcept = default;
12777
0
inline dom_parser_implementation &dom_parser_implementation::operator=(dom_parser_implementation &&other) noexcept = default;
12778
12779
// Leaving these here so they can be inlined if so desired
12780
0
inline simdjson_warn_unused error_code dom_parser_implementation::set_capacity(size_t capacity) noexcept {
12781
0
  if(capacity > SIMDJSON_MAXSIZE_BYTES) { return CAPACITY; }
12782
0
  // Stage 1 index output
12783
0
  size_t max_structures = SIMDJSON_ROUNDUP_N(capacity, 64) + 2 + 7;
12784
0
  structural_indexes.reset( new (std::nothrow) uint32_t[max_structures] );
12785
0
  if (!structural_indexes) { _capacity = 0; return MEMALLOC; }
12786
0
  structural_indexes[0] = 0;
12787
0
  n_structural_indexes = 0;
12788
0
12789
0
  _capacity = capacity;
12790
0
  return SUCCESS;
12791
0
}
12792
12793
0
inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(size_t max_depth) noexcept {
12794
0
  // Stage 2 stacks
12795
0
  open_containers.reset(new (std::nothrow) open_container[max_depth]);
12796
0
  is_array.reset(new (std::nothrow) bool[max_depth]);
12797
0
  if (!is_array || !open_containers) { _max_depth = 0; return MEMALLOC; }
12798
0
12799
0
  _max_depth = max_depth;
12800
0
  return SUCCESS;
12801
0
}
12802
12803
} // namespace fallback
12804
} // namespace simdjson
12805
12806
#endif // SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
12807
/* end file simdjson/generic/dom_parser_implementation.h for fallback */
12808
/* including simdjson/generic/implementation_simdjson_result_base.h for fallback: #include "simdjson/generic/implementation_simdjson_result_base.h" */
12809
/* begin file simdjson/generic/implementation_simdjson_result_base.h for fallback */
12810
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
12811
12812
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12813
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H */
12814
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
12815
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12816
12817
namespace simdjson {
12818
namespace fallback {
12819
12820
// This is a near copy of include/error.h's implementation_simdjson_result_base, except it doesn't use std::pair
12821
// so we can avoid inlining errors
12822
// TODO reconcile these!
12823
/**
12824
 * The result of a simdjson operation that could fail.
12825
 *
12826
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
12827
 *
12828
 * This is a base class for implementations that want to add functions to the result type for
12829
 * chaining.
12830
 *
12831
 * Override like:
12832
 *
12833
 *   struct simdjson_result<T> : public internal::implementation_simdjson_result_base<T> {
12834
 *     simdjson_result() noexcept : internal::implementation_simdjson_result_base<T>() {}
12835
 *     simdjson_result(error_code error) noexcept : internal::implementation_simdjson_result_base<T>(error) {}
12836
 *     simdjson_result(T &&value) noexcept : internal::implementation_simdjson_result_base<T>(std::forward(value)) {}
12837
 *     simdjson_result(T &&value, error_code error) noexcept : internal::implementation_simdjson_result_base<T>(value, error) {}
12838
 *     // Your extra methods here
12839
 *   }
12840
 *
12841
 * Then any method returning simdjson_result<T> will be chainable with your methods.
12842
 */
12843
template<typename T>
12844
struct implementation_simdjson_result_base {
12845
12846
  /**
12847
   * Create a new empty result with error = UNINITIALIZED.
12848
   */
12849
  simdjson_inline implementation_simdjson_result_base() noexcept = default;
12850
12851
  /**
12852
   * Create a new error result.
12853
   */
12854
  simdjson_inline implementation_simdjson_result_base(error_code error) noexcept;
12855
12856
  /**
12857
   * Create a new successful result.
12858
   */
12859
  simdjson_inline implementation_simdjson_result_base(T &&value) noexcept;
12860
12861
  /**
12862
   * Create a new result with both things (use if you don't want to branch when creating the result).
12863
   */
12864
  simdjson_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
12865
12866
  /**
12867
   * Move the value and the error to the provided variables.
12868
   *
12869
   * @param value The variable to assign the value to. May not be set if there is an error.
12870
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
12871
   */
12872
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
12873
12874
  /**
12875
   * Move the value to the provided variable.
12876
   *
12877
   * @param value The variable to assign the value to. May not be set if there is an error.
12878
   */
12879
  simdjson_inline error_code get(T &value) && noexcept;
12880
12881
  /**
12882
   * The error.
12883
   */
12884
  simdjson_inline error_code error() const noexcept;
12885
12886
#if SIMDJSON_EXCEPTIONS
12887
12888
  /**
12889
   * Get the result value.
12890
   *
12891
   * @throw simdjson_error if there was an error.
12892
   */
12893
  simdjson_inline T& value() & noexcept(false);
12894
12895
  /**
12896
   * Take the result value (move it).
12897
   *
12898
   * @throw simdjson_error if there was an error.
12899
   */
12900
  simdjson_inline T&& value() && noexcept(false);
12901
12902
  /**
12903
   * Take the result value (move it).
12904
   *
12905
   * @throw simdjson_error if there was an error.
12906
   */
12907
  simdjson_inline T&& take_value() && noexcept(false);
12908
12909
  /**
12910
   * Cast to the value (will throw on error).
12911
   *
12912
   * @throw simdjson_error if there was an error.
12913
   */
12914
  simdjson_inline operator T&&() && noexcept(false);
12915
12916
12917
#endif // SIMDJSON_EXCEPTIONS
12918
12919
  /**
12920
   * Get the result value. This function is safe if and only
12921
   * the error() method returns a value that evaluates to false.
12922
   */
12923
  simdjson_inline const T& value_unsafe() const& noexcept;
12924
  /**
12925
   * Get the result value. This function is safe if and only
12926
   * the error() method returns a value that evaluates to false.
12927
   */
12928
  simdjson_inline T& value_unsafe() & noexcept;
12929
  /**
12930
   * Take the result value (move it). This function is safe if and only
12931
   * the error() method returns a value that evaluates to false.
12932
   */
12933
  simdjson_inline T&& value_unsafe() && noexcept;
12934
protected:
12935
  /** users should never directly access first and second. **/
12936
  T first{}; /** Users should never directly access 'first'. **/
12937
  error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
12938
}; // struct implementation_simdjson_result_base
12939
12940
} // namespace fallback
12941
} // namespace simdjson
12942
12943
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
12944
/* end file simdjson/generic/implementation_simdjson_result_base.h for fallback */
12945
/* including simdjson/generic/numberparsing.h for fallback: #include "simdjson/generic/numberparsing.h" */
12946
/* begin file simdjson/generic/numberparsing.h for fallback */
12947
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
12948
12949
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
12950
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_NUMBERPARSING_H */
12951
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
12952
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
12953
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
12954
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
12955
12956
#include <limits>
12957
#include <ostream>
12958
#include <cstring>
12959
12960
namespace simdjson {
12961
namespace fallback {
12962
namespace numberparsing {
12963
12964
#ifdef JSON_TEST_NUMBERS
12965
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
12966
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
12967
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
12968
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
12969
#define BIGINT_NUMBER(SRC) (found_invalid_number((SRC)), BIGINT_ERROR)
12970
#else
12971
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
12972
#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
12973
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
12974
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
12975
#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
12976
#endif
12977
12978
namespace {
12979
12980
// Convert a mantissa, an exponent and a sign bit into an ieee64 double.
12981
// The real_exponent needs to be in [0, 2046] (technically real_exponent = 2047 would be acceptable).
12982
// The mantissa should be in [0,1<<53). The bit at index (1ULL << 52) while be zeroed.
12983
0
simdjson_inline double to_double(uint64_t mantissa, uint64_t real_exponent, bool negative) {
12984
0
    double d;
12985
0
    mantissa &= ~(1ULL << 52);
12986
0
    mantissa |= real_exponent << 52;
12987
0
    mantissa |= ((static_cast<uint64_t>(negative)) << 63);
12988
0
    std::memcpy(&d, &mantissa, sizeof(d));
12989
0
    return d;
12990
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::to_double(unsigned long, unsigned long, bool)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::to_double(unsigned long, unsigned long, bool)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::to_double(unsigned long, unsigned long, bool)
12991
12992
// Attempts to compute i * 10^(power) exactly; and if "negative" is
12993
// true, negate the result.
12994
// This function will only work in some cases, when it does not work, success is
12995
// set to false. This should work *most of the time* (like 99% of the time).
12996
// We assume that power is in the [smallest_power,
12997
// largest_power] interval: the caller is responsible for this check.
12998
0
simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, double &d) {
12999
0
  // we start with a fast path
13000
0
  // It was described in
13001
0
  // Clinger WD. How to read floating point numbers accurately.
13002
0
  // ACM SIGPLAN Notices. 1990
13003
0
#ifndef FLT_EVAL_METHOD
13004
0
#error "FLT_EVAL_METHOD should be defined, please include cfloat."
13005
0
#endif
13006
0
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
13007
0
  // We cannot be certain that x/y is rounded to nearest.
13008
0
  if (0 <= power && power <= 22 && i <= 9007199254740991)
13009
0
#else
13010
0
  if (-22 <= power && power <= 22 && i <= 9007199254740991)
13011
0
#endif
13012
0
  {
13013
0
    // convert the integer into a double. This is lossless since
13014
0
    // 0 <= i <= 2^53 - 1.
13015
0
    d = double(i);
13016
0
    //
13017
0
    // The general idea is as follows.
13018
0
    // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
13019
0
    // 1) Both s and p can be represented exactly as 64-bit floating-point
13020
0
    // values
13021
0
    // (binary64).
13022
0
    // 2) Because s and p can be represented exactly as floating-point values,
13023
0
    // then s * p
13024
0
    // and s / p will produce correctly rounded values.
13025
0
    //
13026
0
    if (power < 0) {
13027
0
      d = d / simdjson::internal::power_of_ten[-power];
13028
0
    } else {
13029
0
      d = d * simdjson::internal::power_of_ten[power];
13030
0
    }
13031
0
    if (negative) {
13032
0
      d = -d;
13033
0
    }
13034
0
    return true;
13035
0
  }
13036
0
  // When 22 < power && power <  22 + 16, we could
13037
0
  // hope for another, secondary fast path.  It was
13038
0
  // described by David M. Gay in  "Correctly rounded
13039
0
  // binary-decimal and decimal-binary conversions." (1990)
13040
0
  // If you need to compute i * 10^(22 + x) for x < 16,
13041
0
  // first compute i * 10^x, if you know that result is exact
13042
0
  // (e.g., when i * 10^x < 2^53),
13043
0
  // then you can still proceed and do (i * 10^x) * 10^22.
13044
0
  // Is this worth your time?
13045
0
  // You need  22 < power *and* power <  22 + 16 *and* (i * 10^(x-22) < 2^53)
13046
0
  // for this second fast path to work.
13047
0
  // If you you have 22 < power *and* power <  22 + 16, and then you
13048
0
  // optimistically compute "i * 10^(x-22)", there is still a chance that you
13049
0
  // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
13050
0
  // this optimization maybe less common than we would like. Source:
13051
0
  // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
13052
0
  // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
13053
0
13054
0
  // The fast path has now failed, so we are failing back on the slower path.
13055
0
13056
0
  // In the slow path, we need to adjust i so that it is > 1<<63 which is always
13057
0
  // possible, except if i == 0, so we handle i == 0 separately.
13058
0
  if(i == 0) {
13059
0
    d = negative ? -0.0 : 0.0;
13060
0
    return true;
13061
0
  }
13062
0
13063
0
13064
0
  // The exponent is 1024 + 63 + power
13065
0
  //     + floor(log(5**power)/log(2)).
13066
0
  // The 1024 comes from the ieee64 standard.
13067
0
  // The 63 comes from the fact that we use a 64-bit word.
13068
0
  //
13069
0
  // Computing floor(log(5**power)/log(2)) could be
13070
0
  // slow. Instead we use a fast function.
13071
0
  //
13072
0
  // For power in (-400,350), we have that
13073
0
  // (((152170 + 65536) * power ) >> 16);
13074
0
  // is equal to
13075
0
  //  floor(log(5**power)/log(2)) + power when power >= 0
13076
0
  // and it is equal to
13077
0
  //  ceil(log(5**-power)/log(2)) + power when power < 0
13078
0
  //
13079
0
  // The 65536 is (1<<16) and corresponds to
13080
0
  // (65536 * power) >> 16 ---> power
13081
0
  //
13082
0
  // ((152170 * power ) >> 16) is equal to
13083
0
  // floor(log(5**power)/log(2))
13084
0
  //
13085
0
  // Note that this is not magic: 152170/(1<<16) is
13086
0
  // approximatively equal to log(5)/log(2).
13087
0
  // The 1<<16 value is a power of two; we could use a
13088
0
  // larger power of 2 if we wanted to.
13089
0
  //
13090
0
  int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
13091
0
13092
0
13093
0
  // We want the most significant bit of i to be 1. Shift if needed.
13094
0
  int lz = leading_zeroes(i);
13095
0
  i <<= lz;
13096
0
13097
0
13098
0
  // We are going to need to do some 64-bit arithmetic to get a precise product.
13099
0
  // We use a table lookup approach.
13100
0
  // It is safe because
13101
0
  // power >= smallest_power
13102
0
  // and power <= largest_power
13103
0
  // We recover the mantissa of the power, it has a leading 1. It is always
13104
0
  // rounded down.
13105
0
  //
13106
0
  // We want the most significant 64 bits of the product. We know
13107
0
  // this will be non-zero because the most significant bit of i is
13108
0
  // 1.
13109
0
  const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
13110
0
  // Optimization: It may be that materializing the index as a variable might confuse some compilers and prevent effective complex-addressing loads. (Done for code clarity.)
13111
0
  //
13112
0
  // The full_multiplication function computes the 128-bit product of two 64-bit words
13113
0
  // with a returned value of type value128 with a "low component" corresponding to the
13114
0
  // 64-bit least significant bits of the product and with a "high component" corresponding
13115
0
  // to the 64-bit most significant bits of the product.
13116
0
  simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
13117
0
  // Both i and power_of_five_128[index] have their most significant bit set to 1 which
13118
0
  // implies that the either the most or the second most significant bit of the product
13119
0
  // is 1. We pack values in this manner for efficiency reasons: it maximizes the use
13120
0
  // we make of the product. It also makes it easy to reason about the product: there
13121
0
  // is 0 or 1 leading zero in the product.
13122
0
13123
0
  // Unless the least significant 9 bits of the high (64-bit) part of the full
13124
0
  // product are all 1s, then we know that the most significant 55 bits are
13125
0
  // exact and no further work is needed. Having 55 bits is necessary because
13126
0
  // we need 53 bits for the mantissa but we have to have one rounding bit and
13127
0
  // we can waste a bit if the most significant bit of the product is zero.
13128
0
  if((firstproduct.high & 0x1FF) == 0x1FF) {
13129
0
    // We want to compute i * 5^q, but only care about the top 55 bits at most.
13130
0
    // Consider the scenario where q>=0. Then 5^q may not fit in 64-bits. Doing
13131
0
    // the full computation is wasteful. So we do what is called a "truncated
13132
0
    // multiplication".
13133
0
    // We take the most significant 64-bits, and we put them in
13134
0
    // power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
13135
0
    // to the desired approximation using one multiplication. Sometimes it does not suffice.
13136
0
    // Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
13137
0
    // then we get a better approximation to i * 5^q.
13138
0
    //
13139
0
    // That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
13140
0
    // more complicated.
13141
0
    //
13142
0
    // There is an extra layer of complexity in that we need more than 55 bits of
13143
0
    // accuracy in the round-to-even scenario.
13144
0
    //
13145
0
    // The full_multiplication function computes the 128-bit product of two 64-bit words
13146
0
    // with a returned value of type value128 with a "low component" corresponding to the
13147
0
    // 64-bit least significant bits of the product and with a "high component" corresponding
13148
0
    // to the 64-bit most significant bits of the product.
13149
0
    simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
13150
0
    firstproduct.low += secondproduct.high;
13151
0
    if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
13152
0
    // As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
13153
0
    // Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
13154
0
    // is sufficiently accurate, and more computation is not needed.
13155
0
  }
13156
0
  uint64_t lower = firstproduct.low;
13157
0
  uint64_t upper = firstproduct.high;
13158
0
  // The final mantissa should be 53 bits with a leading 1.
13159
0
  // We shift it so that it occupies 54 bits with a leading 1.
13160
0
  ///////
13161
0
  uint64_t upperbit = upper >> 63;
13162
0
  uint64_t mantissa = upper >> (upperbit + 9);
13163
0
  lz += int(1 ^ upperbit);
13164
0
13165
0
  // Here we have mantissa < (1<<54).
13166
0
  int64_t real_exponent = exponent - lz;
13167
0
  if (simdjson_unlikely(real_exponent <= 0)) { // we have a subnormal?
13168
0
    // Here have that real_exponent <= 0 so -real_exponent >= 0
13169
0
    if(-real_exponent + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
13170
0
      d = negative ? -0.0 : 0.0;
13171
0
      return true;
13172
0
    }
13173
0
    // next line is safe because -real_exponent + 1 < 0
13174
0
    mantissa >>= -real_exponent + 1;
13175
0
    // Thankfully, we can't have both "round-to-even" and subnormals because
13176
0
    // "round-to-even" only occurs for powers close to 0.
13177
0
    mantissa += (mantissa & 1); // round up
13178
0
    mantissa >>= 1;
13179
0
    // There is a weird scenario where we don't have a subnormal but just.
13180
0
    // Suppose we start with 2.2250738585072013e-308, we end up
13181
0
    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
13182
0
    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
13183
0
    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
13184
0
    // subnormal, but we can only know this after rounding.
13185
0
    // So we only declare a subnormal if we are smaller than the threshold.
13186
0
    real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
13187
0
    d = to_double(mantissa, real_exponent, negative);
13188
0
    return true;
13189
0
  }
13190
0
  // We have to round to even. The "to even" part
13191
0
  // is only a problem when we are right in between two floats
13192
0
  // which we guard against.
13193
0
  // If we have lots of trailing zeros, we may fall right between two
13194
0
  // floating-point values.
13195
0
  //
13196
0
  // The round-to-even cases take the form of a number 2m+1 which is in (2^53,2^54]
13197
0
  // times a power of two. That is, it is right between a number with binary significand
13198
0
  // m and another number with binary significand m+1; and it must be the case
13199
0
  // that it cannot be represented by a float itself.
13200
0
  //
13201
0
  // We must have that w * 10 ^q == (2m+1) * 2^p for some power of two 2^p.
13202
0
  // Recall that 10^q = 5^q * 2^q.
13203
0
  // When q >= 0, we must have that (2m+1) is divible by 5^q, so 5^q <= 2^54. We have that
13204
0
  //  5^23 <=  2^54 and it is the last power of five to qualify, so q <= 23.
13205
0
  // When q<0, we have  w  >=  (2m+1) x 5^{-q}.  We must have that w<2^{64} so
13206
0
  // (2m+1) x 5^{-q} < 2^{64}. We have that 2m+1>2^{53}. Hence, we must have
13207
0
  // 2^{53} x 5^{-q} < 2^{64}.
13208
0
  // Hence we have 5^{-q} < 2^{11}$ or q>= -4.
13209
0
  //
13210
0
  // We require lower <= 1 and not lower == 0 because we could not prove that
13211
0
  // that lower == 0 is implied; but we could prove that lower <= 1 is a necessary and sufficient test.
13212
0
  if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
13213
0
    if((mantissa  << (upperbit + 64 - 53 - 2)) ==  upper) {
13214
0
      mantissa &= ~1;             // flip it so that we do not round up
13215
0
    }
13216
0
  }
13217
0
13218
0
  mantissa += mantissa & 1;
13219
0
  mantissa >>= 1;
13220
0
13221
0
  // Here we have mantissa < (1<<53), unless there was an overflow
13222
0
  if (mantissa >= (1ULL << 53)) {
13223
0
    //////////
13224
0
    // This will happen when parsing values such as 7.2057594037927933e+16
13225
0
    ////////
13226
0
    mantissa = (1ULL << 52);
13227
0
    real_exponent++;
13228
0
  }
13229
0
  mantissa &= ~(1ULL << 52);
13230
0
  // we have to check that real_exponent is in range, otherwise we bail out
13231
0
  if (simdjson_unlikely(real_exponent > 2046)) {
13232
0
    // We have an infinite value!!! We could actually throw an error here if we could.
13233
0
    return false;
13234
0
  }
13235
0
  d = to_double(mantissa, real_exponent, negative);
13236
0
  return true;
13237
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::compute_float_64(long, unsigned long, bool, double&)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::compute_float_64(long, unsigned long, bool, double&)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::compute_float_64(long, unsigned long, bool, double&)
13238
13239
// We call a fallback floating-point parser that might be slow. Note
13240
// it will accept JSON numbers, but the JSON spec. is more restrictive so
13241
// before you call parse_float_fallback, you need to have validated the input
13242
// string with the JSON grammar.
13243
// It will return an error (false) if the parsed number is infinite.
13244
// The string parsing itself always succeeds. We know that there is at least
13245
// one digit.
13246
0
static bool parse_float_fallback(const uint8_t *ptr, double *outDouble) {
13247
0
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr));
13248
0
  // We do not accept infinite values.
13249
0
13250
0
  // Detecting finite values in a portable manner is ridiculously hard, ideally
13251
0
  // we would want to do:
13252
0
  // return !std::isfinite(*outDouble);
13253
0
  // but that mysteriously fails under legacy/old libc++ libraries, see
13254
0
  // https://github.com/simdjson/simdjson/issues/1286
13255
0
  //
13256
0
  // Therefore, fall back to this solution (the extra parens are there
13257
0
  // to handle that max may be a macro on windows).
13258
0
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
13259
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_float_fallback(unsigned char const*, double*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_float_fallback(unsigned char const*, double*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_float_fallback(unsigned char const*, double*)
13260
13261
0
static bool parse_float_fallback(const uint8_t *ptr, const uint8_t *end_ptr, double *outDouble) {
13262
0
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr), reinterpret_cast<const char *>(end_ptr));
13263
0
  // We do not accept infinite values.
13264
0
13265
0
  // Detecting finite values in a portable manner is ridiculously hard, ideally
13266
0
  // we would want to do:
13267
0
  // return !std::isfinite(*outDouble);
13268
0
  // but that mysteriously fails under legacy/old libc++ libraries, see
13269
0
  // https://github.com/simdjson/simdjson/issues/1286
13270
0
  //
13271
0
  // Therefore, fall back to this solution (the extra parens are there
13272
0
  // to handle that max may be a macro on windows).
13273
0
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
13274
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_float_fallback(unsigned char const*, unsigned char const*, double*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_float_fallback(unsigned char const*, unsigned char const*, double*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_float_fallback(unsigned char const*, unsigned char const*, double*)
13275
13276
// check quickly whether the next 8 chars are made of digits
13277
// at a glance, it looks better than Mula's
13278
// http://0x80.pl/articles/swar-digits-validate.html
13279
0
simdjson_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
13280
0
  uint64_t val;
13281
0
  // this can read up to 7 bytes beyond the buffer size, but we require
13282
0
  // SIMDJSON_PADDING of padding
13283
0
  static_assert(7 <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be bigger than 7");
13284
0
  std::memcpy(&val, chars, 8);
13285
0
  // a branchy method might be faster:
13286
0
  // return (( val & 0xF0F0F0F0F0F0F0F0 ) == 0x3030303030303030)
13287
0
  //  && (( (val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0 ) ==
13288
0
  //  0x3030303030303030);
13289
0
  return (((val & 0xF0F0F0F0F0F0F0F0) |
13290
0
           (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
13291
0
          0x3333333333333333);
13292
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_made_of_eight_digits_fast(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_made_of_eight_digits_fast(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_made_of_eight_digits_fast(unsigned char const*)
13293
13294
template<typename I>
13295
SIMDJSON_NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
13296
0
simdjson_inline bool parse_digit(const uint8_t c, I &i) {
13297
0
  const uint8_t digit = static_cast<uint8_t>(c - '0');
13298
0
  if (digit > 9) {
13299
0
    return false;
13300
0
  }
13301
0
  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
13302
0
  i = 10 * i + digit; // might overflow, we will handle the overflow later
13303
0
  return true;
13304
0
}
Unexecuted instantiation: node_metadata.cc:bool simdjson::fallback::numberparsing::(anonymous namespace)::parse_digit<unsigned long>(unsigned char, unsigned long&)
Unexecuted instantiation: node_metadata.cc:bool simdjson::fallback::numberparsing::(anonymous namespace)::parse_digit<long>(unsigned char, long&)
Unexecuted instantiation: node_modules.cc:bool simdjson::fallback::numberparsing::(anonymous namespace)::parse_digit<unsigned long>(unsigned char, unsigned long&)
Unexecuted instantiation: node_modules.cc:bool simdjson::fallback::numberparsing::(anonymous namespace)::parse_digit<long>(unsigned char, long&)
Unexecuted instantiation: node_snapshotable.cc:bool simdjson::fallback::numberparsing::(anonymous namespace)::parse_digit<unsigned long>(unsigned char, unsigned long&)
Unexecuted instantiation: node_snapshotable.cc:bool simdjson::fallback::numberparsing::(anonymous namespace)::parse_digit<long>(unsigned char, long&)
13305
13306
0
simdjson_inline bool is_digit(const uint8_t c) {
13307
0
  return static_cast<uint8_t>(c - '0') <= 9;
13308
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_digit(unsigned char)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_digit(unsigned char)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_digit(unsigned char)
13309
13310
0
simdjson_inline error_code parse_decimal_after_separator(simdjson_unused const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
13311
0
  // we continue with the fiction that we have an integer. If the
13312
0
  // floating point number is representable as x * 10^z for some integer
13313
0
  // z that fits in 53 bits, then we will be able to convert back the
13314
0
  // the integer into a float in a lossless manner.
13315
0
  const uint8_t *const first_after_period = p;
13316
0
13317
0
#ifdef SIMDJSON_SWAR_NUMBER_PARSING
13318
0
#if SIMDJSON_SWAR_NUMBER_PARSING
13319
0
  // this helps if we have lots of decimals!
13320
0
  // this turns out to be frequent enough.
13321
0
  if (is_made_of_eight_digits_fast(p)) {
13322
0
    i = i * 100000000 + parse_eight_digits_unrolled(p);
13323
0
    p += 8;
13324
0
  }
13325
0
#endif // SIMDJSON_SWAR_NUMBER_PARSING
13326
0
#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
13327
0
  // Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
13328
0
  if (parse_digit(*p, i)) { ++p; }
13329
0
  while (parse_digit(*p, i)) { p++; }
13330
0
  exponent = first_after_period - p;
13331
0
  // Decimal without digits (123.) is illegal
13332
0
  if (exponent == 0) {
13333
0
    return INVALID_NUMBER(src);
13334
0
  }
13335
0
  return SUCCESS;
13336
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_decimal_after_separator(unsigned char const*, unsigned char const*&, unsigned long&, long&)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_decimal_after_separator(unsigned char const*, unsigned char const*&, unsigned long&, long&)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_decimal_after_separator(unsigned char const*, unsigned char const*&, unsigned long&, long&)
13337
13338
0
simdjson_inline error_code parse_exponent(simdjson_unused const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
13339
0
  // Exp Sign: -123.456e[-]78
13340
0
  bool neg_exp = ('-' == *p);
13341
0
  if (neg_exp || '+' == *p) { p++; } // Skip + as well
13342
0
13343
0
  // Exponent: -123.456e-[78]
13344
0
  auto start_exp = p;
13345
0
  int64_t exp_number = 0;
13346
0
  while (parse_digit(*p, exp_number)) { ++p; }
13347
0
  // It is possible for parse_digit to overflow.
13348
0
  // In particular, it could overflow to INT64_MIN, and we cannot do - INT64_MIN.
13349
0
  // Thus we *must* check for possible overflow before we negate exp_number.
13350
0
13351
0
  // Performance notes: it may seem like combining the two "simdjson_unlikely checks" below into
13352
0
  // a single simdjson_unlikely path would be faster. The reasoning is sound, but the compiler may
13353
0
  // not oblige and may, in fact, generate two distinct paths in any case. It might be
13354
0
  // possible to do uint64_t(p - start_exp - 1) >= 18 but it could end up trading off
13355
0
  // instructions for a simdjson_likely branch, an unconclusive gain.
13356
0
13357
0
  // If there were no digits, it's an error.
13358
0
  if (simdjson_unlikely(p == start_exp)) {
13359
0
    return INVALID_NUMBER(src);
13360
0
  }
13361
0
  // We have a valid positive exponent in exp_number at this point, except that
13362
0
  // it may have overflowed.
13363
0
13364
0
  // If there were more than 18 digits, we may have overflowed the integer. We have to do
13365
0
  // something!!!!
13366
0
  if (simdjson_unlikely(p > start_exp+18)) {
13367
0
    // Skip leading zeroes: 1e000000000000000000001 is technically valid and does not overflow
13368
0
    while (*start_exp == '0') { start_exp++; }
13369
0
    // 19 digits could overflow int64_t and is kind of absurd anyway. We don't
13370
0
    // support exponents smaller than -999,999,999,999,999,999 and bigger
13371
0
    // than 999,999,999,999,999,999.
13372
0
    // We can truncate.
13373
0
    // Note that 999999999999999999 is assuredly too large. The maximal ieee64 value before
13374
0
    // infinity is ~1.8e308. The smallest subnormal is ~5e-324. So, actually, we could
13375
0
    // truncate at 324.
13376
0
    // Note that there is no reason to fail per se at this point in time.
13377
0
    // E.g., 0e999999999999999999999 is a fine number.
13378
0
    if (p > start_exp+18) { exp_number = 999999999999999999; }
13379
0
  }
13380
0
  // At this point, we know that exp_number is a sane, positive, signed integer.
13381
0
  // It is <= 999,999,999,999,999,999. As long as 'exponent' is in
13382
0
  // [-8223372036854775808, 8223372036854775808], we won't overflow. Because 'exponent'
13383
0
  // is bounded in magnitude by the size of the JSON input, we are fine in this universe.
13384
0
  // To sum it up: the next line should never overflow.
13385
0
  exponent += (neg_exp ? -exp_number : exp_number);
13386
0
  return SUCCESS;
13387
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_exponent(unsigned char const*, unsigned char const*&, long&)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_exponent(unsigned char const*, unsigned char const*&, long&)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_exponent(unsigned char const*, unsigned char const*&, long&)
13388
13389
0
simdjson_inline bool check_if_integer(const uint8_t *const src, size_t max_length) {
13390
0
  const uint8_t *const srcend = src + max_length;
13391
0
  bool negative = (*src == '-'); // we can always read at least one character after the '-'
13392
0
  const uint8_t *p = src + uint8_t(negative);
13393
0
  if(p == srcend) { return false; }
13394
0
  if(*p == '0') {
13395
0
    ++p;
13396
0
    if(p == srcend) { return true; }
13397
0
    if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
13398
0
    return true;
13399
0
  }
13400
0
  while(p != srcend && is_digit(*p)) { ++p; }
13401
0
  if(p == srcend) { return true; }
13402
0
  if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
13403
0
  return true;
13404
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::check_if_integer(unsigned char const*, unsigned long)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::check_if_integer(unsigned char const*, unsigned long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::check_if_integer(unsigned char const*, unsigned long)
13405
13406
0
simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
13407
0
  // It is possible that the integer had an overflow.
13408
0
  // We have to handle the case where we have 0.0000somenumber.
13409
0
  const uint8_t *start = start_digits;
13410
0
  while ((*start == '0') || (*start == '.')) { ++start; }
13411
0
  // we over-decrement by one when there is a '.'
13412
0
  return digit_count - size_t(start - start_digits);
13413
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::significant_digits(unsigned char const*, unsigned long)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::significant_digits(unsigned char const*, unsigned long)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::significant_digits(unsigned char const*, unsigned long)
13414
13415
} // unnamed namespace
13416
13417
/** @private */
13418
0
static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
13419
0
  if (parse_float_fallback(src, answer)) {
13420
0
    return SUCCESS;
13421
0
  }
13422
0
  return INVALID_NUMBER(src);
13423
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::slow_float_parsing(unsigned char const*, double*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::slow_float_parsing(unsigned char const*, double*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::slow_float_parsing(unsigned char const*, double*)
13424
13425
/** @private */
13426
template<typename W>
13427
0
simdjson_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
13428
0
  // If we frequently had to deal with long strings of digits,
13429
0
  // we could extend our code by using a 128-bit integer instead
13430
0
  // of a 64-bit integer. However, this is uncommon in practice.
13431
0
  //
13432
0
  // 9999999999999999999 < 2**64 so we can accommodate 19 digits.
13433
0
  // If we have a decimal separator, then digit_count - 1 is the number of digits, but we
13434
0
  // may not have a decimal separator!
13435
0
  if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
13436
0
    // Ok, chances are good that we had an overflow!
13437
0
    // this is almost never going to get called!!!
13438
0
    // we start anew, going slowly!!!
13439
0
    // This will happen in the following examples:
13440
0
    // 10000000000000000000000000000000000000000000e+308
13441
0
    // 3.1415926535897932384626433832795028841971693993751
13442
0
    //
13443
0
    // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
13444
0
    // reference to it, it would force it to be stored in memory, preventing the compiler from
13445
0
    // picking it apart and putting into registers. i.e. if we pass it as reference,
13446
0
    // it gets slow.
13447
0
    double d;
13448
0
    error_code error = slow_float_parsing(src, &d);
13449
0
    writer.append_double(d);
13450
0
    return error;
13451
0
  }
13452
0
  // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
13453
0
  // way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331
13454
0
  // To future reader: we'd love if someone found a better way, or at least could explain this result!
13455
0
  if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
13456
0
    //
13457
0
    // Important: smallest_power is such that it leads to a zero value.
13458
0
    // Observe that 18446744073709551615e-343 == 0, i.e. (2**64 - 1) e -343 is zero
13459
0
    // so something x 10^-343 goes to zero, but not so with  something x 10^-342.
13460
0
    static_assert(simdjson::internal::smallest_power <= -342, "smallest_power is not small enough");
13461
0
    //
13462
0
    if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
13463
0
      // E.g. Parse "-0.0e-999" into the same value as "-0.0". See https://en.wikipedia.org/wiki/Signed_zero
13464
0
      WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
13465
0
      return SUCCESS;
13466
0
    } else { // (exponent > largest_power) and (i != 0)
13467
0
      // We have, for sure, an infinite value and simdjson refuses to parse infinite values.
13468
0
      return INVALID_NUMBER(src);
13469
0
    }
13470
0
  }
13471
0
  double d;
13472
0
  if (!compute_float_64(exponent, i, negative, d)) {
13473
0
    // we are almost never going to get here.
13474
0
    if (!parse_float_fallback(src, &d)) { return INVALID_NUMBER(src); }
13475
0
  }
13476
0
  WRITE_DOUBLE(d, src, writer);
13477
0
  return SUCCESS;
13478
0
}
13479
13480
// parse the number at src
13481
// define JSON_TEST_NUMBERS for unit testing
13482
//
13483
// It is assumed that the number is followed by a structural ({,},],[) character
13484
// or a white space character. If that is not the case (e.g., when the JSON
13485
// document is made of a single number), then it is necessary to copy the
13486
// content and append a space before calling this function.
13487
//
13488
// Our objective is accurate parsing (ULP of 0) at high speed.
13489
template<typename W>
13490
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer);
13491
13492
// for performance analysis, it is sometimes  useful to skip parsing
13493
#ifdef SIMDJSON_SKIPNUMBERPARSING
13494
13495
template<typename W>
13496
simdjson_inline error_code parse_number(const uint8_t *const, W &writer) {
13497
  writer.append_s64(0);        // always write zero
13498
  return SUCCESS;              // always succeeds
13499
}
13500
13501
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
13502
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
13503
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
13504
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept { return 0; }
13505
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t * const src) noexcept { return 0; }
13506
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * const src) noexcept { return 0; }
13507
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept  { return false; }
13508
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept  { return false; }
13509
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept { return number_type::signed_integer; }
13510
#else
13511
13512
// parse the number at src
13513
// define JSON_TEST_NUMBERS for unit testing
13514
//
13515
// It is assumed that the number is followed by a structural ({,},],[) character
13516
// or a white space character. If that is not the case (e.g., when the JSON
13517
// document is made of a single number), then it is necessary to copy the
13518
// content and append a space before calling this function.
13519
//
13520
// Our objective is accurate parsing (ULP of 0) at high speed.
13521
template<typename W>
13522
0
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) {
13523
0
13524
0
  //
13525
0
  // Check for minus sign
13526
0
  //
13527
0
  bool negative = (*src == '-');
13528
0
  const uint8_t *p = src + uint8_t(negative);
13529
0
13530
0
  //
13531
0
  // Parse the integer part.
13532
0
  //
13533
0
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
13534
0
  const uint8_t *const start_digits = p;
13535
0
  uint64_t i = 0;
13536
0
  while (parse_digit(*p, i)) { p++; }
13537
0
13538
0
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
13539
0
  // Optimization note: size_t is expected to be unsigned.
13540
0
  size_t digit_count = size_t(p - start_digits);
13541
0
  if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
13542
0
13543
0
  //
13544
0
  // Handle floats if there is a . or e (or both)
13545
0
  //
13546
0
  int64_t exponent = 0;
13547
0
  bool is_float = false;
13548
0
  if ('.' == *p) {
13549
0
    is_float = true;
13550
0
    ++p;
13551
0
    SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
13552
0
    digit_count = int(p - start_digits); // used later to guard against overflows
13553
0
  }
13554
0
  if (('e' == *p) || ('E' == *p)) {
13555
0
    is_float = true;
13556
0
    ++p;
13557
0
    SIMDJSON_TRY( parse_exponent(src, p, exponent) );
13558
0
  }
13559
0
  if (is_float) {
13560
0
    const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
13561
0
    SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
13562
0
    if (dirty_end) { return INVALID_NUMBER(src); }
13563
0
    return SUCCESS;
13564
0
  }
13565
0
13566
0
  // The longest negative 64-bit number is 19 digits.
13567
0
  // The longest positive 64-bit number is 20 digits.
13568
0
  // We do it this way so we don't trigger this branch unless we must.
13569
0
  size_t longest_digit_count = negative ? 19 : 20;
13570
0
  if (digit_count > longest_digit_count) { return BIGINT_NUMBER(src); }
13571
0
  if (digit_count == longest_digit_count) {
13572
0
    if (negative) {
13573
0
      // Anything negative above INT64_MAX+1 is invalid
13574
0
      if (i > uint64_t(INT64_MAX)+1) { return BIGINT_NUMBER(src);  }
13575
0
      WRITE_INTEGER(~i+1, src, writer);
13576
0
      if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
13577
0
      return SUCCESS;
13578
0
    // Positive overflow check:
13579
0
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
13580
0
    //   biggest uint64_t.
13581
0
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
13582
0
    //   If we got here, it's a 20 digit number starting with the digit "1".
13583
0
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
13584
0
    //   than 1,553,255,926,290,448,384.
13585
0
    // - That is smaller than the smallest possible 20-digit number the user could write:
13586
0
    //   10,000,000,000,000,000,000.
13587
0
    // - Therefore, if the number is positive and lower than that, it's overflow.
13588
0
    // - The value we are looking at is less than or equal to INT64_MAX.
13589
0
    //
13590
0
    }  else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
13591
0
  }
13592
0
13593
0
  // Write unsigned if it does not fit in a signed integer.
13594
0
  if (i > uint64_t(INT64_MAX)) {
13595
0
    WRITE_UNSIGNED(i, src, writer);
13596
0
  } else {
13597
0
    WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
13598
0
  }
13599
0
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
13600
0
  return SUCCESS;
13601
0
}
13602
13603
// Inlineable functions
13604
namespace {
13605
13606
// This table can be used to characterize the final character of an integer
13607
// string. For JSON structural character and allowable white space characters,
13608
// we return SUCCESS. For 'e', '.' and 'E', we return INCORRECT_TYPE. Otherwise
13609
// we return NUMBER_ERROR.
13610
// Optimization note: we could easily reduce the size of the table by half (to 128)
13611
// at the cost of an extra branch.
13612
// Optimization note: we want the values to use at most 8 bits (not, e.g., 32 bits):
13613
static_assert(error_code(uint8_t(NUMBER_ERROR))== NUMBER_ERROR, "bad NUMBER_ERROR cast");
13614
static_assert(error_code(uint8_t(SUCCESS))== SUCCESS, "bad NUMBER_ERROR cast");
13615
static_assert(error_code(uint8_t(INCORRECT_TYPE))== INCORRECT_TYPE, "bad NUMBER_ERROR cast");
13616
13617
const uint8_t integer_string_finisher[256] = {
13618
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13619
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
13620
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
13621
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13622
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13623
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13624
    NUMBER_ERROR, NUMBER_ERROR,   SUCCESS,      NUMBER_ERROR, NUMBER_ERROR,
13625
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13626
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
13627
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13628
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13629
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
13630
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13631
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, INCORRECT_TYPE,
13632
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13633
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13634
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13635
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13636
    NUMBER_ERROR, SUCCESS,        NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
13637
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13638
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13639
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13640
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13641
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13642
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
13643
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13644
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13645
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13646
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13647
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13648
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13649
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13650
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13651
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13652
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13653
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13654
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13655
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13656
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13657
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13658
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13659
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13660
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13661
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13662
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13663
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13664
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13665
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13666
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13667
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13668
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
13669
    NUMBER_ERROR};
13670
13671
// Parse any number from 0 to 18,446,744,073,709,551,615
13672
0
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept {
13673
0
  const uint8_t *p = src;
13674
0
  //
13675
0
  // Parse the integer part.
13676
0
  //
13677
0
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
13678
0
  const uint8_t *const start_digits = p;
13679
0
  uint64_t i = 0;
13680
0
  while (parse_digit(*p, i)) { p++; }
13681
0
13682
0
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
13683
0
  // Optimization note: size_t is expected to be unsigned.
13684
0
  size_t digit_count = size_t(p - start_digits);
13685
0
  // The longest positive 64-bit number is 20 digits.
13686
0
  // We do it this way so we don't trigger this branch unless we must.
13687
0
  // Optimization note: the compiler can probably merge
13688
0
  // ((digit_count == 0) || (digit_count > 20))
13689
0
  // into a single  branch since digit_count is unsigned.
13690
0
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
13691
0
  // Here digit_count > 0.
13692
0
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
13693
0
  // We can do the following...
13694
0
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
13695
0
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
13696
0
  // }
13697
0
  // as a single table lookup:
13698
0
  if (integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
13699
0
13700
0
  if (digit_count == 20) {
13701
0
    // Positive overflow check:
13702
0
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
13703
0
    //   biggest uint64_t.
13704
0
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
13705
0
    //   If we got here, it's a 20 digit number starting with the digit "1".
13706
0
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
13707
0
    //   than 1,553,255,926,290,448,384.
13708
0
    // - That is smaller than the smallest possible 20-digit number the user could write:
13709
0
    //   10,000,000,000,000,000,000.
13710
0
    // - Therefore, if the number is positive and lower than that, it's overflow.
13711
0
    // - The value we are looking at is less than or equal to INT64_MAX.
13712
0
    //
13713
0
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
13714
0
  }
13715
0
13716
0
  return i;
13717
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned(unsigned char const*)
13718
13719
13720
// Parse any number from 0 to 18,446,744,073,709,551,615
13721
// Never read at src_end or beyond
13722
0
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src, const uint8_t * const src_end) noexcept {
13723
0
  const uint8_t *p = src;
13724
0
  //
13725
0
  // Parse the integer part.
13726
0
  //
13727
0
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
13728
0
  const uint8_t *const start_digits = p;
13729
0
  uint64_t i = 0;
13730
0
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
13731
0
13732
0
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
13733
0
  // Optimization note: size_t is expected to be unsigned.
13734
0
  size_t digit_count = size_t(p - start_digits);
13735
0
  // The longest positive 64-bit number is 20 digits.
13736
0
  // We do it this way so we don't trigger this branch unless we must.
13737
0
  // Optimization note: the compiler can probably merge
13738
0
  // ((digit_count == 0) || (digit_count > 20))
13739
0
  // into a single  branch since digit_count is unsigned.
13740
0
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
13741
0
  // Here digit_count > 0.
13742
0
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
13743
0
  // We can do the following...
13744
0
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
13745
0
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
13746
0
  // }
13747
0
  // as a single table lookup:
13748
0
  if ((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
13749
0
13750
0
  if (digit_count == 20) {
13751
0
    // Positive overflow check:
13752
0
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
13753
0
    //   biggest uint64_t.
13754
0
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
13755
0
    //   If we got here, it's a 20 digit number starting with the digit "1".
13756
0
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
13757
0
    //   than 1,553,255,926,290,448,384.
13758
0
    // - That is smaller than the smallest possible 20-digit number the user could write:
13759
0
    //   10,000,000,000,000,000,000.
13760
0
    // - Therefore, if the number is positive and lower than that, it's overflow.
13761
0
    // - The value we are looking at is less than or equal to INT64_MAX.
13762
0
    //
13763
0
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
13764
0
  }
13765
0
13766
0
  return i;
13767
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned(unsigned char const*, unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned(unsigned char const*, unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned(unsigned char const*, unsigned char const*)
13768
13769
// Parse any number from 0 to 18,446,744,073,709,551,615
13770
0
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept {
13771
0
  const uint8_t *p = src + 1;
13772
0
  //
13773
0
  // Parse the integer part.
13774
0
  //
13775
0
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
13776
0
  const uint8_t *const start_digits = p;
13777
0
  uint64_t i = 0;
13778
0
  while (parse_digit(*p, i)) { p++; }
13779
0
13780
0
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
13781
0
  // Optimization note: size_t is expected to be unsigned.
13782
0
  size_t digit_count = size_t(p - start_digits);
13783
0
  // The longest positive 64-bit number is 20 digits.
13784
0
  // We do it this way so we don't trigger this branch unless we must.
13785
0
  // Optimization note: the compiler can probably merge
13786
0
  // ((digit_count == 0) || (digit_count > 20))
13787
0
  // into a single  branch since digit_count is unsigned.
13788
0
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
13789
0
  // Here digit_count > 0.
13790
0
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
13791
0
  // We can do the following...
13792
0
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
13793
0
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
13794
0
  // }
13795
0
  // as a single table lookup:
13796
0
  if (*p != '"') { return NUMBER_ERROR; }
13797
0
13798
0
  if (digit_count == 20) {
13799
0
    // Positive overflow check:
13800
0
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
13801
0
    //   biggest uint64_t.
13802
0
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
13803
0
    //   If we got here, it's a 20 digit number starting with the digit "1".
13804
0
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
13805
0
    //   than 1,553,255,926,290,448,384.
13806
0
    // - That is smaller than the smallest possible 20-digit number the user could write:
13807
0
    //   10,000,000,000,000,000,000.
13808
0
    // - Therefore, if the number is positive and lower than that, it's overflow.
13809
0
    // - The value we are looking at is less than or equal to INT64_MAX.
13810
0
    //
13811
0
    // Note: we use src[1] and not src[0] because src[0] is the quote character in this
13812
0
    // instance.
13813
0
    if (src[1] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
13814
0
  }
13815
0
13816
0
  return i;
13817
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned_in_string(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned_in_string(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_unsigned_in_string(unsigned char const*)
13818
13819
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
13820
0
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
13821
0
  //
13822
0
  // Check for minus sign
13823
0
  //
13824
0
  bool negative = (*src == '-');
13825
0
  const uint8_t *p = src + uint8_t(negative);
13826
0
13827
0
  //
13828
0
  // Parse the integer part.
13829
0
  //
13830
0
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
13831
0
  const uint8_t *const start_digits = p;
13832
0
  uint64_t i = 0;
13833
0
  while (parse_digit(*p, i)) { p++; }
13834
0
13835
0
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
13836
0
  // Optimization note: size_t is expected to be unsigned.
13837
0
  size_t digit_count = size_t(p - start_digits);
13838
0
  // We go from
13839
0
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
13840
0
  // so we can never represent numbers that have more than 19 digits.
13841
0
  size_t longest_digit_count = 19;
13842
0
  // Optimization note: the compiler can probably merge
13843
0
  // ((digit_count == 0) || (digit_count > longest_digit_count))
13844
0
  // into a single  branch since digit_count is unsigned.
13845
0
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
13846
0
  // Here digit_count > 0.
13847
0
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
13848
0
  // We can do the following...
13849
0
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
13850
0
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
13851
0
  // }
13852
0
  // as a single table lookup:
13853
0
  if(integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
13854
0
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
13855
0
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
13856
0
  // so cheap that we might as well always make it.
13857
0
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
13858
0
  return negative ? (~i+1) : i;
13859
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer(unsigned char const*)
13860
13861
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
13862
// Never read at src_end or beyond
13863
0
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src, const uint8_t * const src_end) noexcept {
13864
0
  //
13865
0
  // Check for minus sign
13866
0
  //
13867
0
  if(src == src_end) { return NUMBER_ERROR; }
13868
0
  bool negative = (*src == '-');
13869
0
  const uint8_t *p = src + uint8_t(negative);
13870
0
13871
0
  //
13872
0
  // Parse the integer part.
13873
0
  //
13874
0
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
13875
0
  const uint8_t *const start_digits = p;
13876
0
  uint64_t i = 0;
13877
0
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
13878
0
13879
0
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
13880
0
  // Optimization note: size_t is expected to be unsigned.
13881
0
  size_t digit_count = size_t(p - start_digits);
13882
0
  // We go from
13883
0
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
13884
0
  // so we can never represent numbers that have more than 19 digits.
13885
0
  size_t longest_digit_count = 19;
13886
0
  // Optimization note: the compiler can probably merge
13887
0
  // ((digit_count == 0) || (digit_count > longest_digit_count))
13888
0
  // into a single  branch since digit_count is unsigned.
13889
0
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
13890
0
  // Here digit_count > 0.
13891
0
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
13892
0
  // We can do the following...
13893
0
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
13894
0
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
13895
0
  // }
13896
0
  // as a single table lookup:
13897
0
  if((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
13898
0
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
13899
0
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
13900
0
  // so cheap that we might as well always make it.
13901
0
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
13902
0
  return negative ? (~i+1) : i;
13903
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer(unsigned char const*, unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer(unsigned char const*, unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer(unsigned char const*, unsigned char const*)
13904
13905
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
13906
0
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t *src) noexcept {
13907
0
  //
13908
0
  // Check for minus sign
13909
0
  //
13910
0
  bool negative = (*(src + 1) == '-');
13911
0
  src += uint8_t(negative) + 1;
13912
0
13913
0
  //
13914
0
  // Parse the integer part.
13915
0
  //
13916
0
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
13917
0
  const uint8_t *const start_digits = src;
13918
0
  uint64_t i = 0;
13919
0
  while (parse_digit(*src, i)) { src++; }
13920
0
13921
0
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
13922
0
  // Optimization note: size_t is expected to be unsigned.
13923
0
  size_t digit_count = size_t(src - start_digits);
13924
0
  // We go from
13925
0
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
13926
0
  // so we can never represent numbers that have more than 19 digits.
13927
0
  size_t longest_digit_count = 19;
13928
0
  // Optimization note: the compiler can probably merge
13929
0
  // ((digit_count == 0) || (digit_count > longest_digit_count))
13930
0
  // into a single  branch since digit_count is unsigned.
13931
0
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
13932
0
  // Here digit_count > 0.
13933
0
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
13934
0
  // We can do the following...
13935
0
  // if (!jsoncharutils::is_structural_or_whitespace(*src)) {
13936
0
  //  return (*src == '.' || *src == 'e' || *src == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
13937
0
  // }
13938
0
  // as a single table lookup:
13939
0
  if(*src != '"') { return NUMBER_ERROR; }
13940
0
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
13941
0
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
13942
0
  // so cheap that we might as well always make it.
13943
0
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
13944
0
  return negative ? (~i+1) : i;
13945
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer_in_string(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer_in_string(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_integer_in_string(unsigned char const*)
13946
13947
0
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
13948
0
  //
13949
0
  // Check for minus sign
13950
0
  //
13951
0
  bool negative = (*src == '-');
13952
0
  src += uint8_t(negative);
13953
0
13954
0
  //
13955
0
  // Parse the integer part.
13956
0
  //
13957
0
  uint64_t i = 0;
13958
0
  const uint8_t *p = src;
13959
0
  p += parse_digit(*p, i);
13960
0
  bool leading_zero = (i == 0);
13961
0
  while (parse_digit(*p, i)) { p++; }
13962
0
  // no integer digits, or 0123 (zero must be solo)
13963
0
  if ( p == src ) { return INCORRECT_TYPE; }
13964
0
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
13965
0
13966
0
  //
13967
0
  // Parse the decimal part.
13968
0
  //
13969
0
  int64_t exponent = 0;
13970
0
  bool overflow;
13971
0
  if (simdjson_likely(*p == '.')) {
13972
0
    p++;
13973
0
    const uint8_t *start_decimal_digits = p;
13974
0
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
13975
0
    p++;
13976
0
    while (parse_digit(*p, i)) { p++; }
13977
0
    exponent = -(p - start_decimal_digits);
13978
0
13979
0
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
13980
0
    overflow = p-src-1 > 19;
13981
0
    if (simdjson_unlikely(overflow && leading_zero)) {
13982
0
      // Skip leading 0.00000 and see if it still overflows
13983
0
      const uint8_t *start_digits = src + 2;
13984
0
      while (*start_digits == '0') { start_digits++; }
13985
0
      overflow = p-start_digits > 19;
13986
0
    }
13987
0
  } else {
13988
0
    overflow = p-src > 19;
13989
0
  }
13990
0
13991
0
  //
13992
0
  // Parse the exponent
13993
0
  //
13994
0
  if (*p == 'e' || *p == 'E') {
13995
0
    p++;
13996
0
    bool exp_neg = *p == '-';
13997
0
    p += exp_neg || *p == '+';
13998
0
13999
0
    uint64_t exp = 0;
14000
0
    const uint8_t *start_exp_digits = p;
14001
0
    while (parse_digit(*p, exp)) { p++; }
14002
0
    // no exp digits, or 20+ exp digits
14003
0
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
14004
0
14005
0
    exponent += exp_neg ? 0-exp : exp;
14006
0
  }
14007
0
14008
0
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
14009
0
14010
0
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
14011
0
14012
0
  //
14013
0
  // Assemble (or slow-parse) the float
14014
0
  //
14015
0
  double d;
14016
0
  if (simdjson_likely(!overflow)) {
14017
0
    if (compute_float_64(exponent, i, negative, d)) { return d; }
14018
0
  }
14019
0
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
14020
0
    return NUMBER_ERROR;
14021
0
  }
14022
0
  return d;
14023
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double(unsigned char const*)
14024
14025
0
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept {
14026
0
  return (*src == '-');
14027
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_negative(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_negative(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_negative(unsigned char const*)
14028
14029
0
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept {
14030
0
  bool negative = (*src == '-');
14031
0
  src += uint8_t(negative);
14032
0
  const uint8_t *p = src;
14033
0
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
14034
0
  if ( p == src ) { return NUMBER_ERROR; }
14035
0
  if (jsoncharutils::is_structural_or_whitespace(*p)) { return true; }
14036
0
  return false;
14037
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_integer(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_integer(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::is_integer(unsigned char const*)
14038
14039
0
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept {
14040
0
  bool negative = (*src == '-');
14041
0
  src += uint8_t(negative);
14042
0
  const uint8_t *p = src;
14043
0
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
14044
0
  size_t digit_count = size_t(p - src);
14045
0
  if ( p == src ) { return NUMBER_ERROR; }
14046
0
  if (jsoncharutils::is_structural_or_whitespace(*p)) {
14047
0
    static const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
14048
0
    // We have an integer.
14049
0
    if(simdjson_unlikely(digit_count > 20)) {
14050
0
      return number_type::big_integer;
14051
0
    }
14052
0
    // If the number is negative and valid, it must be a signed integer.
14053
0
    if(negative) {
14054
0
      if (simdjson_unlikely(digit_count > 19)) return number_type::big_integer;
14055
0
      if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) {
14056
0
        return number_type::big_integer;
14057
0
      }
14058
0
      return number_type::signed_integer;
14059
0
    }
14060
0
    // Let us check if we have a big integer (>=2**64).
14061
0
    static const uint8_t * two_to_sixtyfour = reinterpret_cast<const uint8_t *>("18446744073709551616");
14062
0
    if((digit_count > 20) || (digit_count == 20 && memcmp(src, two_to_sixtyfour, 20) >= 0)) {
14063
0
      return number_type::big_integer;
14064
0
    }
14065
0
    // The number is positive and smaller than 18446744073709551616 (or 2**64).
14066
0
    // We want values larger or equal to 9223372036854775808 to be unsigned
14067
0
    // integers, and the other values to be signed integers.
14068
0
    if((digit_count == 20) || (digit_count >= 19 && memcmp(src, smaller_big_integer, 19) >= 0)) {
14069
0
      return number_type::unsigned_integer;
14070
0
    }
14071
0
    return number_type::signed_integer;
14072
0
  }
14073
0
  // Hopefully, we have 'e' or 'E' or '.'.
14074
0
  return number_type::floating_point_number;
14075
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::get_number_type(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::get_number_type(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::get_number_type(unsigned char const*)
14076
14077
// Never read at src_end or beyond
14078
0
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
14079
0
  if(src == src_end) { return NUMBER_ERROR; }
14080
0
  //
14081
0
  // Check for minus sign
14082
0
  //
14083
0
  bool negative = (*src == '-');
14084
0
  src += uint8_t(negative);
14085
0
14086
0
  //
14087
0
  // Parse the integer part.
14088
0
  //
14089
0
  uint64_t i = 0;
14090
0
  const uint8_t *p = src;
14091
0
  if(p == src_end) { return NUMBER_ERROR; }
14092
0
  p += parse_digit(*p, i);
14093
0
  bool leading_zero = (i == 0);
14094
0
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
14095
0
  // no integer digits, or 0123 (zero must be solo)
14096
0
  if ( p == src ) { return INCORRECT_TYPE; }
14097
0
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
14098
0
14099
0
  //
14100
0
  // Parse the decimal part.
14101
0
  //
14102
0
  int64_t exponent = 0;
14103
0
  bool overflow;
14104
0
  if (simdjson_likely((p != src_end) && (*p == '.'))) {
14105
0
    p++;
14106
0
    const uint8_t *start_decimal_digits = p;
14107
0
    if ((p == src_end) || !parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
14108
0
    p++;
14109
0
    while ((p != src_end) && parse_digit(*p, i)) { p++; }
14110
0
    exponent = -(p - start_decimal_digits);
14111
0
14112
0
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
14113
0
    overflow = p-src-1 > 19;
14114
0
    if (simdjson_unlikely(overflow && leading_zero)) {
14115
0
      // Skip leading 0.00000 and see if it still overflows
14116
0
      const uint8_t *start_digits = src + 2;
14117
0
      while (*start_digits == '0') { start_digits++; }
14118
0
      overflow = start_digits-src > 19;
14119
0
    }
14120
0
  } else {
14121
0
    overflow = p-src > 19;
14122
0
  }
14123
0
14124
0
  //
14125
0
  // Parse the exponent
14126
0
  //
14127
0
  if ((p != src_end) && (*p == 'e' || *p == 'E')) {
14128
0
    p++;
14129
0
    if(p == src_end) { return NUMBER_ERROR; }
14130
0
    bool exp_neg = *p == '-';
14131
0
    p += exp_neg || *p == '+';
14132
0
14133
0
    uint64_t exp = 0;
14134
0
    const uint8_t *start_exp_digits = p;
14135
0
    while ((p != src_end) && parse_digit(*p, exp)) { p++; }
14136
0
    // no exp digits, or 20+ exp digits
14137
0
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
14138
0
14139
0
    exponent += exp_neg ? 0-exp : exp;
14140
0
  }
14141
0
14142
0
  if ((p != src_end) && jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
14143
0
14144
0
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
14145
0
14146
0
  //
14147
0
  // Assemble (or slow-parse) the float
14148
0
  //
14149
0
  double d;
14150
0
  if (simdjson_likely(!overflow)) {
14151
0
    if (compute_float_64(exponent, i, negative, d)) { return d; }
14152
0
  }
14153
0
  if (!parse_float_fallback(src - uint8_t(negative), src_end, &d)) {
14154
0
    return NUMBER_ERROR;
14155
0
  }
14156
0
  return d;
14157
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double(unsigned char const*, unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double(unsigned char const*, unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double(unsigned char const*, unsigned char const*)
14158
14159
0
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * src) noexcept {
14160
0
  //
14161
0
  // Check for minus sign
14162
0
  //
14163
0
  bool negative = (*(src + 1) == '-');
14164
0
  src += uint8_t(negative) + 1;
14165
0
14166
0
  //
14167
0
  // Parse the integer part.
14168
0
  //
14169
0
  uint64_t i = 0;
14170
0
  const uint8_t *p = src;
14171
0
  p += parse_digit(*p, i);
14172
0
  bool leading_zero = (i == 0);
14173
0
  while (parse_digit(*p, i)) { p++; }
14174
0
  // no integer digits, or 0123 (zero must be solo)
14175
0
  if ( p == src ) { return INCORRECT_TYPE; }
14176
0
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
14177
0
14178
0
  //
14179
0
  // Parse the decimal part.
14180
0
  //
14181
0
  int64_t exponent = 0;
14182
0
  bool overflow;
14183
0
  if (simdjson_likely(*p == '.')) {
14184
0
    p++;
14185
0
    const uint8_t *start_decimal_digits = p;
14186
0
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
14187
0
    p++;
14188
0
    while (parse_digit(*p, i)) { p++; }
14189
0
    exponent = -(p - start_decimal_digits);
14190
0
14191
0
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
14192
0
    overflow = p-src-1 > 19;
14193
0
    if (simdjson_unlikely(overflow && leading_zero)) {
14194
0
      // Skip leading 0.00000 and see if it still overflows
14195
0
      const uint8_t *start_digits = src + 2;
14196
0
      while (*start_digits == '0') { start_digits++; }
14197
0
      overflow = p-start_digits > 19;
14198
0
    }
14199
0
  } else {
14200
0
    overflow = p-src > 19;
14201
0
  }
14202
0
14203
0
  //
14204
0
  // Parse the exponent
14205
0
  //
14206
0
  if (*p == 'e' || *p == 'E') {
14207
0
    p++;
14208
0
    bool exp_neg = *p == '-';
14209
0
    p += exp_neg || *p == '+';
14210
0
14211
0
    uint64_t exp = 0;
14212
0
    const uint8_t *start_exp_digits = p;
14213
0
    while (parse_digit(*p, exp)) { p++; }
14214
0
    // no exp digits, or 20+ exp digits
14215
0
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
14216
0
14217
0
    exponent += exp_neg ? 0-exp : exp;
14218
0
  }
14219
0
14220
0
  if (*p != '"') { return NUMBER_ERROR; }
14221
0
14222
0
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
14223
0
14224
0
  //
14225
0
  // Assemble (or slow-parse) the float
14226
0
  //
14227
0
  double d;
14228
0
  if (simdjson_likely(!overflow)) {
14229
0
    if (compute_float_64(exponent, i, negative, d)) { return d; }
14230
0
  }
14231
0
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
14232
0
    return NUMBER_ERROR;
14233
0
  }
14234
0
  return d;
14235
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double_in_string(unsigned char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double_in_string(unsigned char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::numberparsing::(anonymous namespace)::parse_double_in_string(unsigned char const*)
14236
14237
} // unnamed namespace
14238
#endif // SIMDJSON_SKIPNUMBERPARSING
14239
14240
} // namespace numberparsing
14241
14242
0
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
14243
0
    switch (type) {
14244
0
        case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
14245
0
        case number_type::unsigned_integer: out << "unsigned integer in [9223372036854775808,18446744073709551616)"; break;
14246
0
        case number_type::floating_point_number: out << "floating-point number (binary64)"; break;
14247
0
        case number_type::big_integer: out << "big integer"; break;
14248
0
        default: SIMDJSON_UNREACHABLE();
14249
0
    }
14250
0
    return out;
14251
0
}
14252
14253
} // namespace fallback
14254
} // namespace simdjson
14255
14256
#endif // SIMDJSON_GENERIC_NUMBERPARSING_H
14257
/* end file simdjson/generic/numberparsing.h for fallback */
14258
14259
/* including simdjson/generic/implementation_simdjson_result_base-inl.h for fallback: #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
14260
/* begin file simdjson/generic/implementation_simdjson_result_base-inl.h for fallback */
14261
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
14262
14263
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14264
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H */
14265
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
14266
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
14267
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14268
14269
namespace simdjson {
14270
namespace fallback {
14271
14272
//
14273
// internal::implementation_simdjson_result_base<T> inline implementation
14274
//
14275
14276
template<typename T>
14277
0
simdjson_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
14278
0
  error = this->second;
14279
0
  if (!error) {
14280
0
    value = std::forward<implementation_simdjson_result_base<T>>(*this).first;
14281
0
  }
14282
0
}
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::json_type>::tie(simdjson::fallback::ondemand::json_type&, simdjson::error_code&) &&
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::raw_json_string>::tie(simdjson::fallback::ondemand::raw_json_string&, simdjson::error_code&) &&
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array>::tie(simdjson::fallback::ondemand::array&, simdjson::error_code&) &&
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object>::tie(simdjson::fallback::ondemand::object&, simdjson::error_code&) &&
14283
14284
template<typename T>
14285
0
simdjson_warn_unused simdjson_inline error_code implementation_simdjson_result_base<T>::get(T &value) && noexcept {
14286
0
  error_code error;
14287
0
  std::forward<implementation_simdjson_result_base<T>>(*this).tie(value, error);
14288
0
  return error;
14289
0
}
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::json_type>::get(simdjson::fallback::ondemand::json_type&) &&
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::raw_json_string>::get(simdjson::fallback::ondemand::raw_json_string&) &&
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array>::get(simdjson::fallback::ondemand::array&) &&
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object>::get(simdjson::fallback::ondemand::object&) &&
14290
14291
template<typename T>
14292
0
simdjson_inline error_code implementation_simdjson_result_base<T>::error() const noexcept {
14293
0
  return this->second;
14294
0
}
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::value>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array_iterator>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::document>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::document_reference>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::field>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object_iterator>::error() const
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::raw_json_string>::error() const
14295
14296
#if SIMDJSON_EXCEPTIONS
14297
14298
template<typename T>
14299
simdjson_inline T& implementation_simdjson_result_base<T>::value() & noexcept(false) {
14300
  if (error()) { throw simdjson_error(error()); }
14301
  return this->first;
14302
}
14303
14304
template<typename T>
14305
simdjson_inline T&& implementation_simdjson_result_base<T>::value() && noexcept(false) {
14306
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
14307
}
14308
14309
template<typename T>
14310
simdjson_inline T&& implementation_simdjson_result_base<T>::take_value() && noexcept(false) {
14311
  if (error()) { throw simdjson_error(error()); }
14312
  return std::forward<T>(this->first);
14313
}
14314
14315
template<typename T>
14316
simdjson_inline implementation_simdjson_result_base<T>::operator T&&() && noexcept(false) {
14317
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
14318
}
14319
14320
#endif // SIMDJSON_EXCEPTIONS
14321
14322
template<typename T>
14323
simdjson_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
14324
  return this->first;
14325
}
14326
14327
template<typename T>
14328
0
simdjson_inline T& implementation_simdjson_result_base<T>::value_unsafe() & noexcept {
14329
0
  return this->first;
14330
0
}
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::document>::value_unsafe() &
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::document_reference>::value_unsafe() &
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::value>::value_unsafe() &
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object>::value_unsafe() &
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array>::value_unsafe() &
14331
14332
template<typename T>
14333
simdjson_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
14334
  return std::forward<T>(this->first);
14335
}
14336
14337
template<typename T>
14338
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
14339
0
    : first{std::forward<T>(value)}, second{error} {}
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::document>::implementation_simdjson_result_base(simdjson::fallback::ondemand::document&&, simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object>::implementation_simdjson_result_base(simdjson::fallback::ondemand::object&&, simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object_iterator>::implementation_simdjson_result_base(simdjson::fallback::ondemand::object_iterator&&, simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::field>::implementation_simdjson_result_base(simdjson::fallback::ondemand::field&&, simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::raw_json_string>::implementation_simdjson_result_base(simdjson::fallback::ondemand::raw_json_string&&, simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::value>::implementation_simdjson_result_base(simdjson::fallback::ondemand::value&&, simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array>::implementation_simdjson_result_base(simdjson::fallback::ondemand::array&&, simdjson::error_code)
14340
template<typename T>
14341
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(error_code error) noexcept
14342
0
    : implementation_simdjson_result_base(T{}, error) {}
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::document>::implementation_simdjson_result_base(simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object>::implementation_simdjson_result_base(simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::field>::implementation_simdjson_result_base(simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::raw_json_string>::implementation_simdjson_result_base(simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::value>::implementation_simdjson_result_base(simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::json_type>::implementation_simdjson_result_base(simdjson::error_code)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array>::implementation_simdjson_result_base(simdjson::error_code)
14343
template<typename T>
14344
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
14345
0
    : implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::document>::implementation_simdjson_result_base(simdjson::fallback::ondemand::document&&)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object>::implementation_simdjson_result_base(simdjson::fallback::ondemand::object&&)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::object_iterator>::implementation_simdjson_result_base(simdjson::fallback::ondemand::object_iterator&&)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::raw_json_string>::implementation_simdjson_result_base(simdjson::fallback::ondemand::raw_json_string&&)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::field>::implementation_simdjson_result_base(simdjson::fallback::ondemand::field&&)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::value>::implementation_simdjson_result_base(simdjson::fallback::ondemand::value&&)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::json_type>::implementation_simdjson_result_base(simdjson::fallback::ondemand::json_type&&)
Unexecuted instantiation: simdjson::fallback::implementation_simdjson_result_base<simdjson::fallback::ondemand::array>::implementation_simdjson_result_base(simdjson::fallback::ondemand::array&&)
14346
14347
} // namespace fallback
14348
} // namespace simdjson
14349
14350
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
14351
/* end file simdjson/generic/implementation_simdjson_result_base-inl.h for fallback */
14352
/* end file simdjson/generic/amalgamated.h for fallback */
14353
/* including simdjson/fallback/end.h: #include "simdjson/fallback/end.h" */
14354
/* begin file simdjson/fallback/end.h */
14355
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14356
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
14357
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14358
14359
/* undefining SIMDJSON_IMPLEMENTATION from "fallback" */
14360
#undef SIMDJSON_IMPLEMENTATION
14361
/* end file simdjson/fallback/end.h */
14362
14363
#endif // SIMDJSON_FALLBACK_H
14364
/* end file simdjson/fallback.h */
14365
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
14366
/* including simdjson/haswell.h: #include "simdjson/haswell.h" */
14367
/* begin file simdjson/haswell.h */
14368
#ifndef SIMDJSON_HASWELL_H
14369
#define SIMDJSON_HASWELL_H
14370
14371
/* including simdjson/haswell/begin.h: #include "simdjson/haswell/begin.h" */
14372
/* begin file simdjson/haswell/begin.h */
14373
/* defining SIMDJSON_IMPLEMENTATION to "haswell" */
14374
#define SIMDJSON_IMPLEMENTATION haswell
14375
14376
/* including simdjson/haswell/base.h: #include "simdjson/haswell/base.h" */
14377
/* begin file simdjson/haswell/base.h */
14378
#ifndef SIMDJSON_HASWELL_BASE_H
14379
#define SIMDJSON_HASWELL_BASE_H
14380
14381
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14382
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
14383
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14384
14385
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_HASWELL
14386
namespace simdjson {
14387
/**
14388
 * Implementation for Haswell (Intel AVX2).
14389
 */
14390
namespace haswell {
14391
14392
class implementation;
14393
14394
namespace {
14395
namespace simd {
14396
template <typename T> struct simd8;
14397
template <typename T> struct simd8x64;
14398
} // namespace simd
14399
} // unnamed namespace
14400
14401
} // namespace haswell
14402
} // namespace simdjson
14403
14404
#endif // SIMDJSON_HASWELL_BASE_H
14405
/* end file simdjson/haswell/base.h */
14406
/* including simdjson/haswell/intrinsics.h: #include "simdjson/haswell/intrinsics.h" */
14407
/* begin file simdjson/haswell/intrinsics.h */
14408
#ifndef SIMDJSON_HASWELL_INTRINSICS_H
14409
#define SIMDJSON_HASWELL_INTRINSICS_H
14410
14411
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14412
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
14413
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14414
14415
#if SIMDJSON_VISUAL_STUDIO
14416
// under clang within visual studio, this will include <x86intrin.h>
14417
#include <intrin.h>  // visual studio or clang
14418
#else
14419
#include <x86intrin.h> // elsewhere
14420
#endif // SIMDJSON_VISUAL_STUDIO
14421
14422
#if SIMDJSON_CLANG_VISUAL_STUDIO
14423
/**
14424
 * You are not supposed, normally, to include these
14425
 * headers directly. Instead you should either include intrin.h
14426
 * or x86intrin.h. However, when compiling with clang
14427
 * under Windows (i.e., when _MSC_VER is set), these headers
14428
 * only get included *if* the corresponding features are detected
14429
 * from macros:
14430
 * e.g., if __AVX2__ is set... in turn,  we normally set these
14431
 * macros by compiling against the corresponding architecture
14432
 * (e.g., arch:AVX2, -mavx2, etc.) which compiles the whole
14433
 * software with these advanced instructions. In simdjson, we
14434
 * want to compile the whole program for a generic target,
14435
 * and only target our specific kernels. As a workaround,
14436
 * we directly include the needed headers. These headers would
14437
 * normally guard against such usage, but we carefully included
14438
 * <x86intrin.h>  (or <intrin.h>) before, so the headers
14439
 * are fooled.
14440
 */
14441
#include <bmiintrin.h>   // for _blsr_u64
14442
#include <lzcntintrin.h> // for  __lzcnt64
14443
#include <immintrin.h>   // for most things (AVX2, AVX512, _popcnt64)
14444
#include <smmintrin.h>
14445
#include <tmmintrin.h>
14446
#include <avxintrin.h>
14447
#include <avx2intrin.h>
14448
#include <wmmintrin.h>   // for  _mm_clmulepi64_si128
14449
// unfortunately, we may not get _blsr_u64, but, thankfully, clang
14450
// has it as a macro.
14451
#ifndef _blsr_u64
14452
// we roll our own
14453
#define _blsr_u64(n) ((n - 1) & n)
14454
#endif //  _blsr_u64
14455
#endif // SIMDJSON_CLANG_VISUAL_STUDIO
14456
14457
static_assert(sizeof(__m256i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for haswell kernel.");
14458
14459
#endif // SIMDJSON_HASWELL_INTRINSICS_H
14460
/* end file simdjson/haswell/intrinsics.h */
14461
14462
#if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL
14463
SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt")
14464
#endif
14465
14466
/* including simdjson/haswell/bitmanipulation.h: #include "simdjson/haswell/bitmanipulation.h" */
14467
/* begin file simdjson/haswell/bitmanipulation.h */
14468
#ifndef SIMDJSON_HASWELL_BITMANIPULATION_H
14469
#define SIMDJSON_HASWELL_BITMANIPULATION_H
14470
14471
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14472
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
14473
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
14474
/* amalgamation skipped (editor-only): #include "simdjson/haswell/bitmask.h" */
14475
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14476
14477
namespace simdjson {
14478
namespace haswell {
14479
namespace {
14480
14481
// We sometimes call trailing_zero on inputs that are zero,
14482
// but the algorithms do not end up using the returned value.
14483
// Sadly, sanitizers are not smart enough to figure it out.
14484
SIMDJSON_NO_SANITIZE_UNDEFINED
14485
// This function can be used safely even if not all bytes have been
14486
// initialized.
14487
// See issue https://github.com/simdjson/simdjson/issues/1965
14488
SIMDJSON_NO_SANITIZE_MEMORY
14489
simdjson_inline int trailing_zeroes(uint64_t input_num) {
14490
#if SIMDJSON_REGULAR_VISUAL_STUDIO
14491
  return (int)_tzcnt_u64(input_num);
14492
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
14493
  ////////
14494
  // You might expect the next line to be equivalent to
14495
  // return (int)_tzcnt_u64(input_num);
14496
  // but the generated code differs and might be less efficient?
14497
  ////////
14498
  return __builtin_ctzll(input_num);
14499
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
14500
}
14501
14502
/* result might be undefined when input_num is zero */
14503
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
14504
  return _blsr_u64(input_num);
14505
}
14506
14507
/* result might be undefined when input_num is zero */
14508
simdjson_inline int leading_zeroes(uint64_t input_num) {
14509
  return int(_lzcnt_u64(input_num));
14510
}
14511
14512
#if SIMDJSON_REGULAR_VISUAL_STUDIO
14513
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
14514
  // note: we do not support legacy 32-bit Windows in this kernel
14515
  return __popcnt64(input_num);// Visual Studio wants two underscores
14516
}
14517
#else
14518
simdjson_inline long long int count_ones(uint64_t input_num) {
14519
  return _popcnt64(input_num);
14520
}
14521
#endif
14522
14523
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
14524
                                uint64_t *result) {
14525
#if SIMDJSON_REGULAR_VISUAL_STUDIO
14526
  return _addcarry_u64(0, value1, value2,
14527
                       reinterpret_cast<unsigned __int64 *>(result));
14528
#else
14529
  return __builtin_uaddll_overflow(value1, value2,
14530
                                   reinterpret_cast<unsigned long long *>(result));
14531
#endif
14532
}
14533
14534
} // unnamed namespace
14535
} // namespace haswell
14536
} // namespace simdjson
14537
14538
#endif // SIMDJSON_HASWELL_BITMANIPULATION_H
14539
/* end file simdjson/haswell/bitmanipulation.h */
14540
/* including simdjson/haswell/bitmask.h: #include "simdjson/haswell/bitmask.h" */
14541
/* begin file simdjson/haswell/bitmask.h */
14542
#ifndef SIMDJSON_HASWELL_BITMASK_H
14543
#define SIMDJSON_HASWELL_BITMASK_H
14544
14545
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14546
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
14547
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
14548
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14549
14550
namespace simdjson {
14551
namespace haswell {
14552
namespace {
14553
14554
//
14555
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
14556
//
14557
// For example, prefix_xor(00100100) == 00011100
14558
//
14559
simdjson_inline uint64_t prefix_xor(const uint64_t bitmask) {
14560
  // There should be no such thing with a processor supporting avx2
14561
  // but not clmul.
14562
  __m128i all_ones = _mm_set1_epi8('\xFF');
14563
  __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, bitmask), all_ones, 0);
14564
  return _mm_cvtsi128_si64(result);
14565
}
14566
14567
} // unnamed namespace
14568
} // namespace haswell
14569
} // namespace simdjson
14570
14571
#endif // SIMDJSON_HASWELL_BITMASK_H
14572
/* end file simdjson/haswell/bitmask.h */
14573
/* including simdjson/haswell/numberparsing_defs.h: #include "simdjson/haswell/numberparsing_defs.h" */
14574
/* begin file simdjson/haswell/numberparsing_defs.h */
14575
#ifndef SIMDJSON_HASWELL_NUMBERPARSING_DEFS_H
14576
#define SIMDJSON_HASWELL_NUMBERPARSING_DEFS_H
14577
14578
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14579
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
14580
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
14581
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14582
14583
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14584
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
14585
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14586
14587
namespace simdjson {
14588
namespace haswell {
14589
namespace numberparsing {
14590
14591
/** @private */
14592
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
14593
  // this actually computes *16* values so we are being wasteful.
14594
  const __m128i ascii0 = _mm_set1_epi8('0');
14595
  const __m128i mul_1_10 =
14596
      _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1);
14597
  const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1);
14598
  const __m128i mul_1_10000 =
14599
      _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1);
14600
  const __m128i input = _mm_sub_epi8(
14601
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0);
14602
  const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10);
14603
  const __m128i t2 = _mm_madd_epi16(t1, mul_1_100);
14604
  const __m128i t3 = _mm_packus_epi32(t2, t2);
14605
  const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000);
14606
  return _mm_cvtsi128_si32(
14607
      t4); // only captures the sum of the first 8 digits, drop the rest
14608
}
14609
14610
/** @private */
14611
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
14612
  internal::value128 answer;
14613
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
14614
#ifdef _M_ARM64
14615
  // ARM64 has native support for 64-bit multiplications, no need to emultate
14616
  answer.high = __umulh(value1, value2);
14617
  answer.low = value1 * value2;
14618
#else
14619
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
14620
#endif // _M_ARM64
14621
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
14622
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
14623
  answer.low = uint64_t(r);
14624
  answer.high = uint64_t(r >> 64);
14625
#endif
14626
  return answer;
14627
}
14628
14629
} // namespace numberparsing
14630
} // namespace haswell
14631
} // namespace simdjson
14632
14633
#define SIMDJSON_SWAR_NUMBER_PARSING 1
14634
14635
#endif // SIMDJSON_HASWELL_NUMBERPARSING_DEFS_H
14636
/* end file simdjson/haswell/numberparsing_defs.h */
14637
/* including simdjson/haswell/simd.h: #include "simdjson/haswell/simd.h" */
14638
/* begin file simdjson/haswell/simd.h */
14639
#ifndef SIMDJSON_HASWELL_SIMD_H
14640
#define SIMDJSON_HASWELL_SIMD_H
14641
14642
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
14643
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
14644
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
14645
/* amalgamation skipped (editor-only): #include "simdjson/haswell/bitmanipulation.h" */
14646
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
14647
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
14648
14649
namespace simdjson {
14650
namespace haswell {
14651
namespace {
14652
namespace simd {
14653
14654
  // Forward-declared so they can be used by splat and friends.
14655
  template<typename Child>
14656
  struct base {
14657
    __m256i value;
14658
14659
    // Zero constructor
14660
    simdjson_inline base() : value{__m256i()} {}
14661
14662
    // Conversion from SIMD register
14663
    simdjson_inline base(const __m256i _value) : value(_value) {}
14664
14665
    // Conversion to SIMD register
14666
    simdjson_inline operator const __m256i&() const { return this->value; }
14667
    simdjson_inline operator __m256i&() { return this->value; }
14668
14669
    // Bit operations
14670
    simdjson_inline Child operator|(const Child other) const { return _mm256_or_si256(*this, other); }
14671
    simdjson_inline Child operator&(const Child other) const { return _mm256_and_si256(*this, other); }
14672
    simdjson_inline Child operator^(const Child other) const { return _mm256_xor_si256(*this, other); }
14673
    simdjson_inline Child bit_andnot(const Child other) const { return _mm256_andnot_si256(other, *this); }
14674
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
14675
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
14676
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
14677
  };
14678
14679
  // Forward-declared so they can be used by splat and friends.
14680
  template<typename T>
14681
  struct simd8;
14682
14683
  template<typename T, typename Mask=simd8<bool>>
14684
  struct base8: base<simd8<T>> {
14685
    typedef uint32_t bitmask_t;
14686
    typedef uint64_t bitmask2_t;
14687
14688
    simdjson_inline base8() : base<simd8<T>>() {}
14689
    simdjson_inline base8(const __m256i _value) : base<simd8<T>>(_value) {}
14690
14691
    friend simdjson_really_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return _mm256_cmpeq_epi8(lhs, rhs); }
14692
14693
    static const int SIZE = sizeof(base<T>::value);
14694
14695
    template<int N=1>
14696
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
14697
      return _mm256_alignr_epi8(*this, _mm256_permute2x128_si256(prev_chunk, *this, 0x21), 16 - N);
14698
    }
14699
  };
14700
14701
  // SIMD byte mask type (returned by things like eq and gt)
14702
  template<>
14703
  struct simd8<bool>: base8<bool> {
14704
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm256_set1_epi8(uint8_t(-(!!_value))); }
14705
14706
    simdjson_inline simd8<bool>() : base8() {}
14707
    simdjson_inline simd8<bool>(const __m256i _value) : base8<bool>(_value) {}
14708
    // Splat constructor
14709
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
14710
14711
    simdjson_inline int to_bitmask() const { return _mm256_movemask_epi8(*this); }
14712
    simdjson_inline bool any() const { return !_mm256_testz_si256(*this, *this); }
14713
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
14714
  };
14715
14716
  template<typename T>
14717
  struct base8_numeric: base8<T> {
14718
    static simdjson_inline simd8<T> splat(T _value) { return _mm256_set1_epi8(_value); }
14719
    static simdjson_inline simd8<T> zero() { return _mm256_setzero_si256(); }
14720
    static simdjson_inline simd8<T> load(const T values[32]) {
14721
      return _mm256_loadu_si256(reinterpret_cast<const __m256i *>(values));
14722
    }
14723
    // Repeat 16 values as many times as necessary (usually for lookup tables)
14724
    static simdjson_inline simd8<T> repeat_16(
14725
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
14726
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
14727
    ) {
14728
      return simd8<T>(
14729
        v0, v1, v2, v3, v4, v5, v6, v7,
14730
        v8, v9, v10,v11,v12,v13,v14,v15,
14731
        v0, v1, v2, v3, v4, v5, v6, v7,
14732
        v8, v9, v10,v11,v12,v13,v14,v15
14733
      );
14734
    }
14735
14736
    simdjson_inline base8_numeric() : base8<T>() {}
14737
    simdjson_inline base8_numeric(const __m256i _value) : base8<T>(_value) {}
14738
14739
    // Store to array
14740
    simdjson_inline void store(T dst[32]) const { return _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst), *this); }
14741
14742
    // Addition/subtraction are the same for signed and unsigned
14743
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm256_add_epi8(*this, other); }
14744
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm256_sub_epi8(*this, other); }
14745
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
14746
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
14747
14748
    // Override to distinguish from bool version
14749
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
14750
14751
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
14752
    template<typename L>
14753
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
14754
      return _mm256_shuffle_epi8(lookup_table, *this);
14755
    }
14756
14757
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
14758
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
14759
    // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes
14760
    // get written.
14761
    // Design consideration: it seems like a function with the
14762
    // signature simd8<L> compress(uint32_t mask) would be
14763
    // sensible, but the AVX ISA makes this kind of approach difficult.
14764
    template<typename L>
14765
    simdjson_inline void compress(uint32_t mask, L * output) const {
14766
      using internal::thintable_epi8;
14767
      using internal::BitsSetTable256mul2;
14768
      using internal::pshufb_combine_table;
14769
      // this particular implementation was inspired by work done by @animetosho
14770
      // we do it in four steps, first 8 bytes and then second 8 bytes...
14771
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
14772
      uint8_t mask2 = uint8_t(mask >> 8); // second least significant 8 bits
14773
      uint8_t mask3 = uint8_t(mask >> 16); // ...
14774
      uint8_t mask4 = uint8_t(mask >> 24); // ...
14775
      // next line just loads the 64-bit values thintable_epi8[mask1] and
14776
      // thintable_epi8[mask2] into a 128-bit register, using only
14777
      // two instructions on most compilers.
14778
      __m256i shufmask =  _mm256_set_epi64x(thintable_epi8[mask4], thintable_epi8[mask3],
14779
        thintable_epi8[mask2], thintable_epi8[mask1]);
14780
      // we increment by 0x08 the second half of the mask and so forth
14781
      shufmask =
14782
      _mm256_add_epi8(shufmask, _mm256_set_epi32(0x18181818, 0x18181818,
14783
         0x10101010, 0x10101010, 0x08080808, 0x08080808, 0, 0));
14784
      // this is the version "nearly pruned"
14785
      __m256i pruned = _mm256_shuffle_epi8(*this, shufmask);
14786
      // we still need to put the  pieces back together.
14787
      // we compute the popcount of the first words:
14788
      int pop1 = BitsSetTable256mul2[mask1];
14789
      int pop3 = BitsSetTable256mul2[mask3];
14790
14791
      // then load the corresponding mask
14792
      // could be done with _mm256_loadu2_m128i but many standard libraries omit this intrinsic.
14793
      __m256i v256 = _mm256_castsi128_si256(
14794
        _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop1 * 8)));
14795
      __m256i compactmask = _mm256_insertf128_si256(v256,
14796
         _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop3 * 8)), 1);
14797
      __m256i almostthere =  _mm256_shuffle_epi8(pruned, compactmask);
14798
      // We just need to write out the result.
14799
      // This is the tricky bit that is hard to do
14800
      // if we want to return a SIMD register, since there
14801
      // is no single-instruction approach to recombine
14802
      // the two 128-bit lanes with an offset.
14803
      __m128i v128;
14804
      v128 = _mm256_castsi256_si128(almostthere);
14805
      _mm_storeu_si128( reinterpret_cast<__m128i *>(output), v128);
14806
      v128 = _mm256_extractf128_si256(almostthere, 1);
14807
      _mm_storeu_si128( reinterpret_cast<__m128i *>(output + 16 - count_ones(mask & 0xFFFF)), v128);
14808
    }
14809
14810
    template<typename L>
14811
    simdjson_inline simd8<L> lookup_16(
14812
        L replace0,  L replace1,  L replace2,  L replace3,
14813
        L replace4,  L replace5,  L replace6,  L replace7,
14814
        L replace8,  L replace9,  L replace10, L replace11,
14815
        L replace12, L replace13, L replace14, L replace15) const {
14816
      return lookup_16(simd8<L>::repeat_16(
14817
        replace0,  replace1,  replace2,  replace3,
14818
        replace4,  replace5,  replace6,  replace7,
14819
        replace8,  replace9,  replace10, replace11,
14820
        replace12, replace13, replace14, replace15
14821
      ));
14822
    }
14823
  };
14824
14825
  // Signed bytes
14826
  template<>
14827
  struct simd8<int8_t> : base8_numeric<int8_t> {
14828
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
14829
    simdjson_inline simd8(const __m256i _value) : base8_numeric<int8_t>(_value) {}
14830
    // Splat constructor
14831
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
14832
    // Array constructor
14833
    simdjson_inline simd8(const int8_t values[32]) : simd8(load(values)) {}
14834
    // Member-by-member initialization
14835
    simdjson_inline simd8(
14836
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
14837
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15,
14838
      int8_t v16, int8_t v17, int8_t v18, int8_t v19, int8_t v20, int8_t v21, int8_t v22, int8_t v23,
14839
      int8_t v24, int8_t v25, int8_t v26, int8_t v27, int8_t v28, int8_t v29, int8_t v30, int8_t v31
14840
    ) : simd8(_mm256_setr_epi8(
14841
      v0, v1, v2, v3, v4, v5, v6, v7,
14842
      v8, v9, v10,v11,v12,v13,v14,v15,
14843
      v16,v17,v18,v19,v20,v21,v22,v23,
14844
      v24,v25,v26,v27,v28,v29,v30,v31
14845
    )) {}
14846
    // Repeat 16 values as many times as necessary (usually for lookup tables)
14847
    simdjson_inline static simd8<int8_t> repeat_16(
14848
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
14849
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
14850
    ) {
14851
      return simd8<int8_t>(
14852
        v0, v1, v2, v3, v4, v5, v6, v7,
14853
        v8, v9, v10,v11,v12,v13,v14,v15,
14854
        v0, v1, v2, v3, v4, v5, v6, v7,
14855
        v8, v9, v10,v11,v12,v13,v14,v15
14856
      );
14857
    }
14858
14859
    // Order-sensitive comparisons
14860
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm256_max_epi8(*this, other); }
14861
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm256_min_epi8(*this, other); }
14862
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm256_cmpgt_epi8(*this, other); }
14863
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm256_cmpgt_epi8(other, *this); }
14864
  };
14865
14866
  // Unsigned bytes
14867
  template<>
14868
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
14869
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
14870
    simdjson_inline simd8(const __m256i _value) : base8_numeric<uint8_t>(_value) {}
14871
    // Splat constructor
14872
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
14873
    // Array constructor
14874
    simdjson_inline simd8(const uint8_t values[32]) : simd8(load(values)) {}
14875
    // Member-by-member initialization
14876
    simdjson_inline simd8(
14877
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
14878
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15,
14879
      uint8_t v16, uint8_t v17, uint8_t v18, uint8_t v19, uint8_t v20, uint8_t v21, uint8_t v22, uint8_t v23,
14880
      uint8_t v24, uint8_t v25, uint8_t v26, uint8_t v27, uint8_t v28, uint8_t v29, uint8_t v30, uint8_t v31
14881
    ) : simd8(_mm256_setr_epi8(
14882
      v0, v1, v2, v3, v4, v5, v6, v7,
14883
      v8, v9, v10,v11,v12,v13,v14,v15,
14884
      v16,v17,v18,v19,v20,v21,v22,v23,
14885
      v24,v25,v26,v27,v28,v29,v30,v31
14886
    )) {}
14887
    // Repeat 16 values as many times as necessary (usually for lookup tables)
14888
    simdjson_inline static simd8<uint8_t> repeat_16(
14889
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
14890
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
14891
    ) {
14892
      return simd8<uint8_t>(
14893
        v0, v1, v2, v3, v4, v5, v6, v7,
14894
        v8, v9, v10,v11,v12,v13,v14,v15,
14895
        v0, v1, v2, v3, v4, v5, v6, v7,
14896
        v8, v9, v10,v11,v12,v13,v14,v15
14897
      );
14898
    }
14899
14900
    // Saturated math
14901
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm256_adds_epu8(*this, other); }
14902
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm256_subs_epu8(*this, other); }
14903
14904
    // Order-specific operations
14905
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm256_max_epu8(*this, other); }
14906
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm256_min_epu8(other, *this); }
14907
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
14908
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
14909
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
14910
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
14911
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
14912
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
14913
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
14914
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->lt_bits(other).any_bits_set(); }
14915
14916
    // Bit-specific operations
14917
    simdjson_inline simd8<bool> bits_not_set() const { return *this == uint8_t(0); }
14918
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
14919
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
14920
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
14921
    simdjson_inline bool is_ascii() const { return _mm256_movemask_epi8(*this) == 0; }
14922
    simdjson_inline bool bits_not_set_anywhere() const { return _mm256_testz_si256(*this, *this); }
14923
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
14924
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return _mm256_testz_si256(*this, bits); }
14925
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
14926
    template<int N>
14927
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm256_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
14928
    template<int N>
14929
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm256_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
14930
    // Get one of the bits and make a bitmask out of it.
14931
    // e.g. value.get_bit<7>() gets the high bit
14932
    template<int N>
14933
    simdjson_inline int get_bit() const { return _mm256_movemask_epi8(_mm256_slli_epi16(*this, 7-N)); }
14934
  };
14935
14936
  template<typename T>
14937
  struct simd8x64 {
14938
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
14939
    static_assert(NUM_CHUNKS == 2, "Haswell kernel should use two registers per 64-byte block.");
14940
    const simd8<T> chunks[NUM_CHUNKS];
14941
14942
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
14943
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
14944
    simd8x64() = delete; // no default constructor allowed
14945
14946
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1) : chunks{chunk0, chunk1} {}
14947
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+32)} {}
14948
14949
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
14950
      uint32_t mask1 = uint32_t(mask);
14951
      uint32_t mask2 = uint32_t(mask >> 32);
14952
      this->chunks[0].compress(mask1, output);
14953
      this->chunks[1].compress(mask2, output + 32 - count_ones(mask1));
14954
      return 64 - count_ones(mask);
14955
    }
14956
14957
    simdjson_inline void store(T ptr[64]) const {
14958
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
14959
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
14960
    }
14961
14962
    simdjson_inline uint64_t to_bitmask() const {
14963
      uint64_t r_lo = uint32_t(this->chunks[0].to_bitmask());
14964
      uint64_t r_hi =                       this->chunks[1].to_bitmask();
14965
      return r_lo | (r_hi << 32);
14966
    }
14967
14968
    simdjson_inline simd8<T> reduce_or() const {
14969
      return this->chunks[0] | this->chunks[1];
14970
    }
14971
14972
    simdjson_inline simd8x64<T> bit_or(const T m) const {
14973
      const simd8<T> mask = simd8<T>::splat(m);
14974
      return simd8x64<T>(
14975
        this->chunks[0] | mask,
14976
        this->chunks[1] | mask
14977
      );
14978
    }
14979
14980
    simdjson_inline uint64_t eq(const T m) const {
14981
      const simd8<T> mask = simd8<T>::splat(m);
14982
      return  simd8x64<bool>(
14983
        this->chunks[0] == mask,
14984
        this->chunks[1] == mask
14985
      ).to_bitmask();
14986
    }
14987
14988
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
14989
      return  simd8x64<bool>(
14990
        this->chunks[0] == other.chunks[0],
14991
        this->chunks[1] == other.chunks[1]
14992
      ).to_bitmask();
14993
    }
14994
14995
    simdjson_inline uint64_t lteq(const T m) const {
14996
      const simd8<T> mask = simd8<T>::splat(m);
14997
      return  simd8x64<bool>(
14998
        this->chunks[0] <= mask,
14999
        this->chunks[1] <= mask
15000
      ).to_bitmask();
15001
    }
15002
  }; // struct simd8x64<T>
15003
15004
} // namespace simd
15005
15006
} // unnamed namespace
15007
} // namespace haswell
15008
} // namespace simdjson
15009
15010
#endif // SIMDJSON_HASWELL_SIMD_H
15011
/* end file simdjson/haswell/simd.h */
15012
/* including simdjson/haswell/stringparsing_defs.h: #include "simdjson/haswell/stringparsing_defs.h" */
15013
/* begin file simdjson/haswell/stringparsing_defs.h */
15014
#ifndef SIMDJSON_HASWELL_STRINGPARSING_DEFS_H
15015
#define SIMDJSON_HASWELL_STRINGPARSING_DEFS_H
15016
15017
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
15018
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
15019
/* amalgamation skipped (editor-only): #include "simdjson/haswell/simd.h" */
15020
/* amalgamation skipped (editor-only): #include "simdjson/haswell/bitmanipulation.h" */
15021
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
15022
15023
namespace simdjson {
15024
namespace haswell {
15025
namespace {
15026
15027
using namespace simd;
15028
15029
// Holds backslashes and quotes locations.
15030
struct backslash_and_quote {
15031
public:
15032
  static constexpr uint32_t BYTES_PROCESSED = 32;
15033
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
15034
15035
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
15036
  simdjson_inline bool has_backslash() { return ((quote_bits - 1) & bs_bits) != 0; }
15037
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
15038
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
15039
15040
  uint32_t bs_bits;
15041
  uint32_t quote_bits;
15042
}; // struct backslash_and_quote
15043
15044
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
15045
  // this can read up to 15 bytes beyond the buffer size, but we require
15046
  // SIMDJSON_PADDING of padding
15047
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
15048
  simd8<uint8_t> v(src);
15049
  // store to dest unconditionally - we can overwrite the bits we don't like later
15050
  v.store(dst);
15051
  return {
15052
      static_cast<uint32_t>((v == '\\').to_bitmask()),     // bs_bits
15053
      static_cast<uint32_t>((v == '"').to_bitmask()), // quote_bits
15054
  };
15055
}
15056
15057
} // unnamed namespace
15058
} // namespace haswell
15059
} // namespace simdjson
15060
15061
#endif // SIMDJSON_HASWELL_STRINGPARSING_DEFS_H
15062
/* end file simdjson/haswell/stringparsing_defs.h */
15063
/* end file simdjson/haswell/begin.h */
15064
/* including simdjson/generic/amalgamated.h for haswell: #include "simdjson/generic/amalgamated.h" */
15065
/* begin file simdjson/generic/amalgamated.h for haswell */
15066
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
15067
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
15068
#endif
15069
15070
/* including simdjson/generic/base.h for haswell: #include "simdjson/generic/base.h" */
15071
/* begin file simdjson/generic/base.h for haswell */
15072
#ifndef SIMDJSON_GENERIC_BASE_H
15073
15074
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
15075
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_BASE_H */
15076
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
15077
/* amalgamation skipped (editor-only): // If we haven't got an implementation yet, we're in the editor, editing a generic file! Just */
15078
/* amalgamation skipped (editor-only): // use the most advanced one we can so the most possible stuff can be tested. */
15079
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_IMPLEMENTATION */
15080
/* amalgamation skipped (editor-only): #include "simdjson/implementation_detection.h" */
15081
/* amalgamation skipped (editor-only): #if SIMDJSON_IMPLEMENTATION_ICELAKE */
15082
/* amalgamation skipped (editor-only): #include "simdjson/icelake/begin.h" */
15083
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_HASWELL */
15084
/* amalgamation skipped (editor-only): #include "simdjson/haswell/begin.h" */
15085
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_WESTMERE */
15086
/* amalgamation skipped (editor-only): #include "simdjson/westmere/begin.h" */
15087
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_ARM64 */
15088
/* amalgamation skipped (editor-only): #include "simdjson/arm64/begin.h" */
15089
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_PPC64 */
15090
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/begin.h" */
15091
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_FALLBACK */
15092
/* amalgamation skipped (editor-only): #include "simdjson/fallback/begin.h" */
15093
/* amalgamation skipped (editor-only): #else */
15094
/* amalgamation skipped (editor-only): #error "All possible implementations (including fallback) have been disabled! simdjson will not run." */
15095
/* amalgamation skipped (editor-only): #endif */
15096
/* amalgamation skipped (editor-only): #endif // SIMDJSON_IMPLEMENTATION */
15097
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
15098
15099
namespace simdjson {
15100
namespace haswell {
15101
15102
struct open_container;
15103
class dom_parser_implementation;
15104
15105
/**
15106
 * The type of a JSON number
15107
 */
15108
enum class number_type {
15109
    floating_point_number=1, /// a binary64 number
15110
    signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
15111
    unsigned_integer,        /// a positive integer larger or equal to 1<<63
15112
    big_integer              /// a big integer that does not fit in a 64-bit word
15113
};
15114
15115
} // namespace haswell
15116
} // namespace simdjson
15117
15118
#endif // SIMDJSON_GENERIC_BASE_H
15119
/* end file simdjson/generic/base.h for haswell */
15120
/* including simdjson/generic/jsoncharutils.h for haswell: #include "simdjson/generic/jsoncharutils.h" */
15121
/* begin file simdjson/generic/jsoncharutils.h for haswell */
15122
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
15123
15124
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
15125
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_JSONCHARUTILS_H */
15126
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
15127
/* amalgamation skipped (editor-only): #include "simdjson/internal/jsoncharutils_tables.h" */
15128
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
15129
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
15130
15131
namespace simdjson {
15132
namespace haswell {
15133
namespace {
15134
namespace jsoncharutils {
15135
15136
// return non-zero if not a structural or whitespace char
15137
// zero otherwise
15138
simdjson_inline uint32_t is_not_structural_or_whitespace(uint8_t c) {
15139
  return internal::structural_or_whitespace_negated[c];
15140
}
15141
15142
simdjson_inline uint32_t is_structural_or_whitespace(uint8_t c) {
15143
  return internal::structural_or_whitespace[c];
15144
}
15145
15146
// returns a value with the high 16 bits set if not valid
15147
// otherwise returns the conversion of the 4 hex digits at src into the bottom
15148
// 16 bits of the 32-bit return register
15149
//
15150
// see
15151
// https://lemire.me/blog/2019/04/17/parsing-short-hexadecimal-strings-efficiently/
15152
static inline uint32_t hex_to_u32_nocheck(
15153
    const uint8_t *src) { // strictly speaking, static inline is a C-ism
15154
  uint32_t v1 = internal::digit_to_val32[630 + src[0]];
15155
  uint32_t v2 = internal::digit_to_val32[420 + src[1]];
15156
  uint32_t v3 = internal::digit_to_val32[210 + src[2]];
15157
  uint32_t v4 = internal::digit_to_val32[0 + src[3]];
15158
  return v1 | v2 | v3 | v4;
15159
}
15160
15161
// given a code point cp, writes to c
15162
// the utf-8 code, outputting the length in
15163
// bytes, if the length is zero, the code point
15164
// is invalid
15165
//
15166
// This can possibly be made faster using pdep
15167
// and clz and table lookups, but JSON documents
15168
// have few escaped code points, and the following
15169
// function looks cheap.
15170
//
15171
// Note: we assume that surrogates are treated separately
15172
//
15173
simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
15174
  if (cp <= 0x7F) {
15175
    c[0] = uint8_t(cp);
15176
    return 1; // ascii
15177
  }
15178
  if (cp <= 0x7FF) {
15179
    c[0] = uint8_t((cp >> 6) + 192);
15180
    c[1] = uint8_t((cp & 63) + 128);
15181
    return 2; // universal plane
15182
    //  Surrogates are treated elsewhere...
15183
    //} //else if (0xd800 <= cp && cp <= 0xdfff) {
15184
    //  return 0; // surrogates // could put assert here
15185
  } else if (cp <= 0xFFFF) {
15186
    c[0] = uint8_t((cp >> 12) + 224);
15187
    c[1] = uint8_t(((cp >> 6) & 63) + 128);
15188
    c[2] = uint8_t((cp & 63) + 128);
15189
    return 3;
15190
  } else if (cp <= 0x10FFFF) { // if you know you have a valid code point, this
15191
                               // is not needed
15192
    c[0] = uint8_t((cp >> 18) + 240);
15193
    c[1] = uint8_t(((cp >> 12) & 63) + 128);
15194
    c[2] = uint8_t(((cp >> 6) & 63) + 128);
15195
    c[3] = uint8_t((cp & 63) + 128);
15196
    return 4;
15197
  }
15198
  // will return 0 when the code point was too large.
15199
  return 0; // bad r
15200
}
15201
15202
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
15203
// this is a slow emulation routine for 32-bit
15204
//
15205
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
15206
  return x * (uint64_t)y;
15207
}
15208
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
15209
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
15210
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
15211
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
15212
  uint64_t adbc_carry = !!(adbc < ad);
15213
  uint64_t lo = bd + (adbc << 32);
15214
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
15215
        (adbc_carry << 32) + !!(lo < bd);
15216
  return lo;
15217
}
15218
#endif
15219
15220
} // namespace jsoncharutils
15221
} // unnamed namespace
15222
} // namespace haswell
15223
} // namespace simdjson
15224
15225
#endif // SIMDJSON_GENERIC_JSONCHARUTILS_H
15226
/* end file simdjson/generic/jsoncharutils.h for haswell */
15227
/* including simdjson/generic/atomparsing.h for haswell: #include "simdjson/generic/atomparsing.h" */
15228
/* begin file simdjson/generic/atomparsing.h for haswell */
15229
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
15230
15231
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
15232
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ATOMPARSING_H */
15233
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
15234
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
15235
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
15236
15237
#include <cstring>
15238
15239
namespace simdjson {
15240
namespace haswell {
15241
namespace {
15242
/// @private
15243
namespace atomparsing {
15244
15245
// The string_to_uint32 is exclusively used to map literal strings to 32-bit values.
15246
// We use memcpy instead of a pointer cast to avoid undefined behaviors since we cannot
15247
// be certain that the character pointer will be properly aligned.
15248
// You might think that using memcpy makes this function expensive, but you'd be wrong.
15249
// All decent optimizing compilers (GCC, clang, Visual Studio) will compile string_to_uint32("false");
15250
// to the compile-time constant 1936482662.
15251
simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(&val, str, sizeof(uint32_t)); return val; }
15252
15253
15254
// Again in str4ncmp we use a memcpy to avoid undefined behavior. The memcpy may appear expensive.
15255
// Yet all decent optimizing compilers will compile memcpy to a single instruction, just about.
15256
simdjson_warn_unused
15257
simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) {
15258
  uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++)
15259
  static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes");
15260
  std::memcpy(&srcval, src, sizeof(uint32_t));
15261
  return srcval ^ string_to_uint32(atom);
15262
}
15263
15264
simdjson_warn_unused
15265
simdjson_inline bool is_valid_true_atom(const uint8_t *src) {
15266
  return (str4ncmp(src, "true") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
15267
}
15268
15269
simdjson_warn_unused
15270
simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) {
15271
  if (len > 4) { return is_valid_true_atom(src); }
15272
  else if (len == 4) { return !str4ncmp(src, "true"); }
15273
  else { return false; }
15274
}
15275
15276
simdjson_warn_unused
15277
simdjson_inline bool is_valid_false_atom(const uint8_t *src) {
15278
  return (str4ncmp(src+1, "alse") | jsoncharutils::is_not_structural_or_whitespace(src[5])) == 0;
15279
}
15280
15281
simdjson_warn_unused
15282
simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) {
15283
  if (len > 5) { return is_valid_false_atom(src); }
15284
  else if (len == 5) { return !str4ncmp(src+1, "alse"); }
15285
  else { return false; }
15286
}
15287
15288
simdjson_warn_unused
15289
simdjson_inline bool is_valid_null_atom(const uint8_t *src) {
15290
  return (str4ncmp(src, "null") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
15291
}
15292
15293
simdjson_warn_unused
15294
simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
15295
  if (len > 4) { return is_valid_null_atom(src); }
15296
  else if (len == 4) { return !str4ncmp(src, "null"); }
15297
  else { return false; }
15298
}
15299
15300
} // namespace atomparsing
15301
} // unnamed namespace
15302
} // namespace haswell
15303
} // namespace simdjson
15304
15305
#endif // SIMDJSON_GENERIC_ATOMPARSING_H
15306
/* end file simdjson/generic/atomparsing.h for haswell */
15307
/* including simdjson/generic/dom_parser_implementation.h for haswell: #include "simdjson/generic/dom_parser_implementation.h" */
15308
/* begin file simdjson/generic/dom_parser_implementation.h for haswell */
15309
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
15310
15311
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
15312
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H */
15313
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
15314
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
15315
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
15316
15317
namespace simdjson {
15318
namespace haswell {
15319
15320
// expectation: sizeof(open_container) = 64/8.
15321
struct open_container {
15322
  uint32_t tape_index; // where, on the tape, does the scope ([,{) begins
15323
  uint32_t count; // how many elements in the scope
15324
}; // struct open_container
15325
15326
static_assert(sizeof(open_container) == 64/8, "Open container must be 64 bits");
15327
15328
class dom_parser_implementation final : public internal::dom_parser_implementation {
15329
public:
15330
  /** Tape location of each open { or [ */
15331
  std::unique_ptr<open_container[]> open_containers{};
15332
  /** Whether each open container is a [ or { */
15333
  std::unique_ptr<bool[]> is_array{};
15334
  /** Buffer passed to stage 1 */
15335
  const uint8_t *buf{};
15336
  /** Length passed to stage 1 */
15337
  size_t len{0};
15338
  /** Document passed to stage 2 */
15339
  dom::document *doc{};
15340
15341
  inline dom_parser_implementation() noexcept;
15342
  inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
15343
  inline dom_parser_implementation &operator=(dom_parser_implementation &&other) noexcept;
15344
  dom_parser_implementation(const dom_parser_implementation &) = delete;
15345
  dom_parser_implementation &operator=(const dom_parser_implementation &) = delete;
15346
15347
  simdjson_warn_unused error_code parse(const uint8_t *buf, size_t len, dom::document &doc) noexcept final;
15348
  simdjson_warn_unused error_code stage1(const uint8_t *buf, size_t len, stage1_mode partial) noexcept final;
15349
  simdjson_warn_unused error_code stage2(dom::document &doc) noexcept final;
15350
  simdjson_warn_unused error_code stage2_next(dom::document &doc) noexcept final;
15351
  simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept final;
15352
  simdjson_warn_unused uint8_t *parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept final;
15353
  inline simdjson_warn_unused error_code set_capacity(size_t capacity) noexcept final;
15354
  inline simdjson_warn_unused error_code set_max_depth(size_t max_depth) noexcept final;
15355
private:
15356
  simdjson_inline simdjson_warn_unused error_code set_capacity_stage1(size_t capacity);
15357
15358
};
15359
15360
} // namespace haswell
15361
} // namespace simdjson
15362
15363
namespace simdjson {
15364
namespace haswell {
15365
15366
inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
15367
inline dom_parser_implementation::dom_parser_implementation(dom_parser_implementation &&other) noexcept = default;
15368
inline dom_parser_implementation &dom_parser_implementation::operator=(dom_parser_implementation &&other) noexcept = default;
15369
15370
// Leaving these here so they can be inlined if so desired
15371
inline simdjson_warn_unused error_code dom_parser_implementation::set_capacity(size_t capacity) noexcept {
15372
  if(capacity > SIMDJSON_MAXSIZE_BYTES) { return CAPACITY; }
15373
  // Stage 1 index output
15374
  size_t max_structures = SIMDJSON_ROUNDUP_N(capacity, 64) + 2 + 7;
15375
  structural_indexes.reset( new (std::nothrow) uint32_t[max_structures] );
15376
  if (!structural_indexes) { _capacity = 0; return MEMALLOC; }
15377
  structural_indexes[0] = 0;
15378
  n_structural_indexes = 0;
15379
15380
  _capacity = capacity;
15381
  return SUCCESS;
15382
}
15383
15384
inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(size_t max_depth) noexcept {
15385
  // Stage 2 stacks
15386
  open_containers.reset(new (std::nothrow) open_container[max_depth]);
15387
  is_array.reset(new (std::nothrow) bool[max_depth]);
15388
  if (!is_array || !open_containers) { _max_depth = 0; return MEMALLOC; }
15389
15390
  _max_depth = max_depth;
15391
  return SUCCESS;
15392
}
15393
15394
} // namespace haswell
15395
} // namespace simdjson
15396
15397
#endif // SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
15398
/* end file simdjson/generic/dom_parser_implementation.h for haswell */
15399
/* including simdjson/generic/implementation_simdjson_result_base.h for haswell: #include "simdjson/generic/implementation_simdjson_result_base.h" */
15400
/* begin file simdjson/generic/implementation_simdjson_result_base.h for haswell */
15401
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
15402
15403
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
15404
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H */
15405
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
15406
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
15407
15408
namespace simdjson {
15409
namespace haswell {
15410
15411
// This is a near copy of include/error.h's implementation_simdjson_result_base, except it doesn't use std::pair
15412
// so we can avoid inlining errors
15413
// TODO reconcile these!
15414
/**
15415
 * The result of a simdjson operation that could fail.
15416
 *
15417
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
15418
 *
15419
 * This is a base class for implementations that want to add functions to the result type for
15420
 * chaining.
15421
 *
15422
 * Override like:
15423
 *
15424
 *   struct simdjson_result<T> : public internal::implementation_simdjson_result_base<T> {
15425
 *     simdjson_result() noexcept : internal::implementation_simdjson_result_base<T>() {}
15426
 *     simdjson_result(error_code error) noexcept : internal::implementation_simdjson_result_base<T>(error) {}
15427
 *     simdjson_result(T &&value) noexcept : internal::implementation_simdjson_result_base<T>(std::forward(value)) {}
15428
 *     simdjson_result(T &&value, error_code error) noexcept : internal::implementation_simdjson_result_base<T>(value, error) {}
15429
 *     // Your extra methods here
15430
 *   }
15431
 *
15432
 * Then any method returning simdjson_result<T> will be chainable with your methods.
15433
 */
15434
template<typename T>
15435
struct implementation_simdjson_result_base {
15436
15437
  /**
15438
   * Create a new empty result with error = UNINITIALIZED.
15439
   */
15440
  simdjson_inline implementation_simdjson_result_base() noexcept = default;
15441
15442
  /**
15443
   * Create a new error result.
15444
   */
15445
  simdjson_inline implementation_simdjson_result_base(error_code error) noexcept;
15446
15447
  /**
15448
   * Create a new successful result.
15449
   */
15450
  simdjson_inline implementation_simdjson_result_base(T &&value) noexcept;
15451
15452
  /**
15453
   * Create a new result with both things (use if you don't want to branch when creating the result).
15454
   */
15455
  simdjson_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
15456
15457
  /**
15458
   * Move the value and the error to the provided variables.
15459
   *
15460
   * @param value The variable to assign the value to. May not be set if there is an error.
15461
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
15462
   */
15463
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
15464
15465
  /**
15466
   * Move the value to the provided variable.
15467
   *
15468
   * @param value The variable to assign the value to. May not be set if there is an error.
15469
   */
15470
  simdjson_inline error_code get(T &value) && noexcept;
15471
15472
  /**
15473
   * The error.
15474
   */
15475
  simdjson_inline error_code error() const noexcept;
15476
15477
#if SIMDJSON_EXCEPTIONS
15478
15479
  /**
15480
   * Get the result value.
15481
   *
15482
   * @throw simdjson_error if there was an error.
15483
   */
15484
  simdjson_inline T& value() & noexcept(false);
15485
15486
  /**
15487
   * Take the result value (move it).
15488
   *
15489
   * @throw simdjson_error if there was an error.
15490
   */
15491
  simdjson_inline T&& value() && noexcept(false);
15492
15493
  /**
15494
   * Take the result value (move it).
15495
   *
15496
   * @throw simdjson_error if there was an error.
15497
   */
15498
  simdjson_inline T&& take_value() && noexcept(false);
15499
15500
  /**
15501
   * Cast to the value (will throw on error).
15502
   *
15503
   * @throw simdjson_error if there was an error.
15504
   */
15505
  simdjson_inline operator T&&() && noexcept(false);
15506
15507
15508
#endif // SIMDJSON_EXCEPTIONS
15509
15510
  /**
15511
   * Get the result value. This function is safe if and only
15512
   * the error() method returns a value that evaluates to false.
15513
   */
15514
  simdjson_inline const T& value_unsafe() const& noexcept;
15515
  /**
15516
   * Get the result value. This function is safe if and only
15517
   * the error() method returns a value that evaluates to false.
15518
   */
15519
  simdjson_inline T& value_unsafe() & noexcept;
15520
  /**
15521
   * Take the result value (move it). This function is safe if and only
15522
   * the error() method returns a value that evaluates to false.
15523
   */
15524
  simdjson_inline T&& value_unsafe() && noexcept;
15525
protected:
15526
  /** users should never directly access first and second. **/
15527
  T first{}; /** Users should never directly access 'first'. **/
15528
  error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
15529
}; // struct implementation_simdjson_result_base
15530
15531
} // namespace haswell
15532
} // namespace simdjson
15533
15534
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
15535
/* end file simdjson/generic/implementation_simdjson_result_base.h for haswell */
15536
/* including simdjson/generic/numberparsing.h for haswell: #include "simdjson/generic/numberparsing.h" */
15537
/* begin file simdjson/generic/numberparsing.h for haswell */
15538
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
15539
15540
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
15541
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_NUMBERPARSING_H */
15542
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
15543
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
15544
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
15545
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
15546
15547
#include <limits>
15548
#include <ostream>
15549
#include <cstring>
15550
15551
namespace simdjson {
15552
namespace haswell {
15553
namespace numberparsing {
15554
15555
#ifdef JSON_TEST_NUMBERS
15556
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
15557
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
15558
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
15559
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
15560
#define BIGINT_NUMBER(SRC) (found_invalid_number((SRC)), BIGINT_ERROR)
15561
#else
15562
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
15563
#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
15564
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
15565
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
15566
#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
15567
#endif
15568
15569
namespace {
15570
15571
// Convert a mantissa, an exponent and a sign bit into an ieee64 double.
15572
// The real_exponent needs to be in [0, 2046] (technically real_exponent = 2047 would be acceptable).
15573
// The mantissa should be in [0,1<<53). The bit at index (1ULL << 52) while be zeroed.
15574
simdjson_inline double to_double(uint64_t mantissa, uint64_t real_exponent, bool negative) {
15575
    double d;
15576
    mantissa &= ~(1ULL << 52);
15577
    mantissa |= real_exponent << 52;
15578
    mantissa |= ((static_cast<uint64_t>(negative)) << 63);
15579
    std::memcpy(&d, &mantissa, sizeof(d));
15580
    return d;
15581
}
15582
15583
// Attempts to compute i * 10^(power) exactly; and if "negative" is
15584
// true, negate the result.
15585
// This function will only work in some cases, when it does not work, success is
15586
// set to false. This should work *most of the time* (like 99% of the time).
15587
// We assume that power is in the [smallest_power,
15588
// largest_power] interval: the caller is responsible for this check.
15589
simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, double &d) {
15590
  // we start with a fast path
15591
  // It was described in
15592
  // Clinger WD. How to read floating point numbers accurately.
15593
  // ACM SIGPLAN Notices. 1990
15594
#ifndef FLT_EVAL_METHOD
15595
#error "FLT_EVAL_METHOD should be defined, please include cfloat."
15596
#endif
15597
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
15598
  // We cannot be certain that x/y is rounded to nearest.
15599
  if (0 <= power && power <= 22 && i <= 9007199254740991)
15600
#else
15601
  if (-22 <= power && power <= 22 && i <= 9007199254740991)
15602
#endif
15603
  {
15604
    // convert the integer into a double. This is lossless since
15605
    // 0 <= i <= 2^53 - 1.
15606
    d = double(i);
15607
    //
15608
    // The general idea is as follows.
15609
    // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
15610
    // 1) Both s and p can be represented exactly as 64-bit floating-point
15611
    // values
15612
    // (binary64).
15613
    // 2) Because s and p can be represented exactly as floating-point values,
15614
    // then s * p
15615
    // and s / p will produce correctly rounded values.
15616
    //
15617
    if (power < 0) {
15618
      d = d / simdjson::internal::power_of_ten[-power];
15619
    } else {
15620
      d = d * simdjson::internal::power_of_ten[power];
15621
    }
15622
    if (negative) {
15623
      d = -d;
15624
    }
15625
    return true;
15626
  }
15627
  // When 22 < power && power <  22 + 16, we could
15628
  // hope for another, secondary fast path.  It was
15629
  // described by David M. Gay in  "Correctly rounded
15630
  // binary-decimal and decimal-binary conversions." (1990)
15631
  // If you need to compute i * 10^(22 + x) for x < 16,
15632
  // first compute i * 10^x, if you know that result is exact
15633
  // (e.g., when i * 10^x < 2^53),
15634
  // then you can still proceed and do (i * 10^x) * 10^22.
15635
  // Is this worth your time?
15636
  // You need  22 < power *and* power <  22 + 16 *and* (i * 10^(x-22) < 2^53)
15637
  // for this second fast path to work.
15638
  // If you you have 22 < power *and* power <  22 + 16, and then you
15639
  // optimistically compute "i * 10^(x-22)", there is still a chance that you
15640
  // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
15641
  // this optimization maybe less common than we would like. Source:
15642
  // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
15643
  // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
15644
15645
  // The fast path has now failed, so we are failing back on the slower path.
15646
15647
  // In the slow path, we need to adjust i so that it is > 1<<63 which is always
15648
  // possible, except if i == 0, so we handle i == 0 separately.
15649
  if(i == 0) {
15650
    d = negative ? -0.0 : 0.0;
15651
    return true;
15652
  }
15653
15654
15655
  // The exponent is 1024 + 63 + power
15656
  //     + floor(log(5**power)/log(2)).
15657
  // The 1024 comes from the ieee64 standard.
15658
  // The 63 comes from the fact that we use a 64-bit word.
15659
  //
15660
  // Computing floor(log(5**power)/log(2)) could be
15661
  // slow. Instead we use a fast function.
15662
  //
15663
  // For power in (-400,350), we have that
15664
  // (((152170 + 65536) * power ) >> 16);
15665
  // is equal to
15666
  //  floor(log(5**power)/log(2)) + power when power >= 0
15667
  // and it is equal to
15668
  //  ceil(log(5**-power)/log(2)) + power when power < 0
15669
  //
15670
  // The 65536 is (1<<16) and corresponds to
15671
  // (65536 * power) >> 16 ---> power
15672
  //
15673
  // ((152170 * power ) >> 16) is equal to
15674
  // floor(log(5**power)/log(2))
15675
  //
15676
  // Note that this is not magic: 152170/(1<<16) is
15677
  // approximatively equal to log(5)/log(2).
15678
  // The 1<<16 value is a power of two; we could use a
15679
  // larger power of 2 if we wanted to.
15680
  //
15681
  int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
15682
15683
15684
  // We want the most significant bit of i to be 1. Shift if needed.
15685
  int lz = leading_zeroes(i);
15686
  i <<= lz;
15687
15688
15689
  // We are going to need to do some 64-bit arithmetic to get a precise product.
15690
  // We use a table lookup approach.
15691
  // It is safe because
15692
  // power >= smallest_power
15693
  // and power <= largest_power
15694
  // We recover the mantissa of the power, it has a leading 1. It is always
15695
  // rounded down.
15696
  //
15697
  // We want the most significant 64 bits of the product. We know
15698
  // this will be non-zero because the most significant bit of i is
15699
  // 1.
15700
  const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
15701
  // Optimization: It may be that materializing the index as a variable might confuse some compilers and prevent effective complex-addressing loads. (Done for code clarity.)
15702
  //
15703
  // The full_multiplication function computes the 128-bit product of two 64-bit words
15704
  // with a returned value of type value128 with a "low component" corresponding to the
15705
  // 64-bit least significant bits of the product and with a "high component" corresponding
15706
  // to the 64-bit most significant bits of the product.
15707
  simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
15708
  // Both i and power_of_five_128[index] have their most significant bit set to 1 which
15709
  // implies that the either the most or the second most significant bit of the product
15710
  // is 1. We pack values in this manner for efficiency reasons: it maximizes the use
15711
  // we make of the product. It also makes it easy to reason about the product: there
15712
  // is 0 or 1 leading zero in the product.
15713
15714
  // Unless the least significant 9 bits of the high (64-bit) part of the full
15715
  // product are all 1s, then we know that the most significant 55 bits are
15716
  // exact and no further work is needed. Having 55 bits is necessary because
15717
  // we need 53 bits for the mantissa but we have to have one rounding bit and
15718
  // we can waste a bit if the most significant bit of the product is zero.
15719
  if((firstproduct.high & 0x1FF) == 0x1FF) {
15720
    // We want to compute i * 5^q, but only care about the top 55 bits at most.
15721
    // Consider the scenario where q>=0. Then 5^q may not fit in 64-bits. Doing
15722
    // the full computation is wasteful. So we do what is called a "truncated
15723
    // multiplication".
15724
    // We take the most significant 64-bits, and we put them in
15725
    // power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
15726
    // to the desired approximation using one multiplication. Sometimes it does not suffice.
15727
    // Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
15728
    // then we get a better approximation to i * 5^q.
15729
    //
15730
    // That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
15731
    // more complicated.
15732
    //
15733
    // There is an extra layer of complexity in that we need more than 55 bits of
15734
    // accuracy in the round-to-even scenario.
15735
    //
15736
    // The full_multiplication function computes the 128-bit product of two 64-bit words
15737
    // with a returned value of type value128 with a "low component" corresponding to the
15738
    // 64-bit least significant bits of the product and with a "high component" corresponding
15739
    // to the 64-bit most significant bits of the product.
15740
    simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
15741
    firstproduct.low += secondproduct.high;
15742
    if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
15743
    // As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
15744
    // Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
15745
    // is sufficiently accurate, and more computation is not needed.
15746
  }
15747
  uint64_t lower = firstproduct.low;
15748
  uint64_t upper = firstproduct.high;
15749
  // The final mantissa should be 53 bits with a leading 1.
15750
  // We shift it so that it occupies 54 bits with a leading 1.
15751
  ///////
15752
  uint64_t upperbit = upper >> 63;
15753
  uint64_t mantissa = upper >> (upperbit + 9);
15754
  lz += int(1 ^ upperbit);
15755
15756
  // Here we have mantissa < (1<<54).
15757
  int64_t real_exponent = exponent - lz;
15758
  if (simdjson_unlikely(real_exponent <= 0)) { // we have a subnormal?
15759
    // Here have that real_exponent <= 0 so -real_exponent >= 0
15760
    if(-real_exponent + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
15761
      d = negative ? -0.0 : 0.0;
15762
      return true;
15763
    }
15764
    // next line is safe because -real_exponent + 1 < 0
15765
    mantissa >>= -real_exponent + 1;
15766
    // Thankfully, we can't have both "round-to-even" and subnormals because
15767
    // "round-to-even" only occurs for powers close to 0.
15768
    mantissa += (mantissa & 1); // round up
15769
    mantissa >>= 1;
15770
    // There is a weird scenario where we don't have a subnormal but just.
15771
    // Suppose we start with 2.2250738585072013e-308, we end up
15772
    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
15773
    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
15774
    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
15775
    // subnormal, but we can only know this after rounding.
15776
    // So we only declare a subnormal if we are smaller than the threshold.
15777
    real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
15778
    d = to_double(mantissa, real_exponent, negative);
15779
    return true;
15780
  }
15781
  // We have to round to even. The "to even" part
15782
  // is only a problem when we are right in between two floats
15783
  // which we guard against.
15784
  // If we have lots of trailing zeros, we may fall right between two
15785
  // floating-point values.
15786
  //
15787
  // The round-to-even cases take the form of a number 2m+1 which is in (2^53,2^54]
15788
  // times a power of two. That is, it is right between a number with binary significand
15789
  // m and another number with binary significand m+1; and it must be the case
15790
  // that it cannot be represented by a float itself.
15791
  //
15792
  // We must have that w * 10 ^q == (2m+1) * 2^p for some power of two 2^p.
15793
  // Recall that 10^q = 5^q * 2^q.
15794
  // When q >= 0, we must have that (2m+1) is divible by 5^q, so 5^q <= 2^54. We have that
15795
  //  5^23 <=  2^54 and it is the last power of five to qualify, so q <= 23.
15796
  // When q<0, we have  w  >=  (2m+1) x 5^{-q}.  We must have that w<2^{64} so
15797
  // (2m+1) x 5^{-q} < 2^{64}. We have that 2m+1>2^{53}. Hence, we must have
15798
  // 2^{53} x 5^{-q} < 2^{64}.
15799
  // Hence we have 5^{-q} < 2^{11}$ or q>= -4.
15800
  //
15801
  // We require lower <= 1 and not lower == 0 because we could not prove that
15802
  // that lower == 0 is implied; but we could prove that lower <= 1 is a necessary and sufficient test.
15803
  if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
15804
    if((mantissa  << (upperbit + 64 - 53 - 2)) ==  upper) {
15805
      mantissa &= ~1;             // flip it so that we do not round up
15806
    }
15807
  }
15808
15809
  mantissa += mantissa & 1;
15810
  mantissa >>= 1;
15811
15812
  // Here we have mantissa < (1<<53), unless there was an overflow
15813
  if (mantissa >= (1ULL << 53)) {
15814
    //////////
15815
    // This will happen when parsing values such as 7.2057594037927933e+16
15816
    ////////
15817
    mantissa = (1ULL << 52);
15818
    real_exponent++;
15819
  }
15820
  mantissa &= ~(1ULL << 52);
15821
  // we have to check that real_exponent is in range, otherwise we bail out
15822
  if (simdjson_unlikely(real_exponent > 2046)) {
15823
    // We have an infinite value!!! We could actually throw an error here if we could.
15824
    return false;
15825
  }
15826
  d = to_double(mantissa, real_exponent, negative);
15827
  return true;
15828
}
15829
15830
// We call a fallback floating-point parser that might be slow. Note
15831
// it will accept JSON numbers, but the JSON spec. is more restrictive so
15832
// before you call parse_float_fallback, you need to have validated the input
15833
// string with the JSON grammar.
15834
// It will return an error (false) if the parsed number is infinite.
15835
// The string parsing itself always succeeds. We know that there is at least
15836
// one digit.
15837
static bool parse_float_fallback(const uint8_t *ptr, double *outDouble) {
15838
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr));
15839
  // We do not accept infinite values.
15840
15841
  // Detecting finite values in a portable manner is ridiculously hard, ideally
15842
  // we would want to do:
15843
  // return !std::isfinite(*outDouble);
15844
  // but that mysteriously fails under legacy/old libc++ libraries, see
15845
  // https://github.com/simdjson/simdjson/issues/1286
15846
  //
15847
  // Therefore, fall back to this solution (the extra parens are there
15848
  // to handle that max may be a macro on windows).
15849
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
15850
}
15851
15852
static bool parse_float_fallback(const uint8_t *ptr, const uint8_t *end_ptr, double *outDouble) {
15853
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr), reinterpret_cast<const char *>(end_ptr));
15854
  // We do not accept infinite values.
15855
15856
  // Detecting finite values in a portable manner is ridiculously hard, ideally
15857
  // we would want to do:
15858
  // return !std::isfinite(*outDouble);
15859
  // but that mysteriously fails under legacy/old libc++ libraries, see
15860
  // https://github.com/simdjson/simdjson/issues/1286
15861
  //
15862
  // Therefore, fall back to this solution (the extra parens are there
15863
  // to handle that max may be a macro on windows).
15864
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
15865
}
15866
15867
// check quickly whether the next 8 chars are made of digits
15868
// at a glance, it looks better than Mula's
15869
// http://0x80.pl/articles/swar-digits-validate.html
15870
simdjson_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
15871
  uint64_t val;
15872
  // this can read up to 7 bytes beyond the buffer size, but we require
15873
  // SIMDJSON_PADDING of padding
15874
  static_assert(7 <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be bigger than 7");
15875
  std::memcpy(&val, chars, 8);
15876
  // a branchy method might be faster:
15877
  // return (( val & 0xF0F0F0F0F0F0F0F0 ) == 0x3030303030303030)
15878
  //  && (( (val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0 ) ==
15879
  //  0x3030303030303030);
15880
  return (((val & 0xF0F0F0F0F0F0F0F0) |
15881
           (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
15882
          0x3333333333333333);
15883
}
15884
15885
template<typename I>
15886
SIMDJSON_NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
15887
simdjson_inline bool parse_digit(const uint8_t c, I &i) {
15888
  const uint8_t digit = static_cast<uint8_t>(c - '0');
15889
  if (digit > 9) {
15890
    return false;
15891
  }
15892
  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
15893
  i = 10 * i + digit; // might overflow, we will handle the overflow later
15894
  return true;
15895
}
15896
15897
simdjson_inline bool is_digit(const uint8_t c) {
15898
  return static_cast<uint8_t>(c - '0') <= 9;
15899
}
15900
15901
simdjson_inline error_code parse_decimal_after_separator(simdjson_unused const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
15902
  // we continue with the fiction that we have an integer. If the
15903
  // floating point number is representable as x * 10^z for some integer
15904
  // z that fits in 53 bits, then we will be able to convert back the
15905
  // the integer into a float in a lossless manner.
15906
  const uint8_t *const first_after_period = p;
15907
15908
#ifdef SIMDJSON_SWAR_NUMBER_PARSING
15909
#if SIMDJSON_SWAR_NUMBER_PARSING
15910
  // this helps if we have lots of decimals!
15911
  // this turns out to be frequent enough.
15912
  if (is_made_of_eight_digits_fast(p)) {
15913
    i = i * 100000000 + parse_eight_digits_unrolled(p);
15914
    p += 8;
15915
  }
15916
#endif // SIMDJSON_SWAR_NUMBER_PARSING
15917
#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
15918
  // Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
15919
  if (parse_digit(*p, i)) { ++p; }
15920
  while (parse_digit(*p, i)) { p++; }
15921
  exponent = first_after_period - p;
15922
  // Decimal without digits (123.) is illegal
15923
  if (exponent == 0) {
15924
    return INVALID_NUMBER(src);
15925
  }
15926
  return SUCCESS;
15927
}
15928
15929
simdjson_inline error_code parse_exponent(simdjson_unused const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
15930
  // Exp Sign: -123.456e[-]78
15931
  bool neg_exp = ('-' == *p);
15932
  if (neg_exp || '+' == *p) { p++; } // Skip + as well
15933
15934
  // Exponent: -123.456e-[78]
15935
  auto start_exp = p;
15936
  int64_t exp_number = 0;
15937
  while (parse_digit(*p, exp_number)) { ++p; }
15938
  // It is possible for parse_digit to overflow.
15939
  // In particular, it could overflow to INT64_MIN, and we cannot do - INT64_MIN.
15940
  // Thus we *must* check for possible overflow before we negate exp_number.
15941
15942
  // Performance notes: it may seem like combining the two "simdjson_unlikely checks" below into
15943
  // a single simdjson_unlikely path would be faster. The reasoning is sound, but the compiler may
15944
  // not oblige and may, in fact, generate two distinct paths in any case. It might be
15945
  // possible to do uint64_t(p - start_exp - 1) >= 18 but it could end up trading off
15946
  // instructions for a simdjson_likely branch, an unconclusive gain.
15947
15948
  // If there were no digits, it's an error.
15949
  if (simdjson_unlikely(p == start_exp)) {
15950
    return INVALID_NUMBER(src);
15951
  }
15952
  // We have a valid positive exponent in exp_number at this point, except that
15953
  // it may have overflowed.
15954
15955
  // If there were more than 18 digits, we may have overflowed the integer. We have to do
15956
  // something!!!!
15957
  if (simdjson_unlikely(p > start_exp+18)) {
15958
    // Skip leading zeroes: 1e000000000000000000001 is technically valid and does not overflow
15959
    while (*start_exp == '0') { start_exp++; }
15960
    // 19 digits could overflow int64_t and is kind of absurd anyway. We don't
15961
    // support exponents smaller than -999,999,999,999,999,999 and bigger
15962
    // than 999,999,999,999,999,999.
15963
    // We can truncate.
15964
    // Note that 999999999999999999 is assuredly too large. The maximal ieee64 value before
15965
    // infinity is ~1.8e308. The smallest subnormal is ~5e-324. So, actually, we could
15966
    // truncate at 324.
15967
    // Note that there is no reason to fail per se at this point in time.
15968
    // E.g., 0e999999999999999999999 is a fine number.
15969
    if (p > start_exp+18) { exp_number = 999999999999999999; }
15970
  }
15971
  // At this point, we know that exp_number is a sane, positive, signed integer.
15972
  // It is <= 999,999,999,999,999,999. As long as 'exponent' is in
15973
  // [-8223372036854775808, 8223372036854775808], we won't overflow. Because 'exponent'
15974
  // is bounded in magnitude by the size of the JSON input, we are fine in this universe.
15975
  // To sum it up: the next line should never overflow.
15976
  exponent += (neg_exp ? -exp_number : exp_number);
15977
  return SUCCESS;
15978
}
15979
15980
simdjson_inline bool check_if_integer(const uint8_t *const src, size_t max_length) {
15981
  const uint8_t *const srcend = src + max_length;
15982
  bool negative = (*src == '-'); // we can always read at least one character after the '-'
15983
  const uint8_t *p = src + uint8_t(negative);
15984
  if(p == srcend) { return false; }
15985
  if(*p == '0') {
15986
    ++p;
15987
    if(p == srcend) { return true; }
15988
    if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
15989
    return true;
15990
  }
15991
  while(p != srcend && is_digit(*p)) { ++p; }
15992
  if(p == srcend) { return true; }
15993
  if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
15994
  return true;
15995
}
15996
15997
simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
15998
  // It is possible that the integer had an overflow.
15999
  // We have to handle the case where we have 0.0000somenumber.
16000
  const uint8_t *start = start_digits;
16001
  while ((*start == '0') || (*start == '.')) { ++start; }
16002
  // we over-decrement by one when there is a '.'
16003
  return digit_count - size_t(start - start_digits);
16004
}
16005
16006
} // unnamed namespace
16007
16008
/** @private */
16009
static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
16010
  if (parse_float_fallback(src, answer)) {
16011
    return SUCCESS;
16012
  }
16013
  return INVALID_NUMBER(src);
16014
}
16015
16016
/** @private */
16017
template<typename W>
16018
simdjson_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
16019
  // If we frequently had to deal with long strings of digits,
16020
  // we could extend our code by using a 128-bit integer instead
16021
  // of a 64-bit integer. However, this is uncommon in practice.
16022
  //
16023
  // 9999999999999999999 < 2**64 so we can accommodate 19 digits.
16024
  // If we have a decimal separator, then digit_count - 1 is the number of digits, but we
16025
  // may not have a decimal separator!
16026
  if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
16027
    // Ok, chances are good that we had an overflow!
16028
    // this is almost never going to get called!!!
16029
    // we start anew, going slowly!!!
16030
    // This will happen in the following examples:
16031
    // 10000000000000000000000000000000000000000000e+308
16032
    // 3.1415926535897932384626433832795028841971693993751
16033
    //
16034
    // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
16035
    // reference to it, it would force it to be stored in memory, preventing the compiler from
16036
    // picking it apart and putting into registers. i.e. if we pass it as reference,
16037
    // it gets slow.
16038
    double d;
16039
    error_code error = slow_float_parsing(src, &d);
16040
    writer.append_double(d);
16041
    return error;
16042
  }
16043
  // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
16044
  // way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331
16045
  // To future reader: we'd love if someone found a better way, or at least could explain this result!
16046
  if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
16047
    //
16048
    // Important: smallest_power is such that it leads to a zero value.
16049
    // Observe that 18446744073709551615e-343 == 0, i.e. (2**64 - 1) e -343 is zero
16050
    // so something x 10^-343 goes to zero, but not so with  something x 10^-342.
16051
    static_assert(simdjson::internal::smallest_power <= -342, "smallest_power is not small enough");
16052
    //
16053
    if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
16054
      // E.g. Parse "-0.0e-999" into the same value as "-0.0". See https://en.wikipedia.org/wiki/Signed_zero
16055
      WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
16056
      return SUCCESS;
16057
    } else { // (exponent > largest_power) and (i != 0)
16058
      // We have, for sure, an infinite value and simdjson refuses to parse infinite values.
16059
      return INVALID_NUMBER(src);
16060
    }
16061
  }
16062
  double d;
16063
  if (!compute_float_64(exponent, i, negative, d)) {
16064
    // we are almost never going to get here.
16065
    if (!parse_float_fallback(src, &d)) { return INVALID_NUMBER(src); }
16066
  }
16067
  WRITE_DOUBLE(d, src, writer);
16068
  return SUCCESS;
16069
}
16070
16071
// parse the number at src
16072
// define JSON_TEST_NUMBERS for unit testing
16073
//
16074
// It is assumed that the number is followed by a structural ({,},],[) character
16075
// or a white space character. If that is not the case (e.g., when the JSON
16076
// document is made of a single number), then it is necessary to copy the
16077
// content and append a space before calling this function.
16078
//
16079
// Our objective is accurate parsing (ULP of 0) at high speed.
16080
template<typename W>
16081
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer);
16082
16083
// for performance analysis, it is sometimes  useful to skip parsing
16084
#ifdef SIMDJSON_SKIPNUMBERPARSING
16085
16086
template<typename W>
16087
simdjson_inline error_code parse_number(const uint8_t *const, W &writer) {
16088
  writer.append_s64(0);        // always write zero
16089
  return SUCCESS;              // always succeeds
16090
}
16091
16092
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
16093
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
16094
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
16095
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept { return 0; }
16096
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t * const src) noexcept { return 0; }
16097
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * const src) noexcept { return 0; }
16098
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept  { return false; }
16099
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept  { return false; }
16100
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept { return number_type::signed_integer; }
16101
#else
16102
16103
// parse the number at src
16104
// define JSON_TEST_NUMBERS for unit testing
16105
//
16106
// It is assumed that the number is followed by a structural ({,},],[) character
16107
// or a white space character. If that is not the case (e.g., when the JSON
16108
// document is made of a single number), then it is necessary to copy the
16109
// content and append a space before calling this function.
16110
//
16111
// Our objective is accurate parsing (ULP of 0) at high speed.
16112
template<typename W>
16113
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) {
16114
16115
  //
16116
  // Check for minus sign
16117
  //
16118
  bool negative = (*src == '-');
16119
  const uint8_t *p = src + uint8_t(negative);
16120
16121
  //
16122
  // Parse the integer part.
16123
  //
16124
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
16125
  const uint8_t *const start_digits = p;
16126
  uint64_t i = 0;
16127
  while (parse_digit(*p, i)) { p++; }
16128
16129
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
16130
  // Optimization note: size_t is expected to be unsigned.
16131
  size_t digit_count = size_t(p - start_digits);
16132
  if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
16133
16134
  //
16135
  // Handle floats if there is a . or e (or both)
16136
  //
16137
  int64_t exponent = 0;
16138
  bool is_float = false;
16139
  if ('.' == *p) {
16140
    is_float = true;
16141
    ++p;
16142
    SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
16143
    digit_count = int(p - start_digits); // used later to guard against overflows
16144
  }
16145
  if (('e' == *p) || ('E' == *p)) {
16146
    is_float = true;
16147
    ++p;
16148
    SIMDJSON_TRY( parse_exponent(src, p, exponent) );
16149
  }
16150
  if (is_float) {
16151
    const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
16152
    SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
16153
    if (dirty_end) { return INVALID_NUMBER(src); }
16154
    return SUCCESS;
16155
  }
16156
16157
  // The longest negative 64-bit number is 19 digits.
16158
  // The longest positive 64-bit number is 20 digits.
16159
  // We do it this way so we don't trigger this branch unless we must.
16160
  size_t longest_digit_count = negative ? 19 : 20;
16161
  if (digit_count > longest_digit_count) { return BIGINT_NUMBER(src); }
16162
  if (digit_count == longest_digit_count) {
16163
    if (negative) {
16164
      // Anything negative above INT64_MAX+1 is invalid
16165
      if (i > uint64_t(INT64_MAX)+1) { return BIGINT_NUMBER(src);  }
16166
      WRITE_INTEGER(~i+1, src, writer);
16167
      if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
16168
      return SUCCESS;
16169
    // Positive overflow check:
16170
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
16171
    //   biggest uint64_t.
16172
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
16173
    //   If we got here, it's a 20 digit number starting with the digit "1".
16174
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
16175
    //   than 1,553,255,926,290,448,384.
16176
    // - That is smaller than the smallest possible 20-digit number the user could write:
16177
    //   10,000,000,000,000,000,000.
16178
    // - Therefore, if the number is positive and lower than that, it's overflow.
16179
    // - The value we are looking at is less than or equal to INT64_MAX.
16180
    //
16181
    }  else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
16182
  }
16183
16184
  // Write unsigned if it does not fit in a signed integer.
16185
  if (i > uint64_t(INT64_MAX)) {
16186
    WRITE_UNSIGNED(i, src, writer);
16187
  } else {
16188
    WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
16189
  }
16190
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
16191
  return SUCCESS;
16192
}
16193
16194
// Inlineable functions
16195
namespace {
16196
16197
// This table can be used to characterize the final character of an integer
16198
// string. For JSON structural character and allowable white space characters,
16199
// we return SUCCESS. For 'e', '.' and 'E', we return INCORRECT_TYPE. Otherwise
16200
// we return NUMBER_ERROR.
16201
// Optimization note: we could easily reduce the size of the table by half (to 128)
16202
// at the cost of an extra branch.
16203
// Optimization note: we want the values to use at most 8 bits (not, e.g., 32 bits):
16204
static_assert(error_code(uint8_t(NUMBER_ERROR))== NUMBER_ERROR, "bad NUMBER_ERROR cast");
16205
static_assert(error_code(uint8_t(SUCCESS))== SUCCESS, "bad NUMBER_ERROR cast");
16206
static_assert(error_code(uint8_t(INCORRECT_TYPE))== INCORRECT_TYPE, "bad NUMBER_ERROR cast");
16207
16208
const uint8_t integer_string_finisher[256] = {
16209
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16210
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
16211
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
16212
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16213
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16214
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16215
    NUMBER_ERROR, NUMBER_ERROR,   SUCCESS,      NUMBER_ERROR, NUMBER_ERROR,
16216
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16217
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
16218
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16219
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16220
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
16221
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16222
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, INCORRECT_TYPE,
16223
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16224
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16225
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16226
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16227
    NUMBER_ERROR, SUCCESS,        NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
16228
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16229
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16230
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16231
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16232
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16233
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
16234
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16235
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16236
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16237
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16238
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16239
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16240
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16241
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16242
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16243
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16244
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16245
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16246
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16247
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16248
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16249
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16250
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16251
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16252
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16253
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16254
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16255
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16256
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16257
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16258
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16259
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
16260
    NUMBER_ERROR};
16261
16262
// Parse any number from 0 to 18,446,744,073,709,551,615
16263
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept {
16264
  const uint8_t *p = src;
16265
  //
16266
  // Parse the integer part.
16267
  //
16268
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
16269
  const uint8_t *const start_digits = p;
16270
  uint64_t i = 0;
16271
  while (parse_digit(*p, i)) { p++; }
16272
16273
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
16274
  // Optimization note: size_t is expected to be unsigned.
16275
  size_t digit_count = size_t(p - start_digits);
16276
  // The longest positive 64-bit number is 20 digits.
16277
  // We do it this way so we don't trigger this branch unless we must.
16278
  // Optimization note: the compiler can probably merge
16279
  // ((digit_count == 0) || (digit_count > 20))
16280
  // into a single  branch since digit_count is unsigned.
16281
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
16282
  // Here digit_count > 0.
16283
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
16284
  // We can do the following...
16285
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
16286
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
16287
  // }
16288
  // as a single table lookup:
16289
  if (integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
16290
16291
  if (digit_count == 20) {
16292
    // Positive overflow check:
16293
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
16294
    //   biggest uint64_t.
16295
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
16296
    //   If we got here, it's a 20 digit number starting with the digit "1".
16297
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
16298
    //   than 1,553,255,926,290,448,384.
16299
    // - That is smaller than the smallest possible 20-digit number the user could write:
16300
    //   10,000,000,000,000,000,000.
16301
    // - Therefore, if the number is positive and lower than that, it's overflow.
16302
    // - The value we are looking at is less than or equal to INT64_MAX.
16303
    //
16304
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
16305
  }
16306
16307
  return i;
16308
}
16309
16310
16311
// Parse any number from 0 to 18,446,744,073,709,551,615
16312
// Never read at src_end or beyond
16313
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src, const uint8_t * const src_end) noexcept {
16314
  const uint8_t *p = src;
16315
  //
16316
  // Parse the integer part.
16317
  //
16318
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
16319
  const uint8_t *const start_digits = p;
16320
  uint64_t i = 0;
16321
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
16322
16323
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
16324
  // Optimization note: size_t is expected to be unsigned.
16325
  size_t digit_count = size_t(p - start_digits);
16326
  // The longest positive 64-bit number is 20 digits.
16327
  // We do it this way so we don't trigger this branch unless we must.
16328
  // Optimization note: the compiler can probably merge
16329
  // ((digit_count == 0) || (digit_count > 20))
16330
  // into a single  branch since digit_count is unsigned.
16331
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
16332
  // Here digit_count > 0.
16333
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
16334
  // We can do the following...
16335
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
16336
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
16337
  // }
16338
  // as a single table lookup:
16339
  if ((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
16340
16341
  if (digit_count == 20) {
16342
    // Positive overflow check:
16343
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
16344
    //   biggest uint64_t.
16345
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
16346
    //   If we got here, it's a 20 digit number starting with the digit "1".
16347
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
16348
    //   than 1,553,255,926,290,448,384.
16349
    // - That is smaller than the smallest possible 20-digit number the user could write:
16350
    //   10,000,000,000,000,000,000.
16351
    // - Therefore, if the number is positive and lower than that, it's overflow.
16352
    // - The value we are looking at is less than or equal to INT64_MAX.
16353
    //
16354
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
16355
  }
16356
16357
  return i;
16358
}
16359
16360
// Parse any number from 0 to 18,446,744,073,709,551,615
16361
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept {
16362
  const uint8_t *p = src + 1;
16363
  //
16364
  // Parse the integer part.
16365
  //
16366
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
16367
  const uint8_t *const start_digits = p;
16368
  uint64_t i = 0;
16369
  while (parse_digit(*p, i)) { p++; }
16370
16371
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
16372
  // Optimization note: size_t is expected to be unsigned.
16373
  size_t digit_count = size_t(p - start_digits);
16374
  // The longest positive 64-bit number is 20 digits.
16375
  // We do it this way so we don't trigger this branch unless we must.
16376
  // Optimization note: the compiler can probably merge
16377
  // ((digit_count == 0) || (digit_count > 20))
16378
  // into a single  branch since digit_count is unsigned.
16379
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
16380
  // Here digit_count > 0.
16381
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
16382
  // We can do the following...
16383
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
16384
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
16385
  // }
16386
  // as a single table lookup:
16387
  if (*p != '"') { return NUMBER_ERROR; }
16388
16389
  if (digit_count == 20) {
16390
    // Positive overflow check:
16391
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
16392
    //   biggest uint64_t.
16393
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
16394
    //   If we got here, it's a 20 digit number starting with the digit "1".
16395
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
16396
    //   than 1,553,255,926,290,448,384.
16397
    // - That is smaller than the smallest possible 20-digit number the user could write:
16398
    //   10,000,000,000,000,000,000.
16399
    // - Therefore, if the number is positive and lower than that, it's overflow.
16400
    // - The value we are looking at is less than or equal to INT64_MAX.
16401
    //
16402
    // Note: we use src[1] and not src[0] because src[0] is the quote character in this
16403
    // instance.
16404
    if (src[1] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
16405
  }
16406
16407
  return i;
16408
}
16409
16410
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
16411
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
16412
  //
16413
  // Check for minus sign
16414
  //
16415
  bool negative = (*src == '-');
16416
  const uint8_t *p = src + uint8_t(negative);
16417
16418
  //
16419
  // Parse the integer part.
16420
  //
16421
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
16422
  const uint8_t *const start_digits = p;
16423
  uint64_t i = 0;
16424
  while (parse_digit(*p, i)) { p++; }
16425
16426
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
16427
  // Optimization note: size_t is expected to be unsigned.
16428
  size_t digit_count = size_t(p - start_digits);
16429
  // We go from
16430
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
16431
  // so we can never represent numbers that have more than 19 digits.
16432
  size_t longest_digit_count = 19;
16433
  // Optimization note: the compiler can probably merge
16434
  // ((digit_count == 0) || (digit_count > longest_digit_count))
16435
  // into a single  branch since digit_count is unsigned.
16436
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
16437
  // Here digit_count > 0.
16438
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
16439
  // We can do the following...
16440
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
16441
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
16442
  // }
16443
  // as a single table lookup:
16444
  if(integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
16445
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
16446
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
16447
  // so cheap that we might as well always make it.
16448
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
16449
  return negative ? (~i+1) : i;
16450
}
16451
16452
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
16453
// Never read at src_end or beyond
16454
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src, const uint8_t * const src_end) noexcept {
16455
  //
16456
  // Check for minus sign
16457
  //
16458
  if(src == src_end) { return NUMBER_ERROR; }
16459
  bool negative = (*src == '-');
16460
  const uint8_t *p = src + uint8_t(negative);
16461
16462
  //
16463
  // Parse the integer part.
16464
  //
16465
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
16466
  const uint8_t *const start_digits = p;
16467
  uint64_t i = 0;
16468
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
16469
16470
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
16471
  // Optimization note: size_t is expected to be unsigned.
16472
  size_t digit_count = size_t(p - start_digits);
16473
  // We go from
16474
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
16475
  // so we can never represent numbers that have more than 19 digits.
16476
  size_t longest_digit_count = 19;
16477
  // Optimization note: the compiler can probably merge
16478
  // ((digit_count == 0) || (digit_count > longest_digit_count))
16479
  // into a single  branch since digit_count is unsigned.
16480
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
16481
  // Here digit_count > 0.
16482
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
16483
  // We can do the following...
16484
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
16485
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
16486
  // }
16487
  // as a single table lookup:
16488
  if((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
16489
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
16490
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
16491
  // so cheap that we might as well always make it.
16492
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
16493
  return negative ? (~i+1) : i;
16494
}
16495
16496
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
16497
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t *src) noexcept {
16498
  //
16499
  // Check for minus sign
16500
  //
16501
  bool negative = (*(src + 1) == '-');
16502
  src += uint8_t(negative) + 1;
16503
16504
  //
16505
  // Parse the integer part.
16506
  //
16507
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
16508
  const uint8_t *const start_digits = src;
16509
  uint64_t i = 0;
16510
  while (parse_digit(*src, i)) { src++; }
16511
16512
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
16513
  // Optimization note: size_t is expected to be unsigned.
16514
  size_t digit_count = size_t(src - start_digits);
16515
  // We go from
16516
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
16517
  // so we can never represent numbers that have more than 19 digits.
16518
  size_t longest_digit_count = 19;
16519
  // Optimization note: the compiler can probably merge
16520
  // ((digit_count == 0) || (digit_count > longest_digit_count))
16521
  // into a single  branch since digit_count is unsigned.
16522
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
16523
  // Here digit_count > 0.
16524
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
16525
  // We can do the following...
16526
  // if (!jsoncharutils::is_structural_or_whitespace(*src)) {
16527
  //  return (*src == '.' || *src == 'e' || *src == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
16528
  // }
16529
  // as a single table lookup:
16530
  if(*src != '"') { return NUMBER_ERROR; }
16531
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
16532
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
16533
  // so cheap that we might as well always make it.
16534
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
16535
  return negative ? (~i+1) : i;
16536
}
16537
16538
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
16539
  //
16540
  // Check for minus sign
16541
  //
16542
  bool negative = (*src == '-');
16543
  src += uint8_t(negative);
16544
16545
  //
16546
  // Parse the integer part.
16547
  //
16548
  uint64_t i = 0;
16549
  const uint8_t *p = src;
16550
  p += parse_digit(*p, i);
16551
  bool leading_zero = (i == 0);
16552
  while (parse_digit(*p, i)) { p++; }
16553
  // no integer digits, or 0123 (zero must be solo)
16554
  if ( p == src ) { return INCORRECT_TYPE; }
16555
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
16556
16557
  //
16558
  // Parse the decimal part.
16559
  //
16560
  int64_t exponent = 0;
16561
  bool overflow;
16562
  if (simdjson_likely(*p == '.')) {
16563
    p++;
16564
    const uint8_t *start_decimal_digits = p;
16565
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
16566
    p++;
16567
    while (parse_digit(*p, i)) { p++; }
16568
    exponent = -(p - start_decimal_digits);
16569
16570
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
16571
    overflow = p-src-1 > 19;
16572
    if (simdjson_unlikely(overflow && leading_zero)) {
16573
      // Skip leading 0.00000 and see if it still overflows
16574
      const uint8_t *start_digits = src + 2;
16575
      while (*start_digits == '0') { start_digits++; }
16576
      overflow = p-start_digits > 19;
16577
    }
16578
  } else {
16579
    overflow = p-src > 19;
16580
  }
16581
16582
  //
16583
  // Parse the exponent
16584
  //
16585
  if (*p == 'e' || *p == 'E') {
16586
    p++;
16587
    bool exp_neg = *p == '-';
16588
    p += exp_neg || *p == '+';
16589
16590
    uint64_t exp = 0;
16591
    const uint8_t *start_exp_digits = p;
16592
    while (parse_digit(*p, exp)) { p++; }
16593
    // no exp digits, or 20+ exp digits
16594
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
16595
16596
    exponent += exp_neg ? 0-exp : exp;
16597
  }
16598
16599
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
16600
16601
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
16602
16603
  //
16604
  // Assemble (or slow-parse) the float
16605
  //
16606
  double d;
16607
  if (simdjson_likely(!overflow)) {
16608
    if (compute_float_64(exponent, i, negative, d)) { return d; }
16609
  }
16610
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
16611
    return NUMBER_ERROR;
16612
  }
16613
  return d;
16614
}
16615
16616
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept {
16617
  return (*src == '-');
16618
}
16619
16620
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept {
16621
  bool negative = (*src == '-');
16622
  src += uint8_t(negative);
16623
  const uint8_t *p = src;
16624
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
16625
  if ( p == src ) { return NUMBER_ERROR; }
16626
  if (jsoncharutils::is_structural_or_whitespace(*p)) { return true; }
16627
  return false;
16628
}
16629
16630
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept {
16631
  bool negative = (*src == '-');
16632
  src += uint8_t(negative);
16633
  const uint8_t *p = src;
16634
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
16635
  size_t digit_count = size_t(p - src);
16636
  if ( p == src ) { return NUMBER_ERROR; }
16637
  if (jsoncharutils::is_structural_or_whitespace(*p)) {
16638
    static const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
16639
    // We have an integer.
16640
    if(simdjson_unlikely(digit_count > 20)) {
16641
      return number_type::big_integer;
16642
    }
16643
    // If the number is negative and valid, it must be a signed integer.
16644
    if(negative) {
16645
      if (simdjson_unlikely(digit_count > 19)) return number_type::big_integer;
16646
      if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) {
16647
        return number_type::big_integer;
16648
      }
16649
      return number_type::signed_integer;
16650
    }
16651
    // Let us check if we have a big integer (>=2**64).
16652
    static const uint8_t * two_to_sixtyfour = reinterpret_cast<const uint8_t *>("18446744073709551616");
16653
    if((digit_count > 20) || (digit_count == 20 && memcmp(src, two_to_sixtyfour, 20) >= 0)) {
16654
      return number_type::big_integer;
16655
    }
16656
    // The number is positive and smaller than 18446744073709551616 (or 2**64).
16657
    // We want values larger or equal to 9223372036854775808 to be unsigned
16658
    // integers, and the other values to be signed integers.
16659
    if((digit_count == 20) || (digit_count >= 19 && memcmp(src, smaller_big_integer, 19) >= 0)) {
16660
      return number_type::unsigned_integer;
16661
    }
16662
    return number_type::signed_integer;
16663
  }
16664
  // Hopefully, we have 'e' or 'E' or '.'.
16665
  return number_type::floating_point_number;
16666
}
16667
16668
// Never read at src_end or beyond
16669
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
16670
  if(src == src_end) { return NUMBER_ERROR; }
16671
  //
16672
  // Check for minus sign
16673
  //
16674
  bool negative = (*src == '-');
16675
  src += uint8_t(negative);
16676
16677
  //
16678
  // Parse the integer part.
16679
  //
16680
  uint64_t i = 0;
16681
  const uint8_t *p = src;
16682
  if(p == src_end) { return NUMBER_ERROR; }
16683
  p += parse_digit(*p, i);
16684
  bool leading_zero = (i == 0);
16685
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
16686
  // no integer digits, or 0123 (zero must be solo)
16687
  if ( p == src ) { return INCORRECT_TYPE; }
16688
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
16689
16690
  //
16691
  // Parse the decimal part.
16692
  //
16693
  int64_t exponent = 0;
16694
  bool overflow;
16695
  if (simdjson_likely((p != src_end) && (*p == '.'))) {
16696
    p++;
16697
    const uint8_t *start_decimal_digits = p;
16698
    if ((p == src_end) || !parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
16699
    p++;
16700
    while ((p != src_end) && parse_digit(*p, i)) { p++; }
16701
    exponent = -(p - start_decimal_digits);
16702
16703
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
16704
    overflow = p-src-1 > 19;
16705
    if (simdjson_unlikely(overflow && leading_zero)) {
16706
      // Skip leading 0.00000 and see if it still overflows
16707
      const uint8_t *start_digits = src + 2;
16708
      while (*start_digits == '0') { start_digits++; }
16709
      overflow = start_digits-src > 19;
16710
    }
16711
  } else {
16712
    overflow = p-src > 19;
16713
  }
16714
16715
  //
16716
  // Parse the exponent
16717
  //
16718
  if ((p != src_end) && (*p == 'e' || *p == 'E')) {
16719
    p++;
16720
    if(p == src_end) { return NUMBER_ERROR; }
16721
    bool exp_neg = *p == '-';
16722
    p += exp_neg || *p == '+';
16723
16724
    uint64_t exp = 0;
16725
    const uint8_t *start_exp_digits = p;
16726
    while ((p != src_end) && parse_digit(*p, exp)) { p++; }
16727
    // no exp digits, or 20+ exp digits
16728
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
16729
16730
    exponent += exp_neg ? 0-exp : exp;
16731
  }
16732
16733
  if ((p != src_end) && jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
16734
16735
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
16736
16737
  //
16738
  // Assemble (or slow-parse) the float
16739
  //
16740
  double d;
16741
  if (simdjson_likely(!overflow)) {
16742
    if (compute_float_64(exponent, i, negative, d)) { return d; }
16743
  }
16744
  if (!parse_float_fallback(src - uint8_t(negative), src_end, &d)) {
16745
    return NUMBER_ERROR;
16746
  }
16747
  return d;
16748
}
16749
16750
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * src) noexcept {
16751
  //
16752
  // Check for minus sign
16753
  //
16754
  bool negative = (*(src + 1) == '-');
16755
  src += uint8_t(negative) + 1;
16756
16757
  //
16758
  // Parse the integer part.
16759
  //
16760
  uint64_t i = 0;
16761
  const uint8_t *p = src;
16762
  p += parse_digit(*p, i);
16763
  bool leading_zero = (i == 0);
16764
  while (parse_digit(*p, i)) { p++; }
16765
  // no integer digits, or 0123 (zero must be solo)
16766
  if ( p == src ) { return INCORRECT_TYPE; }
16767
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
16768
16769
  //
16770
  // Parse the decimal part.
16771
  //
16772
  int64_t exponent = 0;
16773
  bool overflow;
16774
  if (simdjson_likely(*p == '.')) {
16775
    p++;
16776
    const uint8_t *start_decimal_digits = p;
16777
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
16778
    p++;
16779
    while (parse_digit(*p, i)) { p++; }
16780
    exponent = -(p - start_decimal_digits);
16781
16782
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
16783
    overflow = p-src-1 > 19;
16784
    if (simdjson_unlikely(overflow && leading_zero)) {
16785
      // Skip leading 0.00000 and see if it still overflows
16786
      const uint8_t *start_digits = src + 2;
16787
      while (*start_digits == '0') { start_digits++; }
16788
      overflow = p-start_digits > 19;
16789
    }
16790
  } else {
16791
    overflow = p-src > 19;
16792
  }
16793
16794
  //
16795
  // Parse the exponent
16796
  //
16797
  if (*p == 'e' || *p == 'E') {
16798
    p++;
16799
    bool exp_neg = *p == '-';
16800
    p += exp_neg || *p == '+';
16801
16802
    uint64_t exp = 0;
16803
    const uint8_t *start_exp_digits = p;
16804
    while (parse_digit(*p, exp)) { p++; }
16805
    // no exp digits, or 20+ exp digits
16806
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
16807
16808
    exponent += exp_neg ? 0-exp : exp;
16809
  }
16810
16811
  if (*p != '"') { return NUMBER_ERROR; }
16812
16813
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
16814
16815
  //
16816
  // Assemble (or slow-parse) the float
16817
  //
16818
  double d;
16819
  if (simdjson_likely(!overflow)) {
16820
    if (compute_float_64(exponent, i, negative, d)) { return d; }
16821
  }
16822
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
16823
    return NUMBER_ERROR;
16824
  }
16825
  return d;
16826
}
16827
16828
} // unnamed namespace
16829
#endif // SIMDJSON_SKIPNUMBERPARSING
16830
16831
} // namespace numberparsing
16832
16833
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
16834
    switch (type) {
16835
        case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
16836
        case number_type::unsigned_integer: out << "unsigned integer in [9223372036854775808,18446744073709551616)"; break;
16837
        case number_type::floating_point_number: out << "floating-point number (binary64)"; break;
16838
        case number_type::big_integer: out << "big integer"; break;
16839
        default: SIMDJSON_UNREACHABLE();
16840
    }
16841
    return out;
16842
}
16843
16844
} // namespace haswell
16845
} // namespace simdjson
16846
16847
#endif // SIMDJSON_GENERIC_NUMBERPARSING_H
16848
/* end file simdjson/generic/numberparsing.h for haswell */
16849
16850
/* including simdjson/generic/implementation_simdjson_result_base-inl.h for haswell: #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
16851
/* begin file simdjson/generic/implementation_simdjson_result_base-inl.h for haswell */
16852
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
16853
16854
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
16855
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H */
16856
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
16857
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
16858
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
16859
16860
namespace simdjson {
16861
namespace haswell {
16862
16863
//
16864
// internal::implementation_simdjson_result_base<T> inline implementation
16865
//
16866
16867
template<typename T>
16868
simdjson_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
16869
  error = this->second;
16870
  if (!error) {
16871
    value = std::forward<implementation_simdjson_result_base<T>>(*this).first;
16872
  }
16873
}
16874
16875
template<typename T>
16876
simdjson_warn_unused simdjson_inline error_code implementation_simdjson_result_base<T>::get(T &value) && noexcept {
16877
  error_code error;
16878
  std::forward<implementation_simdjson_result_base<T>>(*this).tie(value, error);
16879
  return error;
16880
}
16881
16882
template<typename T>
16883
simdjson_inline error_code implementation_simdjson_result_base<T>::error() const noexcept {
16884
  return this->second;
16885
}
16886
16887
#if SIMDJSON_EXCEPTIONS
16888
16889
template<typename T>
16890
simdjson_inline T& implementation_simdjson_result_base<T>::value() & noexcept(false) {
16891
  if (error()) { throw simdjson_error(error()); }
16892
  return this->first;
16893
}
16894
16895
template<typename T>
16896
simdjson_inline T&& implementation_simdjson_result_base<T>::value() && noexcept(false) {
16897
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
16898
}
16899
16900
template<typename T>
16901
simdjson_inline T&& implementation_simdjson_result_base<T>::take_value() && noexcept(false) {
16902
  if (error()) { throw simdjson_error(error()); }
16903
  return std::forward<T>(this->first);
16904
}
16905
16906
template<typename T>
16907
simdjson_inline implementation_simdjson_result_base<T>::operator T&&() && noexcept(false) {
16908
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
16909
}
16910
16911
#endif // SIMDJSON_EXCEPTIONS
16912
16913
template<typename T>
16914
simdjson_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
16915
  return this->first;
16916
}
16917
16918
template<typename T>
16919
simdjson_inline T& implementation_simdjson_result_base<T>::value_unsafe() & noexcept {
16920
  return this->first;
16921
}
16922
16923
template<typename T>
16924
simdjson_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
16925
  return std::forward<T>(this->first);
16926
}
16927
16928
template<typename T>
16929
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
16930
    : first{std::forward<T>(value)}, second{error} {}
16931
template<typename T>
16932
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(error_code error) noexcept
16933
    : implementation_simdjson_result_base(T{}, error) {}
16934
template<typename T>
16935
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
16936
    : implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
16937
16938
} // namespace haswell
16939
} // namespace simdjson
16940
16941
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
16942
/* end file simdjson/generic/implementation_simdjson_result_base-inl.h for haswell */
16943
/* end file simdjson/generic/amalgamated.h for haswell */
16944
/* including simdjson/haswell/end.h: #include "simdjson/haswell/end.h" */
16945
/* begin file simdjson/haswell/end.h */
16946
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
16947
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
16948
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
16949
16950
#if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL
16951
SIMDJSON_UNTARGET_REGION
16952
#endif
16953
16954
/* undefining SIMDJSON_IMPLEMENTATION from "haswell" */
16955
#undef SIMDJSON_IMPLEMENTATION
16956
/* end file simdjson/haswell/end.h */
16957
16958
#endif // SIMDJSON_HASWELL_H
16959
/* end file simdjson/haswell.h */
16960
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
16961
/* including simdjson/icelake.h: #include "simdjson/icelake.h" */
16962
/* begin file simdjson/icelake.h */
16963
#ifndef SIMDJSON_ICELAKE_H
16964
#define SIMDJSON_ICELAKE_H
16965
16966
/* including simdjson/icelake/begin.h: #include "simdjson/icelake/begin.h" */
16967
/* begin file simdjson/icelake/begin.h */
16968
/* defining SIMDJSON_IMPLEMENTATION to "icelake" */
16969
#define SIMDJSON_IMPLEMENTATION icelake
16970
/* including simdjson/icelake/base.h: #include "simdjson/icelake/base.h" */
16971
/* begin file simdjson/icelake/base.h */
16972
#ifndef SIMDJSON_ICELAKE_BASE_H
16973
#define SIMDJSON_ICELAKE_BASE_H
16974
16975
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
16976
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
16977
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
16978
16979
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_ICELAKE
16980
namespace simdjson {
16981
/**
16982
 * Implementation for Icelake (Intel AVX512).
16983
 */
16984
namespace icelake {
16985
16986
class implementation;
16987
16988
} // namespace icelake
16989
} // namespace simdjson
16990
16991
#endif // SIMDJSON_ICELAKE_BASE_H
16992
/* end file simdjson/icelake/base.h */
16993
/* including simdjson/icelake/intrinsics.h: #include "simdjson/icelake/intrinsics.h" */
16994
/* begin file simdjson/icelake/intrinsics.h */
16995
#ifndef SIMDJSON_ICELAKE_INTRINSICS_H
16996
#define SIMDJSON_ICELAKE_INTRINSICS_H
16997
16998
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
16999
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
17000
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17001
17002
#if SIMDJSON_VISUAL_STUDIO
17003
// under clang within visual studio, this will include <x86intrin.h>
17004
#include <intrin.h>  // visual studio or clang
17005
#else
17006
#include <x86intrin.h> // elsewhere
17007
#endif // SIMDJSON_VISUAL_STUDIO
17008
17009
#if SIMDJSON_CLANG_VISUAL_STUDIO
17010
/**
17011
 * You are not supposed, normally, to include these
17012
 * headers directly. Instead you should either include intrin.h
17013
 * or x86intrin.h. However, when compiling with clang
17014
 * under Windows (i.e., when _MSC_VER is set), these headers
17015
 * only get included *if* the corresponding features are detected
17016
 * from macros:
17017
 * e.g., if __AVX2__ is set... in turn,  we normally set these
17018
 * macros by compiling against the corresponding architecture
17019
 * (e.g., arch:AVX2, -mavx2, etc.) which compiles the whole
17020
 * software with these advanced instructions. In simdjson, we
17021
 * want to compile the whole program for a generic target,
17022
 * and only target our specific kernels. As a workaround,
17023
 * we directly include the needed headers. These headers would
17024
 * normally guard against such usage, but we carefully included
17025
 * <x86intrin.h>  (or <intrin.h>) before, so the headers
17026
 * are fooled.
17027
 */
17028
#include <bmiintrin.h>   // for _blsr_u64
17029
#include <lzcntintrin.h> // for  __lzcnt64
17030
#include <immintrin.h>   // for most things (AVX2, AVX512, _popcnt64)
17031
#include <smmintrin.h>
17032
#include <tmmintrin.h>
17033
#include <avxintrin.h>
17034
#include <avx2intrin.h>
17035
#include <wmmintrin.h>   // for  _mm_clmulepi64_si128
17036
// Important: we need the AVX-512 headers:
17037
#include <avx512fintrin.h>
17038
#include <avx512dqintrin.h>
17039
#include <avx512cdintrin.h>
17040
#include <avx512bwintrin.h>
17041
#include <avx512vlintrin.h>
17042
#include <avx512vbmiintrin.h>
17043
#include <avx512vbmi2intrin.h>
17044
// unfortunately, we may not get _blsr_u64, but, thankfully, clang
17045
// has it as a macro.
17046
#ifndef _blsr_u64
17047
// we roll our own
17048
#define _blsr_u64(n) ((n - 1) & n)
17049
#endif //  _blsr_u64
17050
#endif // SIMDJSON_CLANG_VISUAL_STUDIO
17051
17052
static_assert(sizeof(__m512i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for icelake");
17053
17054
#endif // SIMDJSON_ICELAKE_INTRINSICS_H
17055
/* end file simdjson/icelake/intrinsics.h */
17056
17057
#if !SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
17058
SIMDJSON_TARGET_REGION("avx512f,avx512dq,avx512cd,avx512bw,avx512vbmi,avx512vbmi2,avx512vl,avx2,bmi,pclmul,lzcnt,popcnt")
17059
#endif
17060
17061
/* including simdjson/icelake/bitmanipulation.h: #include "simdjson/icelake/bitmanipulation.h" */
17062
/* begin file simdjson/icelake/bitmanipulation.h */
17063
#ifndef SIMDJSON_ICELAKE_BITMANIPULATION_H
17064
#define SIMDJSON_ICELAKE_BITMANIPULATION_H
17065
17066
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17067
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
17068
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
17069
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17070
17071
namespace simdjson {
17072
namespace icelake {
17073
namespace {
17074
17075
// We sometimes call trailing_zero on inputs that are zero,
17076
// but the algorithms do not end up using the returned value.
17077
// Sadly, sanitizers are not smart enough to figure it out.
17078
SIMDJSON_NO_SANITIZE_UNDEFINED
17079
// This function can be used safely even if not all bytes have been
17080
// initialized.
17081
// See issue https://github.com/simdjson/simdjson/issues/1965
17082
SIMDJSON_NO_SANITIZE_MEMORY
17083
simdjson_inline int trailing_zeroes(uint64_t input_num) {
17084
#if SIMDJSON_REGULAR_VISUAL_STUDIO
17085
  return (int)_tzcnt_u64(input_num);
17086
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
17087
  ////////
17088
  // You might expect the next line to be equivalent to
17089
  // return (int)_tzcnt_u64(input_num);
17090
  // but the generated code differs and might be less efficient?
17091
  ////////
17092
  return __builtin_ctzll(input_num);
17093
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
17094
}
17095
17096
/* result might be undefined when input_num is zero */
17097
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
17098
  return _blsr_u64(input_num);
17099
}
17100
17101
/* result might be undefined when input_num is zero */
17102
simdjson_inline int leading_zeroes(uint64_t input_num) {
17103
  return int(_lzcnt_u64(input_num));
17104
}
17105
17106
#if SIMDJSON_REGULAR_VISUAL_STUDIO
17107
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
17108
  // note: we do not support legacy 32-bit Windows
17109
  return __popcnt64(input_num);// Visual Studio wants two underscores
17110
}
17111
#else
17112
simdjson_inline long long int count_ones(uint64_t input_num) {
17113
  return _popcnt64(input_num);
17114
}
17115
#endif
17116
17117
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
17118
                                uint64_t *result) {
17119
#if SIMDJSON_REGULAR_VISUAL_STUDIO
17120
  return _addcarry_u64(0, value1, value2,
17121
                       reinterpret_cast<unsigned __int64 *>(result));
17122
#else
17123
  return __builtin_uaddll_overflow(value1, value2,
17124
                                   reinterpret_cast<unsigned long long *>(result));
17125
#endif
17126
}
17127
17128
} // unnamed namespace
17129
} // namespace icelake
17130
} // namespace simdjson
17131
17132
#endif // SIMDJSON_ICELAKE_BITMANIPULATION_H
17133
/* end file simdjson/icelake/bitmanipulation.h */
17134
/* including simdjson/icelake/bitmask.h: #include "simdjson/icelake/bitmask.h" */
17135
/* begin file simdjson/icelake/bitmask.h */
17136
#ifndef SIMDJSON_ICELAKE_BITMASK_H
17137
#define SIMDJSON_ICELAKE_BITMASK_H
17138
17139
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17140
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
17141
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
17142
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17143
17144
namespace simdjson {
17145
namespace icelake {
17146
namespace {
17147
17148
//
17149
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
17150
//
17151
// For example, prefix_xor(00100100) == 00011100
17152
//
17153
simdjson_inline uint64_t prefix_xor(const uint64_t bitmask) {
17154
  // There should be no such thing with a processor supporting avx2
17155
  // but not clmul.
17156
  __m128i all_ones = _mm_set1_epi8('\xFF');
17157
  __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, bitmask), all_ones, 0);
17158
  return _mm_cvtsi128_si64(result);
17159
}
17160
17161
} // unnamed namespace
17162
} // namespace icelake
17163
} // namespace simdjson
17164
17165
#endif // SIMDJSON_ICELAKE_BITMASK_H
17166
/* end file simdjson/icelake/bitmask.h */
17167
/* including simdjson/icelake/simd.h: #include "simdjson/icelake/simd.h" */
17168
/* begin file simdjson/icelake/simd.h */
17169
#ifndef SIMDJSON_ICELAKE_SIMD_H
17170
#define SIMDJSON_ICELAKE_SIMD_H
17171
17172
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17173
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
17174
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
17175
/* amalgamation skipped (editor-only): #include "simdjson/icelake/bitmanipulation.h" */
17176
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
17177
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17178
17179
#if defined(__GNUC__) && !defined(__clang__)
17180
#if __GNUC__ == 8
17181
#define SIMDJSON_GCC8 1
17182
#endif //  __GNUC__ == 8
17183
#endif // defined(__GNUC__) && !defined(__clang__)
17184
17185
#if SIMDJSON_GCC8
17186
/**
17187
 * GCC 8 fails to provide _mm512_set_epi8. We roll our own.
17188
 */
17189
inline __m512i _mm512_set_epi8(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, uint8_t a7, uint8_t a8, uint8_t a9, uint8_t a10, uint8_t a11, uint8_t a12, uint8_t a13, uint8_t a14, uint8_t a15, uint8_t a16, uint8_t a17, uint8_t a18, uint8_t a19, uint8_t a20, uint8_t a21, uint8_t a22, uint8_t a23, uint8_t a24, uint8_t a25, uint8_t a26, uint8_t a27, uint8_t a28, uint8_t a29, uint8_t a30, uint8_t a31, uint8_t a32, uint8_t a33, uint8_t a34, uint8_t a35, uint8_t a36, uint8_t a37, uint8_t a38, uint8_t a39, uint8_t a40, uint8_t a41, uint8_t a42, uint8_t a43, uint8_t a44, uint8_t a45, uint8_t a46, uint8_t a47, uint8_t a48, uint8_t a49, uint8_t a50, uint8_t a51, uint8_t a52, uint8_t a53, uint8_t a54, uint8_t a55, uint8_t a56, uint8_t a57, uint8_t a58, uint8_t a59, uint8_t a60, uint8_t a61, uint8_t a62, uint8_t a63) {
17190
  return _mm512_set_epi64(uint64_t(a7) + (uint64_t(a6) << 8) + (uint64_t(a5) << 16) + (uint64_t(a4) << 24) + (uint64_t(a3) << 32) + (uint64_t(a2) << 40) + (uint64_t(a1) << 48) + (uint64_t(a0) << 56),
17191
                          uint64_t(a15) + (uint64_t(a14) << 8) + (uint64_t(a13) << 16) + (uint64_t(a12) << 24) + (uint64_t(a11) << 32) + (uint64_t(a10) << 40) + (uint64_t(a9) << 48) + (uint64_t(a8) << 56),
17192
                          uint64_t(a23) + (uint64_t(a22) << 8) + (uint64_t(a21) << 16) + (uint64_t(a20) << 24) + (uint64_t(a19) << 32) + (uint64_t(a18) << 40) + (uint64_t(a17) << 48) + (uint64_t(a16) << 56),
17193
                          uint64_t(a31) + (uint64_t(a30) << 8) + (uint64_t(a29) << 16) + (uint64_t(a28) << 24) + (uint64_t(a27) << 32) + (uint64_t(a26) << 40) + (uint64_t(a25) << 48) + (uint64_t(a24) << 56),
17194
                          uint64_t(a39) + (uint64_t(a38) << 8) + (uint64_t(a37) << 16) + (uint64_t(a36) << 24) + (uint64_t(a35) << 32) + (uint64_t(a34) << 40) + (uint64_t(a33) << 48) + (uint64_t(a32) << 56),
17195
                          uint64_t(a47) + (uint64_t(a46) << 8) + (uint64_t(a45) << 16) + (uint64_t(a44) << 24) + (uint64_t(a43) << 32) + (uint64_t(a42) << 40) + (uint64_t(a41) << 48) + (uint64_t(a40) << 56),
17196
                          uint64_t(a55) + (uint64_t(a54) << 8) + (uint64_t(a53) << 16) + (uint64_t(a52) << 24) + (uint64_t(a51) << 32) + (uint64_t(a50) << 40) + (uint64_t(a49) << 48) + (uint64_t(a48) << 56),
17197
                          uint64_t(a63) + (uint64_t(a62) << 8) + (uint64_t(a61) << 16) + (uint64_t(a60) << 24) + (uint64_t(a59) << 32) + (uint64_t(a58) << 40) + (uint64_t(a57) << 48) + (uint64_t(a56) << 56));
17198
}
17199
#endif // SIMDJSON_GCC8
17200
17201
17202
17203
namespace simdjson {
17204
namespace icelake {
17205
namespace {
17206
namespace simd {
17207
17208
  // Forward-declared so they can be used by splat and friends.
17209
  template<typename Child>
17210
  struct base {
17211
    __m512i value;
17212
17213
    // Zero constructor
17214
    simdjson_inline base() : value{__m512i()} {}
17215
17216
    // Conversion from SIMD register
17217
    simdjson_inline base(const __m512i _value) : value(_value) {}
17218
17219
    // Conversion to SIMD register
17220
    simdjson_inline operator const __m512i&() const { return this->value; }
17221
    simdjson_inline operator __m512i&() { return this->value; }
17222
17223
    // Bit operations
17224
    simdjson_inline Child operator|(const Child other) const { return _mm512_or_si512(*this, other); }
17225
    simdjson_inline Child operator&(const Child other) const { return _mm512_and_si512(*this, other); }
17226
    simdjson_inline Child operator^(const Child other) const { return _mm512_xor_si512(*this, other); }
17227
    simdjson_inline Child bit_andnot(const Child other) const { return _mm512_andnot_si512(other, *this); }
17228
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
17229
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
17230
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
17231
  };
17232
17233
  // Forward-declared so they can be used by splat and friends.
17234
  template<typename T>
17235
  struct simd8;
17236
17237
  template<typename T, typename Mask=simd8<bool>>
17238
  struct base8: base<simd8<T>> {
17239
    typedef uint32_t bitmask_t;
17240
    typedef uint64_t bitmask2_t;
17241
17242
    simdjson_inline base8() : base<simd8<T>>() {}
17243
    simdjson_inline base8(const __m512i _value) : base<simd8<T>>(_value) {}
17244
17245
    friend simdjson_really_inline uint64_t operator==(const simd8<T> lhs, const simd8<T> rhs) {
17246
      return _mm512_cmpeq_epi8_mask(lhs, rhs);
17247
    }
17248
17249
    static const int SIZE = sizeof(base<T>::value);
17250
17251
    template<int N=1>
17252
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
17253
     // workaround for compilers unable to figure out that 16 - N is a constant (GCC 8)
17254
      constexpr int shift = 16 - N;
17255
      return _mm512_alignr_epi8(*this, _mm512_permutex2var_epi64(prev_chunk, _mm512_set_epi64(13, 12, 11, 10, 9, 8, 7, 6), *this), shift);
17256
    }
17257
  };
17258
17259
  // SIMD byte mask type (returned by things like eq and gt)
17260
  template<>
17261
  struct simd8<bool>: base8<bool> {
17262
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm512_set1_epi8(uint8_t(-(!!_value))); }
17263
17264
    simdjson_inline simd8<bool>() : base8() {}
17265
    simdjson_inline simd8<bool>(const __m512i _value) : base8<bool>(_value) {}
17266
    // Splat constructor
17267
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
17268
    simdjson_inline bool any() const { return !!_mm512_test_epi8_mask (*this, *this); }
17269
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
17270
  };
17271
17272
  template<typename T>
17273
  struct base8_numeric: base8<T> {
17274
    static simdjson_inline simd8<T> splat(T _value) { return _mm512_set1_epi8(_value); }
17275
    static simdjson_inline simd8<T> zero() { return _mm512_setzero_si512(); }
17276
    static simdjson_inline simd8<T> load(const T values[64]) {
17277
      return _mm512_loadu_si512(reinterpret_cast<const __m512i *>(values));
17278
    }
17279
    // Repeat 16 values as many times as necessary (usually for lookup tables)
17280
    static simdjson_inline simd8<T> repeat_16(
17281
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
17282
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
17283
    ) {
17284
      return simd8<T>(
17285
        v0, v1, v2, v3, v4, v5, v6, v7,
17286
        v8, v9, v10,v11,v12,v13,v14,v15,
17287
        v0, v1, v2, v3, v4, v5, v6, v7,
17288
        v8, v9, v10,v11,v12,v13,v14,v15,
17289
        v0, v1, v2, v3, v4, v5, v6, v7,
17290
        v8, v9, v10,v11,v12,v13,v14,v15,
17291
        v0, v1, v2, v3, v4, v5, v6, v7,
17292
        v8, v9, v10,v11,v12,v13,v14,v15
17293
      );
17294
    }
17295
17296
    simdjson_inline base8_numeric() : base8<T>() {}
17297
    simdjson_inline base8_numeric(const __m512i _value) : base8<T>(_value) {}
17298
17299
    // Store to array
17300
    simdjson_inline void store(T dst[64]) const { return _mm512_storeu_si512(reinterpret_cast<__m512i *>(dst), *this); }
17301
17302
    // Addition/subtraction are the same for signed and unsigned
17303
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm512_add_epi8(*this, other); }
17304
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm512_sub_epi8(*this, other); }
17305
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
17306
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
17307
17308
    // Override to distinguish from bool version
17309
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
17310
17311
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
17312
    template<typename L>
17313
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
17314
      return _mm512_shuffle_epi8(lookup_table, *this);
17315
    }
17316
17317
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
17318
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
17319
    // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes
17320
    // get written.
17321
    // Design consideration: it seems like a function with the
17322
    // signature simd8<L> compress(uint32_t mask) would be
17323
    // sensible, but the AVX ISA makes this kind of approach difficult.
17324
    template<typename L>
17325
    simdjson_inline void compress(uint64_t mask, L * output) const {
17326
      _mm512_mask_compressstoreu_epi8 (output,~mask,*this);
17327
    }
17328
17329
    template<typename L>
17330
    simdjson_inline simd8<L> lookup_16(
17331
        L replace0,  L replace1,  L replace2,  L replace3,
17332
        L replace4,  L replace5,  L replace6,  L replace7,
17333
        L replace8,  L replace9,  L replace10, L replace11,
17334
        L replace12, L replace13, L replace14, L replace15) const {
17335
      return lookup_16(simd8<L>::repeat_16(
17336
        replace0,  replace1,  replace2,  replace3,
17337
        replace4,  replace5,  replace6,  replace7,
17338
        replace8,  replace9,  replace10, replace11,
17339
        replace12, replace13, replace14, replace15
17340
      ));
17341
    }
17342
  };
17343
17344
  // Signed bytes
17345
  template<>
17346
  struct simd8<int8_t> : base8_numeric<int8_t> {
17347
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
17348
    simdjson_inline simd8(const __m512i _value) : base8_numeric<int8_t>(_value) {}
17349
    // Splat constructor
17350
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
17351
    // Array constructor
17352
    simdjson_inline simd8(const int8_t values[64]) : simd8(load(values)) {}
17353
    // Member-by-member initialization
17354
    simdjson_inline simd8(
17355
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
17356
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15,
17357
      int8_t v16, int8_t v17, int8_t v18, int8_t v19, int8_t v20, int8_t v21, int8_t v22, int8_t v23,
17358
      int8_t v24, int8_t v25, int8_t v26, int8_t v27, int8_t v28, int8_t v29, int8_t v30, int8_t v31,
17359
      int8_t v32, int8_t v33, int8_t v34, int8_t v35, int8_t v36, int8_t v37, int8_t v38, int8_t v39,
17360
      int8_t v40, int8_t v41, int8_t v42, int8_t v43, int8_t v44, int8_t v45, int8_t v46, int8_t v47,
17361
      int8_t v48, int8_t v49, int8_t v50, int8_t v51, int8_t v52, int8_t v53, int8_t v54, int8_t v55,
17362
      int8_t v56, int8_t v57, int8_t v58, int8_t v59, int8_t v60, int8_t v61, int8_t v62, int8_t v63
17363
    ) : simd8(_mm512_set_epi8(
17364
      v63, v62, v61, v60, v59, v58, v57, v56,
17365
      v55, v54, v53, v52, v51, v50, v49, v48,
17366
      v47, v46, v45, v44, v43, v42, v41, v40,
17367
      v39, v38, v37, v36, v35, v34, v33, v32,
17368
      v31, v30, v29, v28, v27, v26, v25, v24,
17369
      v23, v22, v21, v20, v19, v18, v17, v16,
17370
      v15, v14, v13, v12, v11, v10,  v9,  v8,
17371
       v7,  v6,  v5,  v4,  v3,  v2,  v1,  v0
17372
    )) {}
17373
17374
    // Repeat 16 values as many times as necessary (usually for lookup tables)
17375
    simdjson_inline static simd8<int8_t> repeat_16(
17376
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
17377
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
17378
    ) {
17379
      return simd8<int8_t>(
17380
        v0, v1, v2, v3, v4, v5, v6, v7,
17381
        v8, v9, v10,v11,v12,v13,v14,v15,
17382
        v0, v1, v2, v3, v4, v5, v6, v7,
17383
        v8, v9, v10,v11,v12,v13,v14,v15,
17384
        v0, v1, v2, v3, v4, v5, v6, v7,
17385
        v8, v9, v10,v11,v12,v13,v14,v15,
17386
        v0, v1, v2, v3, v4, v5, v6, v7,
17387
        v8, v9, v10,v11,v12,v13,v14,v15
17388
      );
17389
    }
17390
17391
    // Order-sensitive comparisons
17392
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm512_max_epi8(*this, other); }
17393
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm512_min_epi8(*this, other); }
17394
17395
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm512_maskz_abs_epi8(_mm512_cmpgt_epi8_mask(*this, other),_mm512_set1_epi8(uint8_t(0x80))); }
17396
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm512_maskz_abs_epi8(_mm512_cmpgt_epi8_mask(other, *this),_mm512_set1_epi8(uint8_t(0x80))); }
17397
  };
17398
17399
  // Unsigned bytes
17400
  template<>
17401
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
17402
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
17403
    simdjson_inline simd8(const __m512i _value) : base8_numeric<uint8_t>(_value) {}
17404
    // Splat constructor
17405
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
17406
    // Array constructor
17407
    simdjson_inline simd8(const uint8_t values[64]) : simd8(load(values)) {}
17408
    // Member-by-member initialization
17409
    simdjson_inline simd8(
17410
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
17411
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15,
17412
      uint8_t v16, uint8_t v17, uint8_t v18, uint8_t v19, uint8_t v20, uint8_t v21, uint8_t v22, uint8_t v23,
17413
      uint8_t v24, uint8_t v25, uint8_t v26, uint8_t v27, uint8_t v28, uint8_t v29, uint8_t v30, uint8_t v31,
17414
      uint8_t v32, uint8_t v33, uint8_t v34, uint8_t v35, uint8_t v36, uint8_t v37, uint8_t v38, uint8_t v39,
17415
      uint8_t v40, uint8_t v41, uint8_t v42, uint8_t v43, uint8_t v44, uint8_t v45, uint8_t v46, uint8_t v47,
17416
      uint8_t v48, uint8_t v49, uint8_t v50, uint8_t v51, uint8_t v52, uint8_t v53, uint8_t v54, uint8_t v55,
17417
      uint8_t v56, uint8_t v57, uint8_t v58, uint8_t v59, uint8_t v60, uint8_t v61, uint8_t v62, uint8_t v63
17418
    ) : simd8(_mm512_set_epi8(
17419
      v63, v62, v61, v60, v59, v58, v57, v56,
17420
      v55, v54, v53, v52, v51, v50, v49, v48,
17421
      v47, v46, v45, v44, v43, v42, v41, v40,
17422
      v39, v38, v37, v36, v35, v34, v33, v32,
17423
      v31, v30, v29, v28, v27, v26, v25, v24,
17424
      v23, v22, v21, v20, v19, v18, v17, v16,
17425
      v15, v14, v13, v12, v11, v10,  v9,  v8,
17426
       v7,  v6,  v5,  v4,  v3,  v2,  v1,  v0
17427
    )) {}
17428
17429
    // Repeat 16 values as many times as necessary (usually for lookup tables)
17430
    simdjson_inline static simd8<uint8_t> repeat_16(
17431
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
17432
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
17433
    ) {
17434
      return simd8<uint8_t>(
17435
        v0, v1, v2, v3, v4, v5, v6, v7,
17436
        v8, v9, v10,v11,v12,v13,v14,v15,
17437
        v0, v1, v2, v3, v4, v5, v6, v7,
17438
        v8, v9, v10,v11,v12,v13,v14,v15,
17439
        v0, v1, v2, v3, v4, v5, v6, v7,
17440
        v8, v9, v10,v11,v12,v13,v14,v15,
17441
        v0, v1, v2, v3, v4, v5, v6, v7,
17442
        v8, v9, v10,v11,v12,v13,v14,v15
17443
      );
17444
    }
17445
17446
    // Saturated math
17447
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm512_adds_epu8(*this, other); }
17448
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm512_subs_epu8(*this, other); }
17449
17450
    // Order-specific operations
17451
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm512_max_epu8(*this, other); }
17452
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm512_min_epu8(other, *this); }
17453
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
17454
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
17455
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
17456
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
17457
    simdjson_inline uint64_t operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
17458
    simdjson_inline uint64_t operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
17459
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
17460
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->lt_bits(other).any_bits_set(); }
17461
17462
    // Bit-specific operations
17463
    simdjson_inline simd8<bool> bits_not_set() const { return _mm512_mask_blend_epi8(*this == uint8_t(0), _mm512_set1_epi8(0), _mm512_set1_epi8(-1)); }
17464
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
17465
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
17466
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
17467
17468
    simdjson_inline bool is_ascii() const { return _mm512_movepi8_mask(*this) == 0; }
17469
    simdjson_inline bool bits_not_set_anywhere() const {
17470
      return !_mm512_test_epi8_mask(*this, *this);
17471
    }
17472
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
17473
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return !_mm512_test_epi8_mask(*this, bits); }
17474
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
17475
    template<int N>
17476
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm512_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
17477
    template<int N>
17478
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm512_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
17479
    // Get one of the bits and make a bitmask out of it.
17480
    // e.g. value.get_bit<7>() gets the high bit
17481
    template<int N>
17482
    simdjson_inline uint64_t get_bit() const { return _mm512_movepi8_mask(_mm512_slli_epi16(*this, 7-N)); }
17483
  };
17484
17485
  template<typename T>
17486
  struct simd8x64 {
17487
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
17488
    static_assert(NUM_CHUNKS == 1, "Icelake kernel should use one register per 64-byte block.");
17489
    const simd8<T> chunks[NUM_CHUNKS];
17490
17491
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
17492
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
17493
    simd8x64() = delete; // no default constructor allowed
17494
17495
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1) : chunks{chunk0, chunk1} {}
17496
    simdjson_inline simd8x64(const simd8<T> chunk0) : chunks{chunk0} {}
17497
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr)} {}
17498
17499
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
17500
      this->chunks[0].compress(mask, output);
17501
      return 64 - count_ones(mask);
17502
    }
17503
17504
    simdjson_inline void store(T ptr[64]) const {
17505
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
17506
    }
17507
17508
    simdjson_inline simd8<T> reduce_or() const {
17509
      return this->chunks[0];
17510
    }
17511
17512
    simdjson_inline simd8x64<T> bit_or(const T m) const {
17513
      const simd8<T> mask = simd8<T>::splat(m);
17514
      return simd8x64<T>(
17515
        this->chunks[0] | mask
17516
      );
17517
    }
17518
17519
    simdjson_inline uint64_t eq(const T m) const {
17520
      const simd8<T> mask = simd8<T>::splat(m);
17521
      return this->chunks[0] == mask;
17522
    }
17523
17524
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
17525
      return this->chunks[0] == other.chunks[0];
17526
    }
17527
17528
    simdjson_inline uint64_t lteq(const T m) const {
17529
      const simd8<T> mask = simd8<T>::splat(m);
17530
      return this->chunks[0] <= mask;
17531
    }
17532
  }; // struct simd8x64<T>
17533
17534
} // namespace simd
17535
17536
} // unnamed namespace
17537
} // namespace icelake
17538
} // namespace simdjson
17539
17540
#endif // SIMDJSON_ICELAKE_SIMD_H
17541
/* end file simdjson/icelake/simd.h */
17542
/* including simdjson/icelake/stringparsing_defs.h: #include "simdjson/icelake/stringparsing_defs.h" */
17543
/* begin file simdjson/icelake/stringparsing_defs.h */
17544
#ifndef SIMDJSON_ICELAKE_STRINGPARSING_DEFS_H
17545
#define SIMDJSON_ICELAKE_STRINGPARSING_DEFS_H
17546
17547
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17548
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
17549
/* amalgamation skipped (editor-only): #include "simdjson/icelake/simd.h" */
17550
/* amalgamation skipped (editor-only): #include "simdjson/icelake/bitmanipulation.h" */
17551
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17552
17553
namespace simdjson {
17554
namespace icelake {
17555
namespace {
17556
17557
using namespace simd;
17558
17559
// Holds backslashes and quotes locations.
17560
struct backslash_and_quote {
17561
public:
17562
  static constexpr uint32_t BYTES_PROCESSED = 64;
17563
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
17564
17565
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
17566
  simdjson_inline bool has_backslash() { return ((quote_bits - 1) & bs_bits) != 0; }
17567
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
17568
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
17569
17570
  uint64_t bs_bits;
17571
  uint64_t quote_bits;
17572
}; // struct backslash_and_quote
17573
17574
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
17575
  // this can read up to 15 bytes beyond the buffer size, but we require
17576
  // SIMDJSON_PADDING of padding
17577
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
17578
  simd8<uint8_t> v(src);
17579
  // store to dest unconditionally - we can overwrite the bits we don't like later
17580
  v.store(dst);
17581
  return {
17582
      static_cast<uint64_t>(v == '\\'), // bs_bits
17583
      static_cast<uint64_t>(v == '"'), // quote_bits
17584
  };
17585
}
17586
17587
} // unnamed namespace
17588
} // namespace icelake
17589
} // namespace simdjson
17590
17591
#endif // SIMDJSON_ICELAKE_STRINGPARSING_DEFS_H
17592
/* end file simdjson/icelake/stringparsing_defs.h */
17593
/* including simdjson/icelake/numberparsing_defs.h: #include "simdjson/icelake/numberparsing_defs.h" */
17594
/* begin file simdjson/icelake/numberparsing_defs.h */
17595
#ifndef SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H
17596
#define SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H
17597
17598
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17599
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
17600
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
17601
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
17602
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17603
17604
namespace simdjson {
17605
namespace icelake {
17606
namespace numberparsing {
17607
17608
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
17609
  // this actually computes *16* values so we are being wasteful.
17610
  const __m128i ascii0 = _mm_set1_epi8('0');
17611
  const __m128i mul_1_10 =
17612
      _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1);
17613
  const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1);
17614
  const __m128i mul_1_10000 =
17615
      _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1);
17616
  const __m128i input = _mm_sub_epi8(
17617
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0);
17618
  const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10);
17619
  const __m128i t2 = _mm_madd_epi16(t1, mul_1_100);
17620
  const __m128i t3 = _mm_packus_epi32(t2, t2);
17621
  const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000);
17622
  return _mm_cvtsi128_si32(
17623
      t4); // only captures the sum of the first 8 digits, drop the rest
17624
}
17625
17626
/** @private */
17627
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
17628
  internal::value128 answer;
17629
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
17630
#ifdef _M_ARM64
17631
  // ARM64 has native support for 64-bit multiplications, no need to emultate
17632
  answer.high = __umulh(value1, value2);
17633
  answer.low = value1 * value2;
17634
#else
17635
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
17636
#endif // _M_ARM64
17637
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
17638
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
17639
  answer.low = uint64_t(r);
17640
  answer.high = uint64_t(r >> 64);
17641
#endif
17642
  return answer;
17643
}
17644
17645
} // namespace numberparsing
17646
} // namespace icelake
17647
} // namespace simdjson
17648
17649
#define SIMDJSON_SWAR_NUMBER_PARSING 1
17650
17651
#endif // SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H
17652
/* end file simdjson/icelake/numberparsing_defs.h */
17653
/* end file simdjson/icelake/begin.h */
17654
/* including simdjson/generic/amalgamated.h for icelake: #include "simdjson/generic/amalgamated.h" */
17655
/* begin file simdjson/generic/amalgamated.h for icelake */
17656
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
17657
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
17658
#endif
17659
17660
/* including simdjson/generic/base.h for icelake: #include "simdjson/generic/base.h" */
17661
/* begin file simdjson/generic/base.h for icelake */
17662
#ifndef SIMDJSON_GENERIC_BASE_H
17663
17664
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17665
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_BASE_H */
17666
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
17667
/* amalgamation skipped (editor-only): // If we haven't got an implementation yet, we're in the editor, editing a generic file! Just */
17668
/* amalgamation skipped (editor-only): // use the most advanced one we can so the most possible stuff can be tested. */
17669
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_IMPLEMENTATION */
17670
/* amalgamation skipped (editor-only): #include "simdjson/implementation_detection.h" */
17671
/* amalgamation skipped (editor-only): #if SIMDJSON_IMPLEMENTATION_ICELAKE */
17672
/* amalgamation skipped (editor-only): #include "simdjson/icelake/begin.h" */
17673
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_HASWELL */
17674
/* amalgamation skipped (editor-only): #include "simdjson/haswell/begin.h" */
17675
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_WESTMERE */
17676
/* amalgamation skipped (editor-only): #include "simdjson/westmere/begin.h" */
17677
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_ARM64 */
17678
/* amalgamation skipped (editor-only): #include "simdjson/arm64/begin.h" */
17679
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_PPC64 */
17680
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/begin.h" */
17681
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_FALLBACK */
17682
/* amalgamation skipped (editor-only): #include "simdjson/fallback/begin.h" */
17683
/* amalgamation skipped (editor-only): #else */
17684
/* amalgamation skipped (editor-only): #error "All possible implementations (including fallback) have been disabled! simdjson will not run." */
17685
/* amalgamation skipped (editor-only): #endif */
17686
/* amalgamation skipped (editor-only): #endif // SIMDJSON_IMPLEMENTATION */
17687
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17688
17689
namespace simdjson {
17690
namespace icelake {
17691
17692
struct open_container;
17693
class dom_parser_implementation;
17694
17695
/**
17696
 * The type of a JSON number
17697
 */
17698
enum class number_type {
17699
    floating_point_number=1, /// a binary64 number
17700
    signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
17701
    unsigned_integer,        /// a positive integer larger or equal to 1<<63
17702
    big_integer              /// a big integer that does not fit in a 64-bit word
17703
};
17704
17705
} // namespace icelake
17706
} // namespace simdjson
17707
17708
#endif // SIMDJSON_GENERIC_BASE_H
17709
/* end file simdjson/generic/base.h for icelake */
17710
/* including simdjson/generic/jsoncharutils.h for icelake: #include "simdjson/generic/jsoncharutils.h" */
17711
/* begin file simdjson/generic/jsoncharutils.h for icelake */
17712
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
17713
17714
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17715
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_JSONCHARUTILS_H */
17716
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
17717
/* amalgamation skipped (editor-only): #include "simdjson/internal/jsoncharutils_tables.h" */
17718
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
17719
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17720
17721
namespace simdjson {
17722
namespace icelake {
17723
namespace {
17724
namespace jsoncharutils {
17725
17726
// return non-zero if not a structural or whitespace char
17727
// zero otherwise
17728
simdjson_inline uint32_t is_not_structural_or_whitespace(uint8_t c) {
17729
  return internal::structural_or_whitespace_negated[c];
17730
}
17731
17732
simdjson_inline uint32_t is_structural_or_whitespace(uint8_t c) {
17733
  return internal::structural_or_whitespace[c];
17734
}
17735
17736
// returns a value with the high 16 bits set if not valid
17737
// otherwise returns the conversion of the 4 hex digits at src into the bottom
17738
// 16 bits of the 32-bit return register
17739
//
17740
// see
17741
// https://lemire.me/blog/2019/04/17/parsing-short-hexadecimal-strings-efficiently/
17742
static inline uint32_t hex_to_u32_nocheck(
17743
    const uint8_t *src) { // strictly speaking, static inline is a C-ism
17744
  uint32_t v1 = internal::digit_to_val32[630 + src[0]];
17745
  uint32_t v2 = internal::digit_to_val32[420 + src[1]];
17746
  uint32_t v3 = internal::digit_to_val32[210 + src[2]];
17747
  uint32_t v4 = internal::digit_to_val32[0 + src[3]];
17748
  return v1 | v2 | v3 | v4;
17749
}
17750
17751
// given a code point cp, writes to c
17752
// the utf-8 code, outputting the length in
17753
// bytes, if the length is zero, the code point
17754
// is invalid
17755
//
17756
// This can possibly be made faster using pdep
17757
// and clz and table lookups, but JSON documents
17758
// have few escaped code points, and the following
17759
// function looks cheap.
17760
//
17761
// Note: we assume that surrogates are treated separately
17762
//
17763
simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
17764
  if (cp <= 0x7F) {
17765
    c[0] = uint8_t(cp);
17766
    return 1; // ascii
17767
  }
17768
  if (cp <= 0x7FF) {
17769
    c[0] = uint8_t((cp >> 6) + 192);
17770
    c[1] = uint8_t((cp & 63) + 128);
17771
    return 2; // universal plane
17772
    //  Surrogates are treated elsewhere...
17773
    //} //else if (0xd800 <= cp && cp <= 0xdfff) {
17774
    //  return 0; // surrogates // could put assert here
17775
  } else if (cp <= 0xFFFF) {
17776
    c[0] = uint8_t((cp >> 12) + 224);
17777
    c[1] = uint8_t(((cp >> 6) & 63) + 128);
17778
    c[2] = uint8_t((cp & 63) + 128);
17779
    return 3;
17780
  } else if (cp <= 0x10FFFF) { // if you know you have a valid code point, this
17781
                               // is not needed
17782
    c[0] = uint8_t((cp >> 18) + 240);
17783
    c[1] = uint8_t(((cp >> 12) & 63) + 128);
17784
    c[2] = uint8_t(((cp >> 6) & 63) + 128);
17785
    c[3] = uint8_t((cp & 63) + 128);
17786
    return 4;
17787
  }
17788
  // will return 0 when the code point was too large.
17789
  return 0; // bad r
17790
}
17791
17792
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
17793
// this is a slow emulation routine for 32-bit
17794
//
17795
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
17796
  return x * (uint64_t)y;
17797
}
17798
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
17799
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
17800
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
17801
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
17802
  uint64_t adbc_carry = !!(adbc < ad);
17803
  uint64_t lo = bd + (adbc << 32);
17804
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
17805
        (adbc_carry << 32) + !!(lo < bd);
17806
  return lo;
17807
}
17808
#endif
17809
17810
} // namespace jsoncharutils
17811
} // unnamed namespace
17812
} // namespace icelake
17813
} // namespace simdjson
17814
17815
#endif // SIMDJSON_GENERIC_JSONCHARUTILS_H
17816
/* end file simdjson/generic/jsoncharutils.h for icelake */
17817
/* including simdjson/generic/atomparsing.h for icelake: #include "simdjson/generic/atomparsing.h" */
17818
/* begin file simdjson/generic/atomparsing.h for icelake */
17819
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
17820
17821
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17822
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ATOMPARSING_H */
17823
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
17824
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
17825
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17826
17827
#include <cstring>
17828
17829
namespace simdjson {
17830
namespace icelake {
17831
namespace {
17832
/// @private
17833
namespace atomparsing {
17834
17835
// The string_to_uint32 is exclusively used to map literal strings to 32-bit values.
17836
// We use memcpy instead of a pointer cast to avoid undefined behaviors since we cannot
17837
// be certain that the character pointer will be properly aligned.
17838
// You might think that using memcpy makes this function expensive, but you'd be wrong.
17839
// All decent optimizing compilers (GCC, clang, Visual Studio) will compile string_to_uint32("false");
17840
// to the compile-time constant 1936482662.
17841
simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(&val, str, sizeof(uint32_t)); return val; }
17842
17843
17844
// Again in str4ncmp we use a memcpy to avoid undefined behavior. The memcpy may appear expensive.
17845
// Yet all decent optimizing compilers will compile memcpy to a single instruction, just about.
17846
simdjson_warn_unused
17847
simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) {
17848
  uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++)
17849
  static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes");
17850
  std::memcpy(&srcval, src, sizeof(uint32_t));
17851
  return srcval ^ string_to_uint32(atom);
17852
}
17853
17854
simdjson_warn_unused
17855
simdjson_inline bool is_valid_true_atom(const uint8_t *src) {
17856
  return (str4ncmp(src, "true") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
17857
}
17858
17859
simdjson_warn_unused
17860
simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) {
17861
  if (len > 4) { return is_valid_true_atom(src); }
17862
  else if (len == 4) { return !str4ncmp(src, "true"); }
17863
  else { return false; }
17864
}
17865
17866
simdjson_warn_unused
17867
simdjson_inline bool is_valid_false_atom(const uint8_t *src) {
17868
  return (str4ncmp(src+1, "alse") | jsoncharutils::is_not_structural_or_whitespace(src[5])) == 0;
17869
}
17870
17871
simdjson_warn_unused
17872
simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) {
17873
  if (len > 5) { return is_valid_false_atom(src); }
17874
  else if (len == 5) { return !str4ncmp(src+1, "alse"); }
17875
  else { return false; }
17876
}
17877
17878
simdjson_warn_unused
17879
simdjson_inline bool is_valid_null_atom(const uint8_t *src) {
17880
  return (str4ncmp(src, "null") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
17881
}
17882
17883
simdjson_warn_unused
17884
simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
17885
  if (len > 4) { return is_valid_null_atom(src); }
17886
  else if (len == 4) { return !str4ncmp(src, "null"); }
17887
  else { return false; }
17888
}
17889
17890
} // namespace atomparsing
17891
} // unnamed namespace
17892
} // namespace icelake
17893
} // namespace simdjson
17894
17895
#endif // SIMDJSON_GENERIC_ATOMPARSING_H
17896
/* end file simdjson/generic/atomparsing.h for icelake */
17897
/* including simdjson/generic/dom_parser_implementation.h for icelake: #include "simdjson/generic/dom_parser_implementation.h" */
17898
/* begin file simdjson/generic/dom_parser_implementation.h for icelake */
17899
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
17900
17901
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17902
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H */
17903
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
17904
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
17905
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17906
17907
namespace simdjson {
17908
namespace icelake {
17909
17910
// expectation: sizeof(open_container) = 64/8.
17911
struct open_container {
17912
  uint32_t tape_index; // where, on the tape, does the scope ([,{) begins
17913
  uint32_t count; // how many elements in the scope
17914
}; // struct open_container
17915
17916
static_assert(sizeof(open_container) == 64/8, "Open container must be 64 bits");
17917
17918
class dom_parser_implementation final : public internal::dom_parser_implementation {
17919
public:
17920
  /** Tape location of each open { or [ */
17921
  std::unique_ptr<open_container[]> open_containers{};
17922
  /** Whether each open container is a [ or { */
17923
  std::unique_ptr<bool[]> is_array{};
17924
  /** Buffer passed to stage 1 */
17925
  const uint8_t *buf{};
17926
  /** Length passed to stage 1 */
17927
  size_t len{0};
17928
  /** Document passed to stage 2 */
17929
  dom::document *doc{};
17930
17931
  inline dom_parser_implementation() noexcept;
17932
  inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
17933
  inline dom_parser_implementation &operator=(dom_parser_implementation &&other) noexcept;
17934
  dom_parser_implementation(const dom_parser_implementation &) = delete;
17935
  dom_parser_implementation &operator=(const dom_parser_implementation &) = delete;
17936
17937
  simdjson_warn_unused error_code parse(const uint8_t *buf, size_t len, dom::document &doc) noexcept final;
17938
  simdjson_warn_unused error_code stage1(const uint8_t *buf, size_t len, stage1_mode partial) noexcept final;
17939
  simdjson_warn_unused error_code stage2(dom::document &doc) noexcept final;
17940
  simdjson_warn_unused error_code stage2_next(dom::document &doc) noexcept final;
17941
  simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept final;
17942
  simdjson_warn_unused uint8_t *parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept final;
17943
  inline simdjson_warn_unused error_code set_capacity(size_t capacity) noexcept final;
17944
  inline simdjson_warn_unused error_code set_max_depth(size_t max_depth) noexcept final;
17945
private:
17946
  simdjson_inline simdjson_warn_unused error_code set_capacity_stage1(size_t capacity);
17947
17948
};
17949
17950
} // namespace icelake
17951
} // namespace simdjson
17952
17953
namespace simdjson {
17954
namespace icelake {
17955
17956
inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
17957
inline dom_parser_implementation::dom_parser_implementation(dom_parser_implementation &&other) noexcept = default;
17958
inline dom_parser_implementation &dom_parser_implementation::operator=(dom_parser_implementation &&other) noexcept = default;
17959
17960
// Leaving these here so they can be inlined if so desired
17961
inline simdjson_warn_unused error_code dom_parser_implementation::set_capacity(size_t capacity) noexcept {
17962
  if(capacity > SIMDJSON_MAXSIZE_BYTES) { return CAPACITY; }
17963
  // Stage 1 index output
17964
  size_t max_structures = SIMDJSON_ROUNDUP_N(capacity, 64) + 2 + 7;
17965
  structural_indexes.reset( new (std::nothrow) uint32_t[max_structures] );
17966
  if (!structural_indexes) { _capacity = 0; return MEMALLOC; }
17967
  structural_indexes[0] = 0;
17968
  n_structural_indexes = 0;
17969
17970
  _capacity = capacity;
17971
  return SUCCESS;
17972
}
17973
17974
inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(size_t max_depth) noexcept {
17975
  // Stage 2 stacks
17976
  open_containers.reset(new (std::nothrow) open_container[max_depth]);
17977
  is_array.reset(new (std::nothrow) bool[max_depth]);
17978
  if (!is_array || !open_containers) { _max_depth = 0; return MEMALLOC; }
17979
17980
  _max_depth = max_depth;
17981
  return SUCCESS;
17982
}
17983
17984
} // namespace icelake
17985
} // namespace simdjson
17986
17987
#endif // SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
17988
/* end file simdjson/generic/dom_parser_implementation.h for icelake */
17989
/* including simdjson/generic/implementation_simdjson_result_base.h for icelake: #include "simdjson/generic/implementation_simdjson_result_base.h" */
17990
/* begin file simdjson/generic/implementation_simdjson_result_base.h for icelake */
17991
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
17992
17993
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
17994
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H */
17995
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
17996
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
17997
17998
namespace simdjson {
17999
namespace icelake {
18000
18001
// This is a near copy of include/error.h's implementation_simdjson_result_base, except it doesn't use std::pair
18002
// so we can avoid inlining errors
18003
// TODO reconcile these!
18004
/**
18005
 * The result of a simdjson operation that could fail.
18006
 *
18007
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
18008
 *
18009
 * This is a base class for implementations that want to add functions to the result type for
18010
 * chaining.
18011
 *
18012
 * Override like:
18013
 *
18014
 *   struct simdjson_result<T> : public internal::implementation_simdjson_result_base<T> {
18015
 *     simdjson_result() noexcept : internal::implementation_simdjson_result_base<T>() {}
18016
 *     simdjson_result(error_code error) noexcept : internal::implementation_simdjson_result_base<T>(error) {}
18017
 *     simdjson_result(T &&value) noexcept : internal::implementation_simdjson_result_base<T>(std::forward(value)) {}
18018
 *     simdjson_result(T &&value, error_code error) noexcept : internal::implementation_simdjson_result_base<T>(value, error) {}
18019
 *     // Your extra methods here
18020
 *   }
18021
 *
18022
 * Then any method returning simdjson_result<T> will be chainable with your methods.
18023
 */
18024
template<typename T>
18025
struct implementation_simdjson_result_base {
18026
18027
  /**
18028
   * Create a new empty result with error = UNINITIALIZED.
18029
   */
18030
  simdjson_inline implementation_simdjson_result_base() noexcept = default;
18031
18032
  /**
18033
   * Create a new error result.
18034
   */
18035
  simdjson_inline implementation_simdjson_result_base(error_code error) noexcept;
18036
18037
  /**
18038
   * Create a new successful result.
18039
   */
18040
  simdjson_inline implementation_simdjson_result_base(T &&value) noexcept;
18041
18042
  /**
18043
   * Create a new result with both things (use if you don't want to branch when creating the result).
18044
   */
18045
  simdjson_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
18046
18047
  /**
18048
   * Move the value and the error to the provided variables.
18049
   *
18050
   * @param value The variable to assign the value to. May not be set if there is an error.
18051
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
18052
   */
18053
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
18054
18055
  /**
18056
   * Move the value to the provided variable.
18057
   *
18058
   * @param value The variable to assign the value to. May not be set if there is an error.
18059
   */
18060
  simdjson_inline error_code get(T &value) && noexcept;
18061
18062
  /**
18063
   * The error.
18064
   */
18065
  simdjson_inline error_code error() const noexcept;
18066
18067
#if SIMDJSON_EXCEPTIONS
18068
18069
  /**
18070
   * Get the result value.
18071
   *
18072
   * @throw simdjson_error if there was an error.
18073
   */
18074
  simdjson_inline T& value() & noexcept(false);
18075
18076
  /**
18077
   * Take the result value (move it).
18078
   *
18079
   * @throw simdjson_error if there was an error.
18080
   */
18081
  simdjson_inline T&& value() && noexcept(false);
18082
18083
  /**
18084
   * Take the result value (move it).
18085
   *
18086
   * @throw simdjson_error if there was an error.
18087
   */
18088
  simdjson_inline T&& take_value() && noexcept(false);
18089
18090
  /**
18091
   * Cast to the value (will throw on error).
18092
   *
18093
   * @throw simdjson_error if there was an error.
18094
   */
18095
  simdjson_inline operator T&&() && noexcept(false);
18096
18097
18098
#endif // SIMDJSON_EXCEPTIONS
18099
18100
  /**
18101
   * Get the result value. This function is safe if and only
18102
   * the error() method returns a value that evaluates to false.
18103
   */
18104
  simdjson_inline const T& value_unsafe() const& noexcept;
18105
  /**
18106
   * Get the result value. This function is safe if and only
18107
   * the error() method returns a value that evaluates to false.
18108
   */
18109
  simdjson_inline T& value_unsafe() & noexcept;
18110
  /**
18111
   * Take the result value (move it). This function is safe if and only
18112
   * the error() method returns a value that evaluates to false.
18113
   */
18114
  simdjson_inline T&& value_unsafe() && noexcept;
18115
protected:
18116
  /** users should never directly access first and second. **/
18117
  T first{}; /** Users should never directly access 'first'. **/
18118
  error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
18119
}; // struct implementation_simdjson_result_base
18120
18121
} // namespace icelake
18122
} // namespace simdjson
18123
18124
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
18125
/* end file simdjson/generic/implementation_simdjson_result_base.h for icelake */
18126
/* including simdjson/generic/numberparsing.h for icelake: #include "simdjson/generic/numberparsing.h" */
18127
/* begin file simdjson/generic/numberparsing.h for icelake */
18128
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
18129
18130
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
18131
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_NUMBERPARSING_H */
18132
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
18133
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
18134
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
18135
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
18136
18137
#include <limits>
18138
#include <ostream>
18139
#include <cstring>
18140
18141
namespace simdjson {
18142
namespace icelake {
18143
namespace numberparsing {
18144
18145
#ifdef JSON_TEST_NUMBERS
18146
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
18147
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
18148
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
18149
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
18150
#define BIGINT_NUMBER(SRC) (found_invalid_number((SRC)), BIGINT_ERROR)
18151
#else
18152
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
18153
#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
18154
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
18155
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
18156
#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
18157
#endif
18158
18159
namespace {
18160
18161
// Convert a mantissa, an exponent and a sign bit into an ieee64 double.
18162
// The real_exponent needs to be in [0, 2046] (technically real_exponent = 2047 would be acceptable).
18163
// The mantissa should be in [0,1<<53). The bit at index (1ULL << 52) while be zeroed.
18164
simdjson_inline double to_double(uint64_t mantissa, uint64_t real_exponent, bool negative) {
18165
    double d;
18166
    mantissa &= ~(1ULL << 52);
18167
    mantissa |= real_exponent << 52;
18168
    mantissa |= ((static_cast<uint64_t>(negative)) << 63);
18169
    std::memcpy(&d, &mantissa, sizeof(d));
18170
    return d;
18171
}
18172
18173
// Attempts to compute i * 10^(power) exactly; and if "negative" is
18174
// true, negate the result.
18175
// This function will only work in some cases, when it does not work, success is
18176
// set to false. This should work *most of the time* (like 99% of the time).
18177
// We assume that power is in the [smallest_power,
18178
// largest_power] interval: the caller is responsible for this check.
18179
simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, double &d) {
18180
  // we start with a fast path
18181
  // It was described in
18182
  // Clinger WD. How to read floating point numbers accurately.
18183
  // ACM SIGPLAN Notices. 1990
18184
#ifndef FLT_EVAL_METHOD
18185
#error "FLT_EVAL_METHOD should be defined, please include cfloat."
18186
#endif
18187
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
18188
  // We cannot be certain that x/y is rounded to nearest.
18189
  if (0 <= power && power <= 22 && i <= 9007199254740991)
18190
#else
18191
  if (-22 <= power && power <= 22 && i <= 9007199254740991)
18192
#endif
18193
  {
18194
    // convert the integer into a double. This is lossless since
18195
    // 0 <= i <= 2^53 - 1.
18196
    d = double(i);
18197
    //
18198
    // The general idea is as follows.
18199
    // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
18200
    // 1) Both s and p can be represented exactly as 64-bit floating-point
18201
    // values
18202
    // (binary64).
18203
    // 2) Because s and p can be represented exactly as floating-point values,
18204
    // then s * p
18205
    // and s / p will produce correctly rounded values.
18206
    //
18207
    if (power < 0) {
18208
      d = d / simdjson::internal::power_of_ten[-power];
18209
    } else {
18210
      d = d * simdjson::internal::power_of_ten[power];
18211
    }
18212
    if (negative) {
18213
      d = -d;
18214
    }
18215
    return true;
18216
  }
18217
  // When 22 < power && power <  22 + 16, we could
18218
  // hope for another, secondary fast path.  It was
18219
  // described by David M. Gay in  "Correctly rounded
18220
  // binary-decimal and decimal-binary conversions." (1990)
18221
  // If you need to compute i * 10^(22 + x) for x < 16,
18222
  // first compute i * 10^x, if you know that result is exact
18223
  // (e.g., when i * 10^x < 2^53),
18224
  // then you can still proceed and do (i * 10^x) * 10^22.
18225
  // Is this worth your time?
18226
  // You need  22 < power *and* power <  22 + 16 *and* (i * 10^(x-22) < 2^53)
18227
  // for this second fast path to work.
18228
  // If you you have 22 < power *and* power <  22 + 16, and then you
18229
  // optimistically compute "i * 10^(x-22)", there is still a chance that you
18230
  // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
18231
  // this optimization maybe less common than we would like. Source:
18232
  // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
18233
  // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
18234
18235
  // The fast path has now failed, so we are failing back on the slower path.
18236
18237
  // In the slow path, we need to adjust i so that it is > 1<<63 which is always
18238
  // possible, except if i == 0, so we handle i == 0 separately.
18239
  if(i == 0) {
18240
    d = negative ? -0.0 : 0.0;
18241
    return true;
18242
  }
18243
18244
18245
  // The exponent is 1024 + 63 + power
18246
  //     + floor(log(5**power)/log(2)).
18247
  // The 1024 comes from the ieee64 standard.
18248
  // The 63 comes from the fact that we use a 64-bit word.
18249
  //
18250
  // Computing floor(log(5**power)/log(2)) could be
18251
  // slow. Instead we use a fast function.
18252
  //
18253
  // For power in (-400,350), we have that
18254
  // (((152170 + 65536) * power ) >> 16);
18255
  // is equal to
18256
  //  floor(log(5**power)/log(2)) + power when power >= 0
18257
  // and it is equal to
18258
  //  ceil(log(5**-power)/log(2)) + power when power < 0
18259
  //
18260
  // The 65536 is (1<<16) and corresponds to
18261
  // (65536 * power) >> 16 ---> power
18262
  //
18263
  // ((152170 * power ) >> 16) is equal to
18264
  // floor(log(5**power)/log(2))
18265
  //
18266
  // Note that this is not magic: 152170/(1<<16) is
18267
  // approximatively equal to log(5)/log(2).
18268
  // The 1<<16 value is a power of two; we could use a
18269
  // larger power of 2 if we wanted to.
18270
  //
18271
  int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
18272
18273
18274
  // We want the most significant bit of i to be 1. Shift if needed.
18275
  int lz = leading_zeroes(i);
18276
  i <<= lz;
18277
18278
18279
  // We are going to need to do some 64-bit arithmetic to get a precise product.
18280
  // We use a table lookup approach.
18281
  // It is safe because
18282
  // power >= smallest_power
18283
  // and power <= largest_power
18284
  // We recover the mantissa of the power, it has a leading 1. It is always
18285
  // rounded down.
18286
  //
18287
  // We want the most significant 64 bits of the product. We know
18288
  // this will be non-zero because the most significant bit of i is
18289
  // 1.
18290
  const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
18291
  // Optimization: It may be that materializing the index as a variable might confuse some compilers and prevent effective complex-addressing loads. (Done for code clarity.)
18292
  //
18293
  // The full_multiplication function computes the 128-bit product of two 64-bit words
18294
  // with a returned value of type value128 with a "low component" corresponding to the
18295
  // 64-bit least significant bits of the product and with a "high component" corresponding
18296
  // to the 64-bit most significant bits of the product.
18297
  simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
18298
  // Both i and power_of_five_128[index] have their most significant bit set to 1 which
18299
  // implies that the either the most or the second most significant bit of the product
18300
  // is 1. We pack values in this manner for efficiency reasons: it maximizes the use
18301
  // we make of the product. It also makes it easy to reason about the product: there
18302
  // is 0 or 1 leading zero in the product.
18303
18304
  // Unless the least significant 9 bits of the high (64-bit) part of the full
18305
  // product are all 1s, then we know that the most significant 55 bits are
18306
  // exact and no further work is needed. Having 55 bits is necessary because
18307
  // we need 53 bits for the mantissa but we have to have one rounding bit and
18308
  // we can waste a bit if the most significant bit of the product is zero.
18309
  if((firstproduct.high & 0x1FF) == 0x1FF) {
18310
    // We want to compute i * 5^q, but only care about the top 55 bits at most.
18311
    // Consider the scenario where q>=0. Then 5^q may not fit in 64-bits. Doing
18312
    // the full computation is wasteful. So we do what is called a "truncated
18313
    // multiplication".
18314
    // We take the most significant 64-bits, and we put them in
18315
    // power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
18316
    // to the desired approximation using one multiplication. Sometimes it does not suffice.
18317
    // Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
18318
    // then we get a better approximation to i * 5^q.
18319
    //
18320
    // That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
18321
    // more complicated.
18322
    //
18323
    // There is an extra layer of complexity in that we need more than 55 bits of
18324
    // accuracy in the round-to-even scenario.
18325
    //
18326
    // The full_multiplication function computes the 128-bit product of two 64-bit words
18327
    // with a returned value of type value128 with a "low component" corresponding to the
18328
    // 64-bit least significant bits of the product and with a "high component" corresponding
18329
    // to the 64-bit most significant bits of the product.
18330
    simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
18331
    firstproduct.low += secondproduct.high;
18332
    if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
18333
    // As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
18334
    // Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
18335
    // is sufficiently accurate, and more computation is not needed.
18336
  }
18337
  uint64_t lower = firstproduct.low;
18338
  uint64_t upper = firstproduct.high;
18339
  // The final mantissa should be 53 bits with a leading 1.
18340
  // We shift it so that it occupies 54 bits with a leading 1.
18341
  ///////
18342
  uint64_t upperbit = upper >> 63;
18343
  uint64_t mantissa = upper >> (upperbit + 9);
18344
  lz += int(1 ^ upperbit);
18345
18346
  // Here we have mantissa < (1<<54).
18347
  int64_t real_exponent = exponent - lz;
18348
  if (simdjson_unlikely(real_exponent <= 0)) { // we have a subnormal?
18349
    // Here have that real_exponent <= 0 so -real_exponent >= 0
18350
    if(-real_exponent + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
18351
      d = negative ? -0.0 : 0.0;
18352
      return true;
18353
    }
18354
    // next line is safe because -real_exponent + 1 < 0
18355
    mantissa >>= -real_exponent + 1;
18356
    // Thankfully, we can't have both "round-to-even" and subnormals because
18357
    // "round-to-even" only occurs for powers close to 0.
18358
    mantissa += (mantissa & 1); // round up
18359
    mantissa >>= 1;
18360
    // There is a weird scenario where we don't have a subnormal but just.
18361
    // Suppose we start with 2.2250738585072013e-308, we end up
18362
    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
18363
    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
18364
    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
18365
    // subnormal, but we can only know this after rounding.
18366
    // So we only declare a subnormal if we are smaller than the threshold.
18367
    real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
18368
    d = to_double(mantissa, real_exponent, negative);
18369
    return true;
18370
  }
18371
  // We have to round to even. The "to even" part
18372
  // is only a problem when we are right in between two floats
18373
  // which we guard against.
18374
  // If we have lots of trailing zeros, we may fall right between two
18375
  // floating-point values.
18376
  //
18377
  // The round-to-even cases take the form of a number 2m+1 which is in (2^53,2^54]
18378
  // times a power of two. That is, it is right between a number with binary significand
18379
  // m and another number with binary significand m+1; and it must be the case
18380
  // that it cannot be represented by a float itself.
18381
  //
18382
  // We must have that w * 10 ^q == (2m+1) * 2^p for some power of two 2^p.
18383
  // Recall that 10^q = 5^q * 2^q.
18384
  // When q >= 0, we must have that (2m+1) is divible by 5^q, so 5^q <= 2^54. We have that
18385
  //  5^23 <=  2^54 and it is the last power of five to qualify, so q <= 23.
18386
  // When q<0, we have  w  >=  (2m+1) x 5^{-q}.  We must have that w<2^{64} so
18387
  // (2m+1) x 5^{-q} < 2^{64}. We have that 2m+1>2^{53}. Hence, we must have
18388
  // 2^{53} x 5^{-q} < 2^{64}.
18389
  // Hence we have 5^{-q} < 2^{11}$ or q>= -4.
18390
  //
18391
  // We require lower <= 1 and not lower == 0 because we could not prove that
18392
  // that lower == 0 is implied; but we could prove that lower <= 1 is a necessary and sufficient test.
18393
  if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
18394
    if((mantissa  << (upperbit + 64 - 53 - 2)) ==  upper) {
18395
      mantissa &= ~1;             // flip it so that we do not round up
18396
    }
18397
  }
18398
18399
  mantissa += mantissa & 1;
18400
  mantissa >>= 1;
18401
18402
  // Here we have mantissa < (1<<53), unless there was an overflow
18403
  if (mantissa >= (1ULL << 53)) {
18404
    //////////
18405
    // This will happen when parsing values such as 7.2057594037927933e+16
18406
    ////////
18407
    mantissa = (1ULL << 52);
18408
    real_exponent++;
18409
  }
18410
  mantissa &= ~(1ULL << 52);
18411
  // we have to check that real_exponent is in range, otherwise we bail out
18412
  if (simdjson_unlikely(real_exponent > 2046)) {
18413
    // We have an infinite value!!! We could actually throw an error here if we could.
18414
    return false;
18415
  }
18416
  d = to_double(mantissa, real_exponent, negative);
18417
  return true;
18418
}
18419
18420
// We call a fallback floating-point parser that might be slow. Note
18421
// it will accept JSON numbers, but the JSON spec. is more restrictive so
18422
// before you call parse_float_fallback, you need to have validated the input
18423
// string with the JSON grammar.
18424
// It will return an error (false) if the parsed number is infinite.
18425
// The string parsing itself always succeeds. We know that there is at least
18426
// one digit.
18427
static bool parse_float_fallback(const uint8_t *ptr, double *outDouble) {
18428
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr));
18429
  // We do not accept infinite values.
18430
18431
  // Detecting finite values in a portable manner is ridiculously hard, ideally
18432
  // we would want to do:
18433
  // return !std::isfinite(*outDouble);
18434
  // but that mysteriously fails under legacy/old libc++ libraries, see
18435
  // https://github.com/simdjson/simdjson/issues/1286
18436
  //
18437
  // Therefore, fall back to this solution (the extra parens are there
18438
  // to handle that max may be a macro on windows).
18439
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
18440
}
18441
18442
static bool parse_float_fallback(const uint8_t *ptr, const uint8_t *end_ptr, double *outDouble) {
18443
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr), reinterpret_cast<const char *>(end_ptr));
18444
  // We do not accept infinite values.
18445
18446
  // Detecting finite values in a portable manner is ridiculously hard, ideally
18447
  // we would want to do:
18448
  // return !std::isfinite(*outDouble);
18449
  // but that mysteriously fails under legacy/old libc++ libraries, see
18450
  // https://github.com/simdjson/simdjson/issues/1286
18451
  //
18452
  // Therefore, fall back to this solution (the extra parens are there
18453
  // to handle that max may be a macro on windows).
18454
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
18455
}
18456
18457
// check quickly whether the next 8 chars are made of digits
18458
// at a glance, it looks better than Mula's
18459
// http://0x80.pl/articles/swar-digits-validate.html
18460
simdjson_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
18461
  uint64_t val;
18462
  // this can read up to 7 bytes beyond the buffer size, but we require
18463
  // SIMDJSON_PADDING of padding
18464
  static_assert(7 <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be bigger than 7");
18465
  std::memcpy(&val, chars, 8);
18466
  // a branchy method might be faster:
18467
  // return (( val & 0xF0F0F0F0F0F0F0F0 ) == 0x3030303030303030)
18468
  //  && (( (val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0 ) ==
18469
  //  0x3030303030303030);
18470
  return (((val & 0xF0F0F0F0F0F0F0F0) |
18471
           (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
18472
          0x3333333333333333);
18473
}
18474
18475
template<typename I>
18476
SIMDJSON_NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
18477
simdjson_inline bool parse_digit(const uint8_t c, I &i) {
18478
  const uint8_t digit = static_cast<uint8_t>(c - '0');
18479
  if (digit > 9) {
18480
    return false;
18481
  }
18482
  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
18483
  i = 10 * i + digit; // might overflow, we will handle the overflow later
18484
  return true;
18485
}
18486
18487
simdjson_inline bool is_digit(const uint8_t c) {
18488
  return static_cast<uint8_t>(c - '0') <= 9;
18489
}
18490
18491
simdjson_inline error_code parse_decimal_after_separator(simdjson_unused const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
18492
  // we continue with the fiction that we have an integer. If the
18493
  // floating point number is representable as x * 10^z for some integer
18494
  // z that fits in 53 bits, then we will be able to convert back the
18495
  // the integer into a float in a lossless manner.
18496
  const uint8_t *const first_after_period = p;
18497
18498
#ifdef SIMDJSON_SWAR_NUMBER_PARSING
18499
#if SIMDJSON_SWAR_NUMBER_PARSING
18500
  // this helps if we have lots of decimals!
18501
  // this turns out to be frequent enough.
18502
  if (is_made_of_eight_digits_fast(p)) {
18503
    i = i * 100000000 + parse_eight_digits_unrolled(p);
18504
    p += 8;
18505
  }
18506
#endif // SIMDJSON_SWAR_NUMBER_PARSING
18507
#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
18508
  // Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
18509
  if (parse_digit(*p, i)) { ++p; }
18510
  while (parse_digit(*p, i)) { p++; }
18511
  exponent = first_after_period - p;
18512
  // Decimal without digits (123.) is illegal
18513
  if (exponent == 0) {
18514
    return INVALID_NUMBER(src);
18515
  }
18516
  return SUCCESS;
18517
}
18518
18519
simdjson_inline error_code parse_exponent(simdjson_unused const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
18520
  // Exp Sign: -123.456e[-]78
18521
  bool neg_exp = ('-' == *p);
18522
  if (neg_exp || '+' == *p) { p++; } // Skip + as well
18523
18524
  // Exponent: -123.456e-[78]
18525
  auto start_exp = p;
18526
  int64_t exp_number = 0;
18527
  while (parse_digit(*p, exp_number)) { ++p; }
18528
  // It is possible for parse_digit to overflow.
18529
  // In particular, it could overflow to INT64_MIN, and we cannot do - INT64_MIN.
18530
  // Thus we *must* check for possible overflow before we negate exp_number.
18531
18532
  // Performance notes: it may seem like combining the two "simdjson_unlikely checks" below into
18533
  // a single simdjson_unlikely path would be faster. The reasoning is sound, but the compiler may
18534
  // not oblige and may, in fact, generate two distinct paths in any case. It might be
18535
  // possible to do uint64_t(p - start_exp - 1) >= 18 but it could end up trading off
18536
  // instructions for a simdjson_likely branch, an unconclusive gain.
18537
18538
  // If there were no digits, it's an error.
18539
  if (simdjson_unlikely(p == start_exp)) {
18540
    return INVALID_NUMBER(src);
18541
  }
18542
  // We have a valid positive exponent in exp_number at this point, except that
18543
  // it may have overflowed.
18544
18545
  // If there were more than 18 digits, we may have overflowed the integer. We have to do
18546
  // something!!!!
18547
  if (simdjson_unlikely(p > start_exp+18)) {
18548
    // Skip leading zeroes: 1e000000000000000000001 is technically valid and does not overflow
18549
    while (*start_exp == '0') { start_exp++; }
18550
    // 19 digits could overflow int64_t and is kind of absurd anyway. We don't
18551
    // support exponents smaller than -999,999,999,999,999,999 and bigger
18552
    // than 999,999,999,999,999,999.
18553
    // We can truncate.
18554
    // Note that 999999999999999999 is assuredly too large. The maximal ieee64 value before
18555
    // infinity is ~1.8e308. The smallest subnormal is ~5e-324. So, actually, we could
18556
    // truncate at 324.
18557
    // Note that there is no reason to fail per se at this point in time.
18558
    // E.g., 0e999999999999999999999 is a fine number.
18559
    if (p > start_exp+18) { exp_number = 999999999999999999; }
18560
  }
18561
  // At this point, we know that exp_number is a sane, positive, signed integer.
18562
  // It is <= 999,999,999,999,999,999. As long as 'exponent' is in
18563
  // [-8223372036854775808, 8223372036854775808], we won't overflow. Because 'exponent'
18564
  // is bounded in magnitude by the size of the JSON input, we are fine in this universe.
18565
  // To sum it up: the next line should never overflow.
18566
  exponent += (neg_exp ? -exp_number : exp_number);
18567
  return SUCCESS;
18568
}
18569
18570
simdjson_inline bool check_if_integer(const uint8_t *const src, size_t max_length) {
18571
  const uint8_t *const srcend = src + max_length;
18572
  bool negative = (*src == '-'); // we can always read at least one character after the '-'
18573
  const uint8_t *p = src + uint8_t(negative);
18574
  if(p == srcend) { return false; }
18575
  if(*p == '0') {
18576
    ++p;
18577
    if(p == srcend) { return true; }
18578
    if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
18579
    return true;
18580
  }
18581
  while(p != srcend && is_digit(*p)) { ++p; }
18582
  if(p == srcend) { return true; }
18583
  if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
18584
  return true;
18585
}
18586
18587
simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
18588
  // It is possible that the integer had an overflow.
18589
  // We have to handle the case where we have 0.0000somenumber.
18590
  const uint8_t *start = start_digits;
18591
  while ((*start == '0') || (*start == '.')) { ++start; }
18592
  // we over-decrement by one when there is a '.'
18593
  return digit_count - size_t(start - start_digits);
18594
}
18595
18596
} // unnamed namespace
18597
18598
/** @private */
18599
static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
18600
  if (parse_float_fallback(src, answer)) {
18601
    return SUCCESS;
18602
  }
18603
  return INVALID_NUMBER(src);
18604
}
18605
18606
/** @private */
18607
template<typename W>
18608
simdjson_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
18609
  // If we frequently had to deal with long strings of digits,
18610
  // we could extend our code by using a 128-bit integer instead
18611
  // of a 64-bit integer. However, this is uncommon in practice.
18612
  //
18613
  // 9999999999999999999 < 2**64 so we can accommodate 19 digits.
18614
  // If we have a decimal separator, then digit_count - 1 is the number of digits, but we
18615
  // may not have a decimal separator!
18616
  if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
18617
    // Ok, chances are good that we had an overflow!
18618
    // this is almost never going to get called!!!
18619
    // we start anew, going slowly!!!
18620
    // This will happen in the following examples:
18621
    // 10000000000000000000000000000000000000000000e+308
18622
    // 3.1415926535897932384626433832795028841971693993751
18623
    //
18624
    // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
18625
    // reference to it, it would force it to be stored in memory, preventing the compiler from
18626
    // picking it apart and putting into registers. i.e. if we pass it as reference,
18627
    // it gets slow.
18628
    double d;
18629
    error_code error = slow_float_parsing(src, &d);
18630
    writer.append_double(d);
18631
    return error;
18632
  }
18633
  // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
18634
  // way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331
18635
  // To future reader: we'd love if someone found a better way, or at least could explain this result!
18636
  if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
18637
    //
18638
    // Important: smallest_power is such that it leads to a zero value.
18639
    // Observe that 18446744073709551615e-343 == 0, i.e. (2**64 - 1) e -343 is zero
18640
    // so something x 10^-343 goes to zero, but not so with  something x 10^-342.
18641
    static_assert(simdjson::internal::smallest_power <= -342, "smallest_power is not small enough");
18642
    //
18643
    if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
18644
      // E.g. Parse "-0.0e-999" into the same value as "-0.0". See https://en.wikipedia.org/wiki/Signed_zero
18645
      WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
18646
      return SUCCESS;
18647
    } else { // (exponent > largest_power) and (i != 0)
18648
      // We have, for sure, an infinite value and simdjson refuses to parse infinite values.
18649
      return INVALID_NUMBER(src);
18650
    }
18651
  }
18652
  double d;
18653
  if (!compute_float_64(exponent, i, negative, d)) {
18654
    // we are almost never going to get here.
18655
    if (!parse_float_fallback(src, &d)) { return INVALID_NUMBER(src); }
18656
  }
18657
  WRITE_DOUBLE(d, src, writer);
18658
  return SUCCESS;
18659
}
18660
18661
// parse the number at src
18662
// define JSON_TEST_NUMBERS for unit testing
18663
//
18664
// It is assumed that the number is followed by a structural ({,},],[) character
18665
// or a white space character. If that is not the case (e.g., when the JSON
18666
// document is made of a single number), then it is necessary to copy the
18667
// content and append a space before calling this function.
18668
//
18669
// Our objective is accurate parsing (ULP of 0) at high speed.
18670
template<typename W>
18671
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer);
18672
18673
// for performance analysis, it is sometimes  useful to skip parsing
18674
#ifdef SIMDJSON_SKIPNUMBERPARSING
18675
18676
template<typename W>
18677
simdjson_inline error_code parse_number(const uint8_t *const, W &writer) {
18678
  writer.append_s64(0);        // always write zero
18679
  return SUCCESS;              // always succeeds
18680
}
18681
18682
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
18683
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
18684
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
18685
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept { return 0; }
18686
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t * const src) noexcept { return 0; }
18687
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * const src) noexcept { return 0; }
18688
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept  { return false; }
18689
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept  { return false; }
18690
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept { return number_type::signed_integer; }
18691
#else
18692
18693
// parse the number at src
18694
// define JSON_TEST_NUMBERS for unit testing
18695
//
18696
// It is assumed that the number is followed by a structural ({,},],[) character
18697
// or a white space character. If that is not the case (e.g., when the JSON
18698
// document is made of a single number), then it is necessary to copy the
18699
// content and append a space before calling this function.
18700
//
18701
// Our objective is accurate parsing (ULP of 0) at high speed.
18702
template<typename W>
18703
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) {
18704
18705
  //
18706
  // Check for minus sign
18707
  //
18708
  bool negative = (*src == '-');
18709
  const uint8_t *p = src + uint8_t(negative);
18710
18711
  //
18712
  // Parse the integer part.
18713
  //
18714
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
18715
  const uint8_t *const start_digits = p;
18716
  uint64_t i = 0;
18717
  while (parse_digit(*p, i)) { p++; }
18718
18719
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
18720
  // Optimization note: size_t is expected to be unsigned.
18721
  size_t digit_count = size_t(p - start_digits);
18722
  if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
18723
18724
  //
18725
  // Handle floats if there is a . or e (or both)
18726
  //
18727
  int64_t exponent = 0;
18728
  bool is_float = false;
18729
  if ('.' == *p) {
18730
    is_float = true;
18731
    ++p;
18732
    SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
18733
    digit_count = int(p - start_digits); // used later to guard against overflows
18734
  }
18735
  if (('e' == *p) || ('E' == *p)) {
18736
    is_float = true;
18737
    ++p;
18738
    SIMDJSON_TRY( parse_exponent(src, p, exponent) );
18739
  }
18740
  if (is_float) {
18741
    const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
18742
    SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
18743
    if (dirty_end) { return INVALID_NUMBER(src); }
18744
    return SUCCESS;
18745
  }
18746
18747
  // The longest negative 64-bit number is 19 digits.
18748
  // The longest positive 64-bit number is 20 digits.
18749
  // We do it this way so we don't trigger this branch unless we must.
18750
  size_t longest_digit_count = negative ? 19 : 20;
18751
  if (digit_count > longest_digit_count) { return BIGINT_NUMBER(src); }
18752
  if (digit_count == longest_digit_count) {
18753
    if (negative) {
18754
      // Anything negative above INT64_MAX+1 is invalid
18755
      if (i > uint64_t(INT64_MAX)+1) { return BIGINT_NUMBER(src);  }
18756
      WRITE_INTEGER(~i+1, src, writer);
18757
      if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
18758
      return SUCCESS;
18759
    // Positive overflow check:
18760
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
18761
    //   biggest uint64_t.
18762
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
18763
    //   If we got here, it's a 20 digit number starting with the digit "1".
18764
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
18765
    //   than 1,553,255,926,290,448,384.
18766
    // - That is smaller than the smallest possible 20-digit number the user could write:
18767
    //   10,000,000,000,000,000,000.
18768
    // - Therefore, if the number is positive and lower than that, it's overflow.
18769
    // - The value we are looking at is less than or equal to INT64_MAX.
18770
    //
18771
    }  else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
18772
  }
18773
18774
  // Write unsigned if it does not fit in a signed integer.
18775
  if (i > uint64_t(INT64_MAX)) {
18776
    WRITE_UNSIGNED(i, src, writer);
18777
  } else {
18778
    WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
18779
  }
18780
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
18781
  return SUCCESS;
18782
}
18783
18784
// Inlineable functions
18785
namespace {
18786
18787
// This table can be used to characterize the final character of an integer
18788
// string. For JSON structural character and allowable white space characters,
18789
// we return SUCCESS. For 'e', '.' and 'E', we return INCORRECT_TYPE. Otherwise
18790
// we return NUMBER_ERROR.
18791
// Optimization note: we could easily reduce the size of the table by half (to 128)
18792
// at the cost of an extra branch.
18793
// Optimization note: we want the values to use at most 8 bits (not, e.g., 32 bits):
18794
static_assert(error_code(uint8_t(NUMBER_ERROR))== NUMBER_ERROR, "bad NUMBER_ERROR cast");
18795
static_assert(error_code(uint8_t(SUCCESS))== SUCCESS, "bad NUMBER_ERROR cast");
18796
static_assert(error_code(uint8_t(INCORRECT_TYPE))== INCORRECT_TYPE, "bad NUMBER_ERROR cast");
18797
18798
const uint8_t integer_string_finisher[256] = {
18799
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18800
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
18801
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
18802
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18803
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18804
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18805
    NUMBER_ERROR, NUMBER_ERROR,   SUCCESS,      NUMBER_ERROR, NUMBER_ERROR,
18806
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18807
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
18808
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18809
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18810
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
18811
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18812
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, INCORRECT_TYPE,
18813
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18814
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18815
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18816
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18817
    NUMBER_ERROR, SUCCESS,        NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
18818
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18819
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18820
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18821
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18822
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18823
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
18824
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18825
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18826
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18827
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18828
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18829
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18830
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18831
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18832
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18833
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18834
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18835
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18836
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18837
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18838
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18839
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18840
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18841
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18842
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18843
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18844
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18845
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18846
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18847
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18848
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18849
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
18850
    NUMBER_ERROR};
18851
18852
// Parse any number from 0 to 18,446,744,073,709,551,615
18853
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept {
18854
  const uint8_t *p = src;
18855
  //
18856
  // Parse the integer part.
18857
  //
18858
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
18859
  const uint8_t *const start_digits = p;
18860
  uint64_t i = 0;
18861
  while (parse_digit(*p, i)) { p++; }
18862
18863
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
18864
  // Optimization note: size_t is expected to be unsigned.
18865
  size_t digit_count = size_t(p - start_digits);
18866
  // The longest positive 64-bit number is 20 digits.
18867
  // We do it this way so we don't trigger this branch unless we must.
18868
  // Optimization note: the compiler can probably merge
18869
  // ((digit_count == 0) || (digit_count > 20))
18870
  // into a single  branch since digit_count is unsigned.
18871
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
18872
  // Here digit_count > 0.
18873
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
18874
  // We can do the following...
18875
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
18876
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
18877
  // }
18878
  // as a single table lookup:
18879
  if (integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
18880
18881
  if (digit_count == 20) {
18882
    // Positive overflow check:
18883
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
18884
    //   biggest uint64_t.
18885
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
18886
    //   If we got here, it's a 20 digit number starting with the digit "1".
18887
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
18888
    //   than 1,553,255,926,290,448,384.
18889
    // - That is smaller than the smallest possible 20-digit number the user could write:
18890
    //   10,000,000,000,000,000,000.
18891
    // - Therefore, if the number is positive and lower than that, it's overflow.
18892
    // - The value we are looking at is less than or equal to INT64_MAX.
18893
    //
18894
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
18895
  }
18896
18897
  return i;
18898
}
18899
18900
18901
// Parse any number from 0 to 18,446,744,073,709,551,615
18902
// Never read at src_end or beyond
18903
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src, const uint8_t * const src_end) noexcept {
18904
  const uint8_t *p = src;
18905
  //
18906
  // Parse the integer part.
18907
  //
18908
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
18909
  const uint8_t *const start_digits = p;
18910
  uint64_t i = 0;
18911
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
18912
18913
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
18914
  // Optimization note: size_t is expected to be unsigned.
18915
  size_t digit_count = size_t(p - start_digits);
18916
  // The longest positive 64-bit number is 20 digits.
18917
  // We do it this way so we don't trigger this branch unless we must.
18918
  // Optimization note: the compiler can probably merge
18919
  // ((digit_count == 0) || (digit_count > 20))
18920
  // into a single  branch since digit_count is unsigned.
18921
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
18922
  // Here digit_count > 0.
18923
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
18924
  // We can do the following...
18925
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
18926
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
18927
  // }
18928
  // as a single table lookup:
18929
  if ((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
18930
18931
  if (digit_count == 20) {
18932
    // Positive overflow check:
18933
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
18934
    //   biggest uint64_t.
18935
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
18936
    //   If we got here, it's a 20 digit number starting with the digit "1".
18937
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
18938
    //   than 1,553,255,926,290,448,384.
18939
    // - That is smaller than the smallest possible 20-digit number the user could write:
18940
    //   10,000,000,000,000,000,000.
18941
    // - Therefore, if the number is positive and lower than that, it's overflow.
18942
    // - The value we are looking at is less than or equal to INT64_MAX.
18943
    //
18944
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
18945
  }
18946
18947
  return i;
18948
}
18949
18950
// Parse any number from 0 to 18,446,744,073,709,551,615
18951
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept {
18952
  const uint8_t *p = src + 1;
18953
  //
18954
  // Parse the integer part.
18955
  //
18956
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
18957
  const uint8_t *const start_digits = p;
18958
  uint64_t i = 0;
18959
  while (parse_digit(*p, i)) { p++; }
18960
18961
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
18962
  // Optimization note: size_t is expected to be unsigned.
18963
  size_t digit_count = size_t(p - start_digits);
18964
  // The longest positive 64-bit number is 20 digits.
18965
  // We do it this way so we don't trigger this branch unless we must.
18966
  // Optimization note: the compiler can probably merge
18967
  // ((digit_count == 0) || (digit_count > 20))
18968
  // into a single  branch since digit_count is unsigned.
18969
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
18970
  // Here digit_count > 0.
18971
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
18972
  // We can do the following...
18973
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
18974
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
18975
  // }
18976
  // as a single table lookup:
18977
  if (*p != '"') { return NUMBER_ERROR; }
18978
18979
  if (digit_count == 20) {
18980
    // Positive overflow check:
18981
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
18982
    //   biggest uint64_t.
18983
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
18984
    //   If we got here, it's a 20 digit number starting with the digit "1".
18985
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
18986
    //   than 1,553,255,926,290,448,384.
18987
    // - That is smaller than the smallest possible 20-digit number the user could write:
18988
    //   10,000,000,000,000,000,000.
18989
    // - Therefore, if the number is positive and lower than that, it's overflow.
18990
    // - The value we are looking at is less than or equal to INT64_MAX.
18991
    //
18992
    // Note: we use src[1] and not src[0] because src[0] is the quote character in this
18993
    // instance.
18994
    if (src[1] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
18995
  }
18996
18997
  return i;
18998
}
18999
19000
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
19001
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
19002
  //
19003
  // Check for minus sign
19004
  //
19005
  bool negative = (*src == '-');
19006
  const uint8_t *p = src + uint8_t(negative);
19007
19008
  //
19009
  // Parse the integer part.
19010
  //
19011
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
19012
  const uint8_t *const start_digits = p;
19013
  uint64_t i = 0;
19014
  while (parse_digit(*p, i)) { p++; }
19015
19016
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
19017
  // Optimization note: size_t is expected to be unsigned.
19018
  size_t digit_count = size_t(p - start_digits);
19019
  // We go from
19020
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
19021
  // so we can never represent numbers that have more than 19 digits.
19022
  size_t longest_digit_count = 19;
19023
  // Optimization note: the compiler can probably merge
19024
  // ((digit_count == 0) || (digit_count > longest_digit_count))
19025
  // into a single  branch since digit_count is unsigned.
19026
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
19027
  // Here digit_count > 0.
19028
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
19029
  // We can do the following...
19030
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
19031
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
19032
  // }
19033
  // as a single table lookup:
19034
  if(integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
19035
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
19036
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
19037
  // so cheap that we might as well always make it.
19038
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
19039
  return negative ? (~i+1) : i;
19040
}
19041
19042
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
19043
// Never read at src_end or beyond
19044
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src, const uint8_t * const src_end) noexcept {
19045
  //
19046
  // Check for minus sign
19047
  //
19048
  if(src == src_end) { return NUMBER_ERROR; }
19049
  bool negative = (*src == '-');
19050
  const uint8_t *p = src + uint8_t(negative);
19051
19052
  //
19053
  // Parse the integer part.
19054
  //
19055
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
19056
  const uint8_t *const start_digits = p;
19057
  uint64_t i = 0;
19058
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
19059
19060
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
19061
  // Optimization note: size_t is expected to be unsigned.
19062
  size_t digit_count = size_t(p - start_digits);
19063
  // We go from
19064
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
19065
  // so we can never represent numbers that have more than 19 digits.
19066
  size_t longest_digit_count = 19;
19067
  // Optimization note: the compiler can probably merge
19068
  // ((digit_count == 0) || (digit_count > longest_digit_count))
19069
  // into a single  branch since digit_count is unsigned.
19070
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
19071
  // Here digit_count > 0.
19072
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
19073
  // We can do the following...
19074
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
19075
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
19076
  // }
19077
  // as a single table lookup:
19078
  if((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
19079
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
19080
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
19081
  // so cheap that we might as well always make it.
19082
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
19083
  return negative ? (~i+1) : i;
19084
}
19085
19086
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
19087
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t *src) noexcept {
19088
  //
19089
  // Check for minus sign
19090
  //
19091
  bool negative = (*(src + 1) == '-');
19092
  src += uint8_t(negative) + 1;
19093
19094
  //
19095
  // Parse the integer part.
19096
  //
19097
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
19098
  const uint8_t *const start_digits = src;
19099
  uint64_t i = 0;
19100
  while (parse_digit(*src, i)) { src++; }
19101
19102
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
19103
  // Optimization note: size_t is expected to be unsigned.
19104
  size_t digit_count = size_t(src - start_digits);
19105
  // We go from
19106
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
19107
  // so we can never represent numbers that have more than 19 digits.
19108
  size_t longest_digit_count = 19;
19109
  // Optimization note: the compiler can probably merge
19110
  // ((digit_count == 0) || (digit_count > longest_digit_count))
19111
  // into a single  branch since digit_count is unsigned.
19112
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
19113
  // Here digit_count > 0.
19114
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
19115
  // We can do the following...
19116
  // if (!jsoncharutils::is_structural_or_whitespace(*src)) {
19117
  //  return (*src == '.' || *src == 'e' || *src == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
19118
  // }
19119
  // as a single table lookup:
19120
  if(*src != '"') { return NUMBER_ERROR; }
19121
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
19122
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
19123
  // so cheap that we might as well always make it.
19124
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
19125
  return negative ? (~i+1) : i;
19126
}
19127
19128
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
19129
  //
19130
  // Check for minus sign
19131
  //
19132
  bool negative = (*src == '-');
19133
  src += uint8_t(negative);
19134
19135
  //
19136
  // Parse the integer part.
19137
  //
19138
  uint64_t i = 0;
19139
  const uint8_t *p = src;
19140
  p += parse_digit(*p, i);
19141
  bool leading_zero = (i == 0);
19142
  while (parse_digit(*p, i)) { p++; }
19143
  // no integer digits, or 0123 (zero must be solo)
19144
  if ( p == src ) { return INCORRECT_TYPE; }
19145
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
19146
19147
  //
19148
  // Parse the decimal part.
19149
  //
19150
  int64_t exponent = 0;
19151
  bool overflow;
19152
  if (simdjson_likely(*p == '.')) {
19153
    p++;
19154
    const uint8_t *start_decimal_digits = p;
19155
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
19156
    p++;
19157
    while (parse_digit(*p, i)) { p++; }
19158
    exponent = -(p - start_decimal_digits);
19159
19160
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
19161
    overflow = p-src-1 > 19;
19162
    if (simdjson_unlikely(overflow && leading_zero)) {
19163
      // Skip leading 0.00000 and see if it still overflows
19164
      const uint8_t *start_digits = src + 2;
19165
      while (*start_digits == '0') { start_digits++; }
19166
      overflow = p-start_digits > 19;
19167
    }
19168
  } else {
19169
    overflow = p-src > 19;
19170
  }
19171
19172
  //
19173
  // Parse the exponent
19174
  //
19175
  if (*p == 'e' || *p == 'E') {
19176
    p++;
19177
    bool exp_neg = *p == '-';
19178
    p += exp_neg || *p == '+';
19179
19180
    uint64_t exp = 0;
19181
    const uint8_t *start_exp_digits = p;
19182
    while (parse_digit(*p, exp)) { p++; }
19183
    // no exp digits, or 20+ exp digits
19184
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
19185
19186
    exponent += exp_neg ? 0-exp : exp;
19187
  }
19188
19189
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
19190
19191
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
19192
19193
  //
19194
  // Assemble (or slow-parse) the float
19195
  //
19196
  double d;
19197
  if (simdjson_likely(!overflow)) {
19198
    if (compute_float_64(exponent, i, negative, d)) { return d; }
19199
  }
19200
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
19201
    return NUMBER_ERROR;
19202
  }
19203
  return d;
19204
}
19205
19206
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept {
19207
  return (*src == '-');
19208
}
19209
19210
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept {
19211
  bool negative = (*src == '-');
19212
  src += uint8_t(negative);
19213
  const uint8_t *p = src;
19214
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
19215
  if ( p == src ) { return NUMBER_ERROR; }
19216
  if (jsoncharutils::is_structural_or_whitespace(*p)) { return true; }
19217
  return false;
19218
}
19219
19220
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept {
19221
  bool negative = (*src == '-');
19222
  src += uint8_t(negative);
19223
  const uint8_t *p = src;
19224
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
19225
  size_t digit_count = size_t(p - src);
19226
  if ( p == src ) { return NUMBER_ERROR; }
19227
  if (jsoncharutils::is_structural_or_whitespace(*p)) {
19228
    static const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
19229
    // We have an integer.
19230
    if(simdjson_unlikely(digit_count > 20)) {
19231
      return number_type::big_integer;
19232
    }
19233
    // If the number is negative and valid, it must be a signed integer.
19234
    if(negative) {
19235
      if (simdjson_unlikely(digit_count > 19)) return number_type::big_integer;
19236
      if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) {
19237
        return number_type::big_integer;
19238
      }
19239
      return number_type::signed_integer;
19240
    }
19241
    // Let us check if we have a big integer (>=2**64).
19242
    static const uint8_t * two_to_sixtyfour = reinterpret_cast<const uint8_t *>("18446744073709551616");
19243
    if((digit_count > 20) || (digit_count == 20 && memcmp(src, two_to_sixtyfour, 20) >= 0)) {
19244
      return number_type::big_integer;
19245
    }
19246
    // The number is positive and smaller than 18446744073709551616 (or 2**64).
19247
    // We want values larger or equal to 9223372036854775808 to be unsigned
19248
    // integers, and the other values to be signed integers.
19249
    if((digit_count == 20) || (digit_count >= 19 && memcmp(src, smaller_big_integer, 19) >= 0)) {
19250
      return number_type::unsigned_integer;
19251
    }
19252
    return number_type::signed_integer;
19253
  }
19254
  // Hopefully, we have 'e' or 'E' or '.'.
19255
  return number_type::floating_point_number;
19256
}
19257
19258
// Never read at src_end or beyond
19259
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
19260
  if(src == src_end) { return NUMBER_ERROR; }
19261
  //
19262
  // Check for minus sign
19263
  //
19264
  bool negative = (*src == '-');
19265
  src += uint8_t(negative);
19266
19267
  //
19268
  // Parse the integer part.
19269
  //
19270
  uint64_t i = 0;
19271
  const uint8_t *p = src;
19272
  if(p == src_end) { return NUMBER_ERROR; }
19273
  p += parse_digit(*p, i);
19274
  bool leading_zero = (i == 0);
19275
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
19276
  // no integer digits, or 0123 (zero must be solo)
19277
  if ( p == src ) { return INCORRECT_TYPE; }
19278
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
19279
19280
  //
19281
  // Parse the decimal part.
19282
  //
19283
  int64_t exponent = 0;
19284
  bool overflow;
19285
  if (simdjson_likely((p != src_end) && (*p == '.'))) {
19286
    p++;
19287
    const uint8_t *start_decimal_digits = p;
19288
    if ((p == src_end) || !parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
19289
    p++;
19290
    while ((p != src_end) && parse_digit(*p, i)) { p++; }
19291
    exponent = -(p - start_decimal_digits);
19292
19293
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
19294
    overflow = p-src-1 > 19;
19295
    if (simdjson_unlikely(overflow && leading_zero)) {
19296
      // Skip leading 0.00000 and see if it still overflows
19297
      const uint8_t *start_digits = src + 2;
19298
      while (*start_digits == '0') { start_digits++; }
19299
      overflow = start_digits-src > 19;
19300
    }
19301
  } else {
19302
    overflow = p-src > 19;
19303
  }
19304
19305
  //
19306
  // Parse the exponent
19307
  //
19308
  if ((p != src_end) && (*p == 'e' || *p == 'E')) {
19309
    p++;
19310
    if(p == src_end) { return NUMBER_ERROR; }
19311
    bool exp_neg = *p == '-';
19312
    p += exp_neg || *p == '+';
19313
19314
    uint64_t exp = 0;
19315
    const uint8_t *start_exp_digits = p;
19316
    while ((p != src_end) && parse_digit(*p, exp)) { p++; }
19317
    // no exp digits, or 20+ exp digits
19318
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
19319
19320
    exponent += exp_neg ? 0-exp : exp;
19321
  }
19322
19323
  if ((p != src_end) && jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
19324
19325
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
19326
19327
  //
19328
  // Assemble (or slow-parse) the float
19329
  //
19330
  double d;
19331
  if (simdjson_likely(!overflow)) {
19332
    if (compute_float_64(exponent, i, negative, d)) { return d; }
19333
  }
19334
  if (!parse_float_fallback(src - uint8_t(negative), src_end, &d)) {
19335
    return NUMBER_ERROR;
19336
  }
19337
  return d;
19338
}
19339
19340
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * src) noexcept {
19341
  //
19342
  // Check for minus sign
19343
  //
19344
  bool negative = (*(src + 1) == '-');
19345
  src += uint8_t(negative) + 1;
19346
19347
  //
19348
  // Parse the integer part.
19349
  //
19350
  uint64_t i = 0;
19351
  const uint8_t *p = src;
19352
  p += parse_digit(*p, i);
19353
  bool leading_zero = (i == 0);
19354
  while (parse_digit(*p, i)) { p++; }
19355
  // no integer digits, or 0123 (zero must be solo)
19356
  if ( p == src ) { return INCORRECT_TYPE; }
19357
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
19358
19359
  //
19360
  // Parse the decimal part.
19361
  //
19362
  int64_t exponent = 0;
19363
  bool overflow;
19364
  if (simdjson_likely(*p == '.')) {
19365
    p++;
19366
    const uint8_t *start_decimal_digits = p;
19367
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
19368
    p++;
19369
    while (parse_digit(*p, i)) { p++; }
19370
    exponent = -(p - start_decimal_digits);
19371
19372
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
19373
    overflow = p-src-1 > 19;
19374
    if (simdjson_unlikely(overflow && leading_zero)) {
19375
      // Skip leading 0.00000 and see if it still overflows
19376
      const uint8_t *start_digits = src + 2;
19377
      while (*start_digits == '0') { start_digits++; }
19378
      overflow = p-start_digits > 19;
19379
    }
19380
  } else {
19381
    overflow = p-src > 19;
19382
  }
19383
19384
  //
19385
  // Parse the exponent
19386
  //
19387
  if (*p == 'e' || *p == 'E') {
19388
    p++;
19389
    bool exp_neg = *p == '-';
19390
    p += exp_neg || *p == '+';
19391
19392
    uint64_t exp = 0;
19393
    const uint8_t *start_exp_digits = p;
19394
    while (parse_digit(*p, exp)) { p++; }
19395
    // no exp digits, or 20+ exp digits
19396
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
19397
19398
    exponent += exp_neg ? 0-exp : exp;
19399
  }
19400
19401
  if (*p != '"') { return NUMBER_ERROR; }
19402
19403
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
19404
19405
  //
19406
  // Assemble (or slow-parse) the float
19407
  //
19408
  double d;
19409
  if (simdjson_likely(!overflow)) {
19410
    if (compute_float_64(exponent, i, negative, d)) { return d; }
19411
  }
19412
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
19413
    return NUMBER_ERROR;
19414
  }
19415
  return d;
19416
}
19417
19418
} // unnamed namespace
19419
#endif // SIMDJSON_SKIPNUMBERPARSING
19420
19421
} // namespace numberparsing
19422
19423
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
19424
    switch (type) {
19425
        case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
19426
        case number_type::unsigned_integer: out << "unsigned integer in [9223372036854775808,18446744073709551616)"; break;
19427
        case number_type::floating_point_number: out << "floating-point number (binary64)"; break;
19428
        case number_type::big_integer: out << "big integer"; break;
19429
        default: SIMDJSON_UNREACHABLE();
19430
    }
19431
    return out;
19432
}
19433
19434
} // namespace icelake
19435
} // namespace simdjson
19436
19437
#endif // SIMDJSON_GENERIC_NUMBERPARSING_H
19438
/* end file simdjson/generic/numberparsing.h for icelake */
19439
19440
/* including simdjson/generic/implementation_simdjson_result_base-inl.h for icelake: #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
19441
/* begin file simdjson/generic/implementation_simdjson_result_base-inl.h for icelake */
19442
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
19443
19444
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19445
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H */
19446
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
19447
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
19448
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19449
19450
namespace simdjson {
19451
namespace icelake {
19452
19453
//
19454
// internal::implementation_simdjson_result_base<T> inline implementation
19455
//
19456
19457
template<typename T>
19458
simdjson_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
19459
  error = this->second;
19460
  if (!error) {
19461
    value = std::forward<implementation_simdjson_result_base<T>>(*this).first;
19462
  }
19463
}
19464
19465
template<typename T>
19466
simdjson_warn_unused simdjson_inline error_code implementation_simdjson_result_base<T>::get(T &value) && noexcept {
19467
  error_code error;
19468
  std::forward<implementation_simdjson_result_base<T>>(*this).tie(value, error);
19469
  return error;
19470
}
19471
19472
template<typename T>
19473
simdjson_inline error_code implementation_simdjson_result_base<T>::error() const noexcept {
19474
  return this->second;
19475
}
19476
19477
#if SIMDJSON_EXCEPTIONS
19478
19479
template<typename T>
19480
simdjson_inline T& implementation_simdjson_result_base<T>::value() & noexcept(false) {
19481
  if (error()) { throw simdjson_error(error()); }
19482
  return this->first;
19483
}
19484
19485
template<typename T>
19486
simdjson_inline T&& implementation_simdjson_result_base<T>::value() && noexcept(false) {
19487
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
19488
}
19489
19490
template<typename T>
19491
simdjson_inline T&& implementation_simdjson_result_base<T>::take_value() && noexcept(false) {
19492
  if (error()) { throw simdjson_error(error()); }
19493
  return std::forward<T>(this->first);
19494
}
19495
19496
template<typename T>
19497
simdjson_inline implementation_simdjson_result_base<T>::operator T&&() && noexcept(false) {
19498
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
19499
}
19500
19501
#endif // SIMDJSON_EXCEPTIONS
19502
19503
template<typename T>
19504
simdjson_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
19505
  return this->first;
19506
}
19507
19508
template<typename T>
19509
simdjson_inline T& implementation_simdjson_result_base<T>::value_unsafe() & noexcept {
19510
  return this->first;
19511
}
19512
19513
template<typename T>
19514
simdjson_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
19515
  return std::forward<T>(this->first);
19516
}
19517
19518
template<typename T>
19519
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
19520
    : first{std::forward<T>(value)}, second{error} {}
19521
template<typename T>
19522
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(error_code error) noexcept
19523
    : implementation_simdjson_result_base(T{}, error) {}
19524
template<typename T>
19525
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
19526
    : implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
19527
19528
} // namespace icelake
19529
} // namespace simdjson
19530
19531
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
19532
/* end file simdjson/generic/implementation_simdjson_result_base-inl.h for icelake */
19533
/* end file simdjson/generic/amalgamated.h for icelake */
19534
/* including simdjson/icelake/end.h: #include "simdjson/icelake/end.h" */
19535
/* begin file simdjson/icelake/end.h */
19536
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19537
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
19538
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19539
19540
#if !SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
19541
SIMDJSON_UNTARGET_REGION
19542
#endif
19543
19544
/* undefining SIMDJSON_IMPLEMENTATION from "icelake" */
19545
#undef SIMDJSON_IMPLEMENTATION
19546
/* end file simdjson/icelake/end.h */
19547
19548
#endif // SIMDJSON_ICELAKE_H
19549
/* end file simdjson/icelake.h */
19550
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
19551
/* including simdjson/ppc64.h: #include "simdjson/ppc64.h" */
19552
/* begin file simdjson/ppc64.h */
19553
#ifndef SIMDJSON_PPC64_H
19554
#define SIMDJSON_PPC64_H
19555
19556
/* including simdjson/ppc64/begin.h: #include "simdjson/ppc64/begin.h" */
19557
/* begin file simdjson/ppc64/begin.h */
19558
/* defining SIMDJSON_IMPLEMENTATION to "ppc64" */
19559
#define SIMDJSON_IMPLEMENTATION ppc64
19560
/* including simdjson/ppc64/base.h: #include "simdjson/ppc64/base.h" */
19561
/* begin file simdjson/ppc64/base.h */
19562
#ifndef SIMDJSON_PPC64_BASE_H
19563
#define SIMDJSON_PPC64_BASE_H
19564
19565
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19566
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
19567
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19568
19569
namespace simdjson {
19570
/**
19571
 * Implementation for ALTIVEC (PPC64).
19572
 */
19573
namespace ppc64 {
19574
19575
class implementation;
19576
19577
namespace {
19578
namespace simd {
19579
template <typename T> struct simd8;
19580
template <typename T> struct simd8x64;
19581
} // namespace simd
19582
} // unnamed namespace
19583
19584
} // namespace ppc64
19585
} // namespace simdjson
19586
19587
#endif // SIMDJSON_PPC64_BASE_H
19588
/* end file simdjson/ppc64/base.h */
19589
/* including simdjson/ppc64/intrinsics.h: #include "simdjson/ppc64/intrinsics.h" */
19590
/* begin file simdjson/ppc64/intrinsics.h */
19591
#ifndef SIMDJSON_PPC64_INTRINSICS_H
19592
#define SIMDJSON_PPC64_INTRINSICS_H
19593
19594
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19595
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
19596
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19597
19598
// This should be the correct header whether
19599
// you use visual studio or other compilers.
19600
#include <altivec.h>
19601
19602
// These are defined by altivec.h in GCC toolchain, it is safe to undef them.
19603
#ifdef bool
19604
#undef bool
19605
#endif
19606
19607
#ifdef vector
19608
#undef vector
19609
#endif
19610
19611
static_assert(sizeof(__vector unsigned char) <= simdjson::SIMDJSON_PADDING, "insufficient padding for ppc64");
19612
19613
#endif //  SIMDJSON_PPC64_INTRINSICS_H
19614
/* end file simdjson/ppc64/intrinsics.h */
19615
/* including simdjson/ppc64/bitmanipulation.h: #include "simdjson/ppc64/bitmanipulation.h" */
19616
/* begin file simdjson/ppc64/bitmanipulation.h */
19617
#ifndef SIMDJSON_PPC64_BITMANIPULATION_H
19618
#define SIMDJSON_PPC64_BITMANIPULATION_H
19619
19620
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19621
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
19622
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19623
19624
namespace simdjson {
19625
namespace ppc64 {
19626
namespace {
19627
19628
// We sometimes call trailing_zero on inputs that are zero,
19629
// but the algorithms do not end up using the returned value.
19630
// Sadly, sanitizers are not smart enough to figure it out.
19631
SIMDJSON_NO_SANITIZE_UNDEFINED
19632
// This function can be used safely even if not all bytes have been
19633
// initialized.
19634
// See issue https://github.com/simdjson/simdjson/issues/1965
19635
SIMDJSON_NO_SANITIZE_MEMORY
19636
simdjson_inline int trailing_zeroes(uint64_t input_num) {
19637
#if SIMDJSON_REGULAR_VISUAL_STUDIO
19638
  unsigned long ret;
19639
  // Search the mask data from least significant bit (LSB)
19640
  // to the most significant bit (MSB) for a set bit (1).
19641
  _BitScanForward64(&ret, input_num);
19642
  return (int)ret;
19643
#else  // SIMDJSON_REGULAR_VISUAL_STUDIO
19644
  return __builtin_ctzll(input_num);
19645
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
19646
}
19647
19648
/* result might be undefined when input_num is zero */
19649
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
19650
  return input_num & (input_num - 1);
19651
}
19652
19653
/* result might be undefined when input_num is zero */
19654
simdjson_inline int leading_zeroes(uint64_t input_num) {
19655
#if SIMDJSON_REGULAR_VISUAL_STUDIO
19656
  unsigned long leading_zero = 0;
19657
  // Search the mask data from most significant bit (MSB)
19658
  // to least significant bit (LSB) for a set bit (1).
19659
  if (_BitScanReverse64(&leading_zero, input_num))
19660
    return (int)(63 - leading_zero);
19661
  else
19662
    return 64;
19663
#else
19664
  return __builtin_clzll(input_num);
19665
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
19666
}
19667
19668
#if SIMDJSON_REGULAR_VISUAL_STUDIO
19669
simdjson_inline int count_ones(uint64_t input_num) {
19670
  // note: we do not support legacy 32-bit Windows in this kernel
19671
  return __popcnt64(input_num); // Visual Studio wants two underscores
19672
}
19673
#else
19674
simdjson_inline int count_ones(uint64_t input_num) {
19675
  return __builtin_popcountll(input_num);
19676
}
19677
#endif
19678
19679
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
19680
                                         uint64_t *result) {
19681
#if SIMDJSON_REGULAR_VISUAL_STUDIO
19682
  *result = value1 + value2;
19683
  return *result < value1;
19684
#else
19685
  return __builtin_uaddll_overflow(value1, value2,
19686
                                   reinterpret_cast<unsigned long long *>(result));
19687
#endif
19688
}
19689
19690
} // unnamed namespace
19691
} // namespace ppc64
19692
} // namespace simdjson
19693
19694
#endif // SIMDJSON_PPC64_BITMANIPULATION_H
19695
/* end file simdjson/ppc64/bitmanipulation.h */
19696
/* including simdjson/ppc64/bitmask.h: #include "simdjson/ppc64/bitmask.h" */
19697
/* begin file simdjson/ppc64/bitmask.h */
19698
#ifndef SIMDJSON_PPC64_BITMASK_H
19699
#define SIMDJSON_PPC64_BITMASK_H
19700
19701
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19702
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
19703
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19704
19705
namespace simdjson {
19706
namespace ppc64 {
19707
namespace {
19708
19709
//
19710
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is
19711
// encountered.
19712
//
19713
// For example, prefix_xor(00100100) == 00011100
19714
//
19715
simdjson_inline uint64_t prefix_xor(uint64_t bitmask) {
19716
  // You can use the version below, however gcc sometimes miscompiles
19717
  // vec_pmsum_be, it happens somewhere around between 8 and 9th version.
19718
  // The performance boost was not noticeable, falling back to a usual
19719
  // implementation.
19720
  //   __vector unsigned long long all_ones = {~0ull, ~0ull};
19721
  //   __vector unsigned long long mask = {bitmask, 0};
19722
  //   // Clang and GCC return different values for pmsum for ull so cast it to one.
19723
  //   // Generally it is not specified by ALTIVEC ISA what is returned by
19724
  //   // vec_pmsum_be.
19725
  // #if defined(__LITTLE_ENDIAN__)
19726
  //   return (uint64_t)(((__vector unsigned long long)vec_pmsum_be(all_ones, mask))[0]);
19727
  // #else
19728
  //   return (uint64_t)(((__vector unsigned long long)vec_pmsum_be(all_ones, mask))[1]);
19729
  // #endif
19730
  bitmask ^= bitmask << 1;
19731
  bitmask ^= bitmask << 2;
19732
  bitmask ^= bitmask << 4;
19733
  bitmask ^= bitmask << 8;
19734
  bitmask ^= bitmask << 16;
19735
  bitmask ^= bitmask << 32;
19736
  return bitmask;
19737
}
19738
19739
} // unnamed namespace
19740
} // namespace ppc64
19741
} // namespace simdjson
19742
19743
#endif
19744
/* end file simdjson/ppc64/bitmask.h */
19745
/* including simdjson/ppc64/numberparsing_defs.h: #include "simdjson/ppc64/numberparsing_defs.h" */
19746
/* begin file simdjson/ppc64/numberparsing_defs.h */
19747
#ifndef SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
19748
#define SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
19749
19750
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19751
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
19752
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/intrinsics.h" */
19753
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
19754
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19755
19756
#include <cstring>
19757
19758
#if defined(__linux__)
19759
#include <byteswap.h>
19760
#elif defined(__FreeBSD__)
19761
#include <sys/endian.h>
19762
#endif
19763
19764
namespace simdjson {
19765
namespace ppc64 {
19766
namespace numberparsing {
19767
19768
// we don't have appropriate instructions, so let us use a scalar function
19769
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
19770
/** @private */
19771
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
19772
  uint64_t val;
19773
  std::memcpy(&val, chars, sizeof(uint64_t));
19774
#ifdef __BIG_ENDIAN__
19775
#if defined(__linux__)
19776
  val = bswap_64(val);
19777
#elif defined(__FreeBSD__)
19778
  val = bswap64(val);
19779
#endif
19780
#endif
19781
  val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
19782
  val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
19783
  return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
19784
}
19785
19786
/** @private */
19787
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
19788
  internal::value128 answer;
19789
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
19790
#ifdef _M_ARM64
19791
  // ARM64 has native support for 64-bit multiplications, no need to emultate
19792
  answer.high = __umulh(value1, value2);
19793
  answer.low = value1 * value2;
19794
#else
19795
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
19796
#endif // _M_ARM64
19797
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
19798
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
19799
  answer.low = uint64_t(r);
19800
  answer.high = uint64_t(r >> 64);
19801
#endif
19802
  return answer;
19803
}
19804
19805
} // namespace numberparsing
19806
} // namespace ppc64
19807
} // namespace simdjson
19808
19809
#define SIMDJSON_SWAR_NUMBER_PARSING 1
19810
19811
#endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
19812
/* end file simdjson/ppc64/numberparsing_defs.h */
19813
/* including simdjson/ppc64/simd.h: #include "simdjson/ppc64/simd.h" */
19814
/* begin file simdjson/ppc64/simd.h */
19815
#ifndef SIMDJSON_PPC64_SIMD_H
19816
#define SIMDJSON_PPC64_SIMD_H
19817
19818
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
19819
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
19820
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/bitmanipulation.h" */
19821
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
19822
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
19823
19824
#include <type_traits>
19825
19826
namespace simdjson {
19827
namespace ppc64 {
19828
namespace {
19829
namespace simd {
19830
19831
using __m128i = __vector unsigned char;
19832
19833
template <typename Child> struct base {
19834
  __m128i value;
19835
19836
  // Zero constructor
19837
  simdjson_inline base() : value{__m128i()} {}
19838
19839
  // Conversion from SIMD register
19840
  simdjson_inline base(const __m128i _value) : value(_value) {}
19841
19842
  // Conversion to SIMD register
19843
  simdjson_inline operator const __m128i &() const {
19844
    return this->value;
19845
  }
19846
  simdjson_inline operator __m128i &() { return this->value; }
19847
19848
  // Bit operations
19849
  simdjson_inline Child operator|(const Child other) const {
19850
    return vec_or(this->value, (__m128i)other);
19851
  }
19852
  simdjson_inline Child operator&(const Child other) const {
19853
    return vec_and(this->value, (__m128i)other);
19854
  }
19855
  simdjson_inline Child operator^(const Child other) const {
19856
    return vec_xor(this->value, (__m128i)other);
19857
  }
19858
  simdjson_inline Child bit_andnot(const Child other) const {
19859
    return vec_andc(this->value, (__m128i)other);
19860
  }
19861
  simdjson_inline Child &operator|=(const Child other) {
19862
    auto this_cast = static_cast<Child*>(this);
19863
    *this_cast = *this_cast | other;
19864
    return *this_cast;
19865
  }
19866
  simdjson_inline Child &operator&=(const Child other) {
19867
    auto this_cast = static_cast<Child*>(this);
19868
    *this_cast = *this_cast & other;
19869
    return *this_cast;
19870
  }
19871
  simdjson_inline Child &operator^=(const Child other) {
19872
    auto this_cast = static_cast<Child*>(this);
19873
    *this_cast = *this_cast ^ other;
19874
    return *this_cast;
19875
  }
19876
};
19877
19878
template <typename T, typename Mask = simd8<bool>>
19879
struct base8 : base<simd8<T>> {
19880
  typedef uint16_t bitmask_t;
19881
  typedef uint32_t bitmask2_t;
19882
19883
  simdjson_inline base8() : base<simd8<T>>() {}
19884
  simdjson_inline base8(const __m128i _value) : base<simd8<T>>(_value) {}
19885
19886
  friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) {
19887
    return (__m128i)vec_cmpeq(lhs.value, (__m128i)rhs);
19888
  }
19889
19890
  static const int SIZE = sizeof(base<simd8<T>>::value);
19891
19892
  template <int N = 1>
19893
  simdjson_inline simd8<T> prev(simd8<T> prev_chunk) const {
19894
    __m128i chunk = this->value;
19895
#ifdef __LITTLE_ENDIAN__
19896
    chunk = (__m128i)vec_reve(this->value);
19897
    prev_chunk = (__m128i)vec_reve((__m128i)prev_chunk);
19898
#endif
19899
    chunk = (__m128i)vec_sld((__m128i)prev_chunk, (__m128i)chunk, 16 - N);
19900
#ifdef __LITTLE_ENDIAN__
19901
    chunk = (__m128i)vec_reve((__m128i)chunk);
19902
#endif
19903
    return chunk;
19904
  }
19905
};
19906
19907
// SIMD byte mask type (returned by things like eq and gt)
19908
template <> struct simd8<bool> : base8<bool> {
19909
  static simdjson_inline simd8<bool> splat(bool _value) {
19910
    return (__m128i)vec_splats((unsigned char)(-(!!_value)));
19911
  }
19912
19913
  simdjson_inline simd8<bool>() : base8<bool>() {}
19914
  simdjson_inline simd8<bool>(const __m128i _value)
19915
      : base8<bool>(_value) {}
19916
  // Splat constructor
19917
  simdjson_inline simd8<bool>(bool _value)
19918
      : base8<bool>(splat(_value)) {}
19919
19920
  simdjson_inline int to_bitmask() const {
19921
    __vector unsigned long long result;
19922
    const __m128i perm_mask = {0x78, 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40,
19923
                               0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x00};
19924
19925
    result = ((__vector unsigned long long)vec_vbpermq((__m128i)this->value,
19926
                                                       (__m128i)perm_mask));
19927
#ifdef __LITTLE_ENDIAN__
19928
    return static_cast<int>(result[1]);
19929
#else
19930
    return static_cast<int>(result[0]);
19931
#endif
19932
  }
19933
  simdjson_inline bool any() const {
19934
    return !vec_all_eq(this->value, (__m128i)vec_splats(0));
19935
  }
19936
  simdjson_inline simd8<bool> operator~() const {
19937
    return this->value ^ (__m128i)splat(true);
19938
  }
19939
};
19940
19941
template <typename T> struct base8_numeric : base8<T> {
19942
  static simdjson_inline simd8<T> splat(T value) {
19943
    (void)value;
19944
    return (__m128i)vec_splats(value);
19945
  }
19946
  static simdjson_inline simd8<T> zero() { return splat(0); }
19947
  static simdjson_inline simd8<T> load(const T values[16]) {
19948
    return (__m128i)(vec_vsx_ld(0, reinterpret_cast<const uint8_t *>(values)));
19949
  }
19950
  // Repeat 16 values as many times as necessary (usually for lookup tables)
19951
  static simdjson_inline simd8<T> repeat_16(T v0, T v1, T v2, T v3, T v4,
19952
                                                   T v5, T v6, T v7, T v8, T v9,
19953
                                                   T v10, T v11, T v12, T v13,
19954
                                                   T v14, T v15) {
19955
    return simd8<T>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
19956
                    v14, v15);
19957
  }
19958
19959
  simdjson_inline base8_numeric() : base8<T>() {}
19960
  simdjson_inline base8_numeric(const __m128i _value)
19961
      : base8<T>(_value) {}
19962
19963
  // Store to array
19964
  simdjson_inline void store(T dst[16]) const {
19965
    vec_vsx_st(this->value, 0, reinterpret_cast<__m128i *>(dst));
19966
  }
19967
19968
  // Override to distinguish from bool version
19969
  simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
19970
19971
  // Addition/subtraction are the same for signed and unsigned
19972
  simdjson_inline simd8<T> operator+(const simd8<T> other) const {
19973
    return (__m128i)((__m128i)this->value + (__m128i)other);
19974
  }
19975
  simdjson_inline simd8<T> operator-(const simd8<T> other) const {
19976
    return (__m128i)((__m128i)this->value - (__m128i)other);
19977
  }
19978
  simdjson_inline simd8<T> &operator+=(const simd8<T> other) {
19979
    *this = *this + other;
19980
    return *static_cast<simd8<T> *>(this);
19981
  }
19982
  simdjson_inline simd8<T> &operator-=(const simd8<T> other) {
19983
    *this = *this - other;
19984
    return *static_cast<simd8<T> *>(this);
19985
  }
19986
19987
  // Perform a lookup assuming the value is between 0 and 16 (undefined behavior
19988
  // for out of range values)
19989
  template <typename L>
19990
  simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
19991
    return (__m128i)vec_perm((__m128i)lookup_table, (__m128i)lookup_table, this->value);
19992
  }
19993
19994
  // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted
19995
  // as a bitset). Passing a 0 value for mask would be equivalent to writing out
19996
  // every byte to output. Only the first 16 - count_ones(mask) bytes of the
19997
  // result are significant but 16 bytes get written. Design consideration: it
19998
  // seems like a function with the signature simd8<L> compress(uint32_t mask)
19999
  // would be sensible, but the AVX ISA makes this kind of approach difficult.
20000
  template <typename L>
20001
  simdjson_inline void compress(uint16_t mask, L *output) const {
20002
    using internal::BitsSetTable256mul2;
20003
    using internal::pshufb_combine_table;
20004
    using internal::thintable_epi8;
20005
    // this particular implementation was inspired by work done by @animetosho
20006
    // we do it in two steps, first 8 bytes and then second 8 bytes
20007
    uint8_t mask1 = uint8_t(mask);      // least significant 8 bits
20008
    uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
20009
    // next line just loads the 64-bit values thintable_epi8[mask1] and
20010
    // thintable_epi8[mask2] into a 128-bit register, using only
20011
    // two instructions on most compilers.
20012
#ifdef __LITTLE_ENDIAN__
20013
    __m128i shufmask = (__m128i)(__vector unsigned long long){
20014
        thintable_epi8[mask1], thintable_epi8[mask2]};
20015
#else
20016
    __m128i shufmask = (__m128i)(__vector unsigned long long){
20017
        thintable_epi8[mask2], thintable_epi8[mask1]};
20018
    shufmask = (__m128i)vec_reve((__m128i)shufmask);
20019
#endif
20020
    // we increment by 0x08 the second half of the mask
20021
    shufmask = ((__m128i)shufmask) +
20022
               ((__m128i)(__vector int){0, 0, 0x08080808, 0x08080808});
20023
20024
    // this is the version "nearly pruned"
20025
    __m128i pruned = vec_perm(this->value, this->value, shufmask);
20026
    // we still need to put the two halves together.
20027
    // we compute the popcount of the first half:
20028
    int pop1 = BitsSetTable256mul2[mask1];
20029
    // then load the corresponding mask, what it does is to write
20030
    // only the first pop1 bytes from the first 8 bytes, and then
20031
    // it fills in with the bytes from the second 8 bytes + some filling
20032
    // at the end.
20033
    __m128i compactmask =
20034
        vec_vsx_ld(0, reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
20035
    __m128i answer = vec_perm(pruned, (__m128i)vec_splats(0), compactmask);
20036
    vec_vsx_st(answer, 0, reinterpret_cast<__m128i *>(output));
20037
  }
20038
20039
  template <typename L>
20040
  simdjson_inline simd8<L>
20041
  lookup_16(L replace0, L replace1, L replace2, L replace3, L replace4,
20042
            L replace5, L replace6, L replace7, L replace8, L replace9,
20043
            L replace10, L replace11, L replace12, L replace13, L replace14,
20044
            L replace15) const {
20045
    return lookup_16(simd8<L>::repeat_16(
20046
        replace0, replace1, replace2, replace3, replace4, replace5, replace6,
20047
        replace7, replace8, replace9, replace10, replace11, replace12,
20048
        replace13, replace14, replace15));
20049
  }
20050
};
20051
20052
// Signed bytes
20053
template <> struct simd8<int8_t> : base8_numeric<int8_t> {
20054
  simdjson_inline simd8() : base8_numeric<int8_t>() {}
20055
  simdjson_inline simd8(const __m128i _value)
20056
      : base8_numeric<int8_t>(_value) {}
20057
  // Splat constructor
20058
  simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
20059
  // Array constructor
20060
  simdjson_inline simd8(const int8_t *values) : simd8(load(values)) {}
20061
  // Member-by-member initialization
20062
  simdjson_inline simd8(int8_t v0, int8_t v1, int8_t v2, int8_t v3,
20063
                               int8_t v4, int8_t v5, int8_t v6, int8_t v7,
20064
                               int8_t v8, int8_t v9, int8_t v10, int8_t v11,
20065
                               int8_t v12, int8_t v13, int8_t v14, int8_t v15)
20066
      : simd8((__m128i)(__vector signed char){v0, v1, v2, v3, v4, v5, v6, v7,
20067
                                              v8, v9, v10, v11, v12, v13, v14,
20068
                                              v15}) {}
20069
  // Repeat 16 values as many times as necessary (usually for lookup tables)
20070
  simdjson_inline static simd8<int8_t>
20071
  repeat_16(int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5,
20072
            int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11,
20073
            int8_t v12, int8_t v13, int8_t v14, int8_t v15) {
20074
    return simd8<int8_t>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
20075
                         v13, v14, v15);
20076
  }
20077
20078
  // Order-sensitive comparisons
20079
  simdjson_inline simd8<int8_t>
20080
  max_val(const simd8<int8_t> other) const {
20081
    return (__m128i)vec_max((__vector signed char)this->value,
20082
                            (__vector signed char)(__m128i)other);
20083
  }
20084
  simdjson_inline simd8<int8_t>
20085
  min_val(const simd8<int8_t> other) const {
20086
    return (__m128i)vec_min((__vector signed char)this->value,
20087
                            (__vector signed char)(__m128i)other);
20088
  }
20089
  simdjson_inline simd8<bool>
20090
  operator>(const simd8<int8_t> other) const {
20091
    return (__m128i)vec_cmpgt((__vector signed char)this->value,
20092
                              (__vector signed char)(__m128i)other);
20093
  }
20094
  simdjson_inline simd8<bool>
20095
  operator<(const simd8<int8_t> other) const {
20096
    return (__m128i)vec_cmplt((__vector signed char)this->value,
20097
                              (__vector signed char)(__m128i)other);
20098
  }
20099
};
20100
20101
// Unsigned bytes
20102
template <> struct simd8<uint8_t> : base8_numeric<uint8_t> {
20103
  simdjson_inline simd8() : base8_numeric<uint8_t>() {}
20104
  simdjson_inline simd8(const __m128i _value)
20105
      : base8_numeric<uint8_t>(_value) {}
20106
  // Splat constructor
20107
  simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
20108
  // Array constructor
20109
  simdjson_inline simd8(const uint8_t *values) : simd8(load(values)) {}
20110
  // Member-by-member initialization
20111
  simdjson_inline
20112
  simd8(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5,
20113
        uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10,
20114
        uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15)
20115
      : simd8((__m128i){v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
20116
                        v13, v14, v15}) {}
20117
  // Repeat 16 values as many times as necessary (usually for lookup tables)
20118
  simdjson_inline static simd8<uint8_t>
20119
  repeat_16(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4,
20120
            uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9,
20121
            uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14,
20122
            uint8_t v15) {
20123
    return simd8<uint8_t>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
20124
                          v13, v14, v15);
20125
  }
20126
20127
  // Saturated math
20128
  simdjson_inline simd8<uint8_t>
20129
  saturating_add(const simd8<uint8_t> other) const {
20130
    return (__m128i)vec_adds(this->value, (__m128i)other);
20131
  }
20132
  simdjson_inline simd8<uint8_t>
20133
  saturating_sub(const simd8<uint8_t> other) const {
20134
    return (__m128i)vec_subs(this->value, (__m128i)other);
20135
  }
20136
20137
  // Order-specific operations
20138
  simdjson_inline simd8<uint8_t>
20139
  max_val(const simd8<uint8_t> other) const {
20140
    return (__m128i)vec_max(this->value, (__m128i)other);
20141
  }
20142
  simdjson_inline simd8<uint8_t>
20143
  min_val(const simd8<uint8_t> other) const {
20144
    return (__m128i)vec_min(this->value, (__m128i)other);
20145
  }
20146
  // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
20147
  simdjson_inline simd8<uint8_t>
20148
  gt_bits(const simd8<uint8_t> other) const {
20149
    return this->saturating_sub(other);
20150
  }
20151
  // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
20152
  simdjson_inline simd8<uint8_t>
20153
  lt_bits(const simd8<uint8_t> other) const {
20154
    return other.saturating_sub(*this);
20155
  }
20156
  simdjson_inline simd8<bool>
20157
  operator<=(const simd8<uint8_t> other) const {
20158
    return other.max_val(*this) == other;
20159
  }
20160
  simdjson_inline simd8<bool>
20161
  operator>=(const simd8<uint8_t> other) const {
20162
    return other.min_val(*this) == other;
20163
  }
20164
  simdjson_inline simd8<bool>
20165
  operator>(const simd8<uint8_t> other) const {
20166
    return this->gt_bits(other).any_bits_set();
20167
  }
20168
  simdjson_inline simd8<bool>
20169
  operator<(const simd8<uint8_t> other) const {
20170
    return this->gt_bits(other).any_bits_set();
20171
  }
20172
20173
  // Bit-specific operations
20174
  simdjson_inline simd8<bool> bits_not_set() const {
20175
    return (__m128i)vec_cmpeq(this->value, (__m128i)vec_splats(uint8_t(0)));
20176
  }
20177
  simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const {
20178
    return (*this & bits).bits_not_set();
20179
  }
20180
  simdjson_inline simd8<bool> any_bits_set() const {
20181
    return ~this->bits_not_set();
20182
  }
20183
  simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const {
20184
    return ~this->bits_not_set(bits);
20185
  }
20186
  simdjson_inline bool bits_not_set_anywhere() const {
20187
    return vec_all_eq(this->value, (__m128i)vec_splats(0));
20188
  }
20189
  simdjson_inline bool any_bits_set_anywhere() const {
20190
    return !bits_not_set_anywhere();
20191
  }
20192
  simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const {
20193
    return vec_all_eq(vec_and(this->value, (__m128i)bits),
20194
                      (__m128i)vec_splats(0));
20195
  }
20196
  simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const {
20197
    return !bits_not_set_anywhere(bits);
20198
  }
20199
  template <int N> simdjson_inline simd8<uint8_t> shr() const {
20200
    return simd8<uint8_t>(
20201
        (__m128i)vec_sr(this->value, (__m128i)vec_splat_u8(N)));
20202
  }
20203
  template <int N> simdjson_inline simd8<uint8_t> shl() const {
20204
    return simd8<uint8_t>(
20205
        (__m128i)vec_sl(this->value, (__m128i)vec_splat_u8(N)));
20206
  }
20207
};
20208
20209
template <typename T> struct simd8x64 {
20210
  static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
20211
  static_assert(NUM_CHUNKS == 4,
20212
                "PPC64 kernel should use four registers per 64-byte block.");
20213
  const simd8<T> chunks[NUM_CHUNKS];
20214
20215
  simd8x64(const simd8x64<T> &o) = delete; // no copy allowed
20216
  simd8x64<T> &
20217
  operator=(const simd8<T>& other) = delete; // no assignment allowed
20218
  simd8x64() = delete;                      // no default constructor allowed
20219
20220
  simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1,
20221
                                  const simd8<T> chunk2, const simd8<T> chunk3)
20222
      : chunks{chunk0, chunk1, chunk2, chunk3} {}
20223
  simdjson_inline simd8x64(const T ptr[64])
20224
      : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr + 16),
20225
               simd8<T>::load(ptr + 32), simd8<T>::load(ptr + 48)} {}
20226
20227
  simdjson_inline void store(T ptr[64]) const {
20228
    this->chunks[0].store(ptr + sizeof(simd8<T>) * 0);
20229
    this->chunks[1].store(ptr + sizeof(simd8<T>) * 1);
20230
    this->chunks[2].store(ptr + sizeof(simd8<T>) * 2);
20231
    this->chunks[3].store(ptr + sizeof(simd8<T>) * 3);
20232
  }
20233
20234
  simdjson_inline simd8<T> reduce_or() const {
20235
    return (this->chunks[0] | this->chunks[1]) |
20236
           (this->chunks[2] | this->chunks[3]);
20237
  }
20238
20239
  simdjson_inline uint64_t compress(uint64_t mask, T *output) const {
20240
    this->chunks[0].compress(uint16_t(mask), output);
20241
    this->chunks[1].compress(uint16_t(mask >> 16),
20242
                             output + 16 - count_ones(mask & 0xFFFF));
20243
    this->chunks[2].compress(uint16_t(mask >> 32),
20244
                             output + 32 - count_ones(mask & 0xFFFFFFFF));
20245
    this->chunks[3].compress(uint16_t(mask >> 48),
20246
                             output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
20247
    return 64 - count_ones(mask);
20248
  }
20249
20250
  simdjson_inline uint64_t to_bitmask() const {
20251
    uint64_t r0 = uint32_t(this->chunks[0].to_bitmask());
20252
    uint64_t r1 = this->chunks[1].to_bitmask();
20253
    uint64_t r2 = this->chunks[2].to_bitmask();
20254
    uint64_t r3 = this->chunks[3].to_bitmask();
20255
    return r0 | (r1 << 16) | (r2 << 32) | (r3 << 48);
20256
  }
20257
20258
  simdjson_inline uint64_t eq(const T m) const {
20259
    const simd8<T> mask = simd8<T>::splat(m);
20260
    return simd8x64<bool>(this->chunks[0] == mask, this->chunks[1] == mask,
20261
                          this->chunks[2] == mask, this->chunks[3] == mask)
20262
        .to_bitmask();
20263
  }
20264
20265
  simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
20266
    return simd8x64<bool>(this->chunks[0] == other.chunks[0],
20267
                          this->chunks[1] == other.chunks[1],
20268
                          this->chunks[2] == other.chunks[2],
20269
                          this->chunks[3] == other.chunks[3])
20270
        .to_bitmask();
20271
  }
20272
20273
  simdjson_inline uint64_t lteq(const T m) const {
20274
    const simd8<T> mask = simd8<T>::splat(m);
20275
    return simd8x64<bool>(this->chunks[0] <= mask, this->chunks[1] <= mask,
20276
                          this->chunks[2] <= mask, this->chunks[3] <= mask)
20277
        .to_bitmask();
20278
  }
20279
}; // struct simd8x64<T>
20280
20281
} // namespace simd
20282
} // unnamed namespace
20283
} // namespace ppc64
20284
} // namespace simdjson
20285
20286
#endif // SIMDJSON_PPC64_SIMD_INPUT_H
20287
/* end file simdjson/ppc64/simd.h */
20288
/* including simdjson/ppc64/stringparsing_defs.h: #include "simdjson/ppc64/stringparsing_defs.h" */
20289
/* begin file simdjson/ppc64/stringparsing_defs.h */
20290
#ifndef SIMDJSON_PPC64_STRINGPARSING_DEFS_H
20291
#define SIMDJSON_PPC64_STRINGPARSING_DEFS_H
20292
20293
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
20294
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
20295
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/bitmanipulation.h" */
20296
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/simd.h" */
20297
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
20298
20299
namespace simdjson {
20300
namespace ppc64 {
20301
namespace {
20302
20303
using namespace simd;
20304
20305
// Holds backslashes and quotes locations.
20306
struct backslash_and_quote {
20307
public:
20308
  static constexpr uint32_t BYTES_PROCESSED = 32;
20309
  simdjson_inline static backslash_and_quote
20310
  copy_and_find(const uint8_t *src, uint8_t *dst);
20311
20312
  simdjson_inline bool has_quote_first() {
20313
    return ((bs_bits - 1) & quote_bits) != 0;
20314
  }
20315
  simdjson_inline bool has_backslash() { return bs_bits != 0; }
20316
  simdjson_inline int quote_index() {
20317
    return trailing_zeroes(quote_bits);
20318
  }
20319
  simdjson_inline int backslash_index() {
20320
    return trailing_zeroes(bs_bits);
20321
  }
20322
20323
  uint32_t bs_bits;
20324
  uint32_t quote_bits;
20325
}; // struct backslash_and_quote
20326
20327
simdjson_inline backslash_and_quote
20328
backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
20329
  // this can read up to 31 bytes beyond the buffer size, but we require
20330
  // SIMDJSON_PADDING of padding
20331
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1),
20332
                "backslash and quote finder must process fewer than "
20333
                "SIMDJSON_PADDING bytes");
20334
  simd8<uint8_t> v0(src);
20335
  simd8<uint8_t> v1(src + sizeof(v0));
20336
  v0.store(dst);
20337
  v1.store(dst + sizeof(v0));
20338
20339
  // Getting a 64-bit bitmask is much cheaper than multiple 16-bit bitmasks on
20340
  // PPC; therefore, we smash them together into a 64-byte mask and get the
20341
  // bitmask from there.
20342
  uint64_t bs_and_quote =
20343
      simd8x64<bool>(v0 == '\\', v1 == '\\', v0 == '"', v1 == '"').to_bitmask();
20344
  return {
20345
      uint32_t(bs_and_quote),      // bs_bits
20346
      uint32_t(bs_and_quote >> 32) // quote_bits
20347
  };
20348
}
20349
20350
} // unnamed namespace
20351
} // namespace ppc64
20352
} // namespace simdjson
20353
20354
#endif // SIMDJSON_PPC64_STRINGPARSING_DEFS_H
20355
/* end file simdjson/ppc64/stringparsing_defs.h */
20356
20357
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
20358
/* end file simdjson/ppc64/begin.h */
20359
/* including simdjson/generic/amalgamated.h for ppc64: #include "simdjson/generic/amalgamated.h" */
20360
/* begin file simdjson/generic/amalgamated.h for ppc64 */
20361
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
20362
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
20363
#endif
20364
20365
/* including simdjson/generic/base.h for ppc64: #include "simdjson/generic/base.h" */
20366
/* begin file simdjson/generic/base.h for ppc64 */
20367
#ifndef SIMDJSON_GENERIC_BASE_H
20368
20369
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
20370
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_BASE_H */
20371
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
20372
/* amalgamation skipped (editor-only): // If we haven't got an implementation yet, we're in the editor, editing a generic file! Just */
20373
/* amalgamation skipped (editor-only): // use the most advanced one we can so the most possible stuff can be tested. */
20374
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_IMPLEMENTATION */
20375
/* amalgamation skipped (editor-only): #include "simdjson/implementation_detection.h" */
20376
/* amalgamation skipped (editor-only): #if SIMDJSON_IMPLEMENTATION_ICELAKE */
20377
/* amalgamation skipped (editor-only): #include "simdjson/icelake/begin.h" */
20378
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_HASWELL */
20379
/* amalgamation skipped (editor-only): #include "simdjson/haswell/begin.h" */
20380
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_WESTMERE */
20381
/* amalgamation skipped (editor-only): #include "simdjson/westmere/begin.h" */
20382
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_ARM64 */
20383
/* amalgamation skipped (editor-only): #include "simdjson/arm64/begin.h" */
20384
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_PPC64 */
20385
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/begin.h" */
20386
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_FALLBACK */
20387
/* amalgamation skipped (editor-only): #include "simdjson/fallback/begin.h" */
20388
/* amalgamation skipped (editor-only): #else */
20389
/* amalgamation skipped (editor-only): #error "All possible implementations (including fallback) have been disabled! simdjson will not run." */
20390
/* amalgamation skipped (editor-only): #endif */
20391
/* amalgamation skipped (editor-only): #endif // SIMDJSON_IMPLEMENTATION */
20392
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
20393
20394
namespace simdjson {
20395
namespace ppc64 {
20396
20397
struct open_container;
20398
class dom_parser_implementation;
20399
20400
/**
20401
 * The type of a JSON number
20402
 */
20403
enum class number_type {
20404
    floating_point_number=1, /// a binary64 number
20405
    signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
20406
    unsigned_integer,        /// a positive integer larger or equal to 1<<63
20407
    big_integer              /// a big integer that does not fit in a 64-bit word
20408
};
20409
20410
} // namespace ppc64
20411
} // namespace simdjson
20412
20413
#endif // SIMDJSON_GENERIC_BASE_H
20414
/* end file simdjson/generic/base.h for ppc64 */
20415
/* including simdjson/generic/jsoncharutils.h for ppc64: #include "simdjson/generic/jsoncharutils.h" */
20416
/* begin file simdjson/generic/jsoncharutils.h for ppc64 */
20417
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
20418
20419
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
20420
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_JSONCHARUTILS_H */
20421
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
20422
/* amalgamation skipped (editor-only): #include "simdjson/internal/jsoncharutils_tables.h" */
20423
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
20424
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
20425
20426
namespace simdjson {
20427
namespace ppc64 {
20428
namespace {
20429
namespace jsoncharutils {
20430
20431
// return non-zero if not a structural or whitespace char
20432
// zero otherwise
20433
simdjson_inline uint32_t is_not_structural_or_whitespace(uint8_t c) {
20434
  return internal::structural_or_whitespace_negated[c];
20435
}
20436
20437
simdjson_inline uint32_t is_structural_or_whitespace(uint8_t c) {
20438
  return internal::structural_or_whitespace[c];
20439
}
20440
20441
// returns a value with the high 16 bits set if not valid
20442
// otherwise returns the conversion of the 4 hex digits at src into the bottom
20443
// 16 bits of the 32-bit return register
20444
//
20445
// see
20446
// https://lemire.me/blog/2019/04/17/parsing-short-hexadecimal-strings-efficiently/
20447
static inline uint32_t hex_to_u32_nocheck(
20448
    const uint8_t *src) { // strictly speaking, static inline is a C-ism
20449
  uint32_t v1 = internal::digit_to_val32[630 + src[0]];
20450
  uint32_t v2 = internal::digit_to_val32[420 + src[1]];
20451
  uint32_t v3 = internal::digit_to_val32[210 + src[2]];
20452
  uint32_t v4 = internal::digit_to_val32[0 + src[3]];
20453
  return v1 | v2 | v3 | v4;
20454
}
20455
20456
// given a code point cp, writes to c
20457
// the utf-8 code, outputting the length in
20458
// bytes, if the length is zero, the code point
20459
// is invalid
20460
//
20461
// This can possibly be made faster using pdep
20462
// and clz and table lookups, but JSON documents
20463
// have few escaped code points, and the following
20464
// function looks cheap.
20465
//
20466
// Note: we assume that surrogates are treated separately
20467
//
20468
simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
20469
  if (cp <= 0x7F) {
20470
    c[0] = uint8_t(cp);
20471
    return 1; // ascii
20472
  }
20473
  if (cp <= 0x7FF) {
20474
    c[0] = uint8_t((cp >> 6) + 192);
20475
    c[1] = uint8_t((cp & 63) + 128);
20476
    return 2; // universal plane
20477
    //  Surrogates are treated elsewhere...
20478
    //} //else if (0xd800 <= cp && cp <= 0xdfff) {
20479
    //  return 0; // surrogates // could put assert here
20480
  } else if (cp <= 0xFFFF) {
20481
    c[0] = uint8_t((cp >> 12) + 224);
20482
    c[1] = uint8_t(((cp >> 6) & 63) + 128);
20483
    c[2] = uint8_t((cp & 63) + 128);
20484
    return 3;
20485
  } else if (cp <= 0x10FFFF) { // if you know you have a valid code point, this
20486
                               // is not needed
20487
    c[0] = uint8_t((cp >> 18) + 240);
20488
    c[1] = uint8_t(((cp >> 12) & 63) + 128);
20489
    c[2] = uint8_t(((cp >> 6) & 63) + 128);
20490
    c[3] = uint8_t((cp & 63) + 128);
20491
    return 4;
20492
  }
20493
  // will return 0 when the code point was too large.
20494
  return 0; // bad r
20495
}
20496
20497
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
20498
// this is a slow emulation routine for 32-bit
20499
//
20500
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
20501
  return x * (uint64_t)y;
20502
}
20503
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
20504
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
20505
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
20506
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
20507
  uint64_t adbc_carry = !!(adbc < ad);
20508
  uint64_t lo = bd + (adbc << 32);
20509
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
20510
        (adbc_carry << 32) + !!(lo < bd);
20511
  return lo;
20512
}
20513
#endif
20514
20515
} // namespace jsoncharutils
20516
} // unnamed namespace
20517
} // namespace ppc64
20518
} // namespace simdjson
20519
20520
#endif // SIMDJSON_GENERIC_JSONCHARUTILS_H
20521
/* end file simdjson/generic/jsoncharutils.h for ppc64 */
20522
/* including simdjson/generic/atomparsing.h for ppc64: #include "simdjson/generic/atomparsing.h" */
20523
/* begin file simdjson/generic/atomparsing.h for ppc64 */
20524
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
20525
20526
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
20527
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ATOMPARSING_H */
20528
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
20529
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
20530
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
20531
20532
#include <cstring>
20533
20534
namespace simdjson {
20535
namespace ppc64 {
20536
namespace {
20537
/// @private
20538
namespace atomparsing {
20539
20540
// The string_to_uint32 is exclusively used to map literal strings to 32-bit values.
20541
// We use memcpy instead of a pointer cast to avoid undefined behaviors since we cannot
20542
// be certain that the character pointer will be properly aligned.
20543
// You might think that using memcpy makes this function expensive, but you'd be wrong.
20544
// All decent optimizing compilers (GCC, clang, Visual Studio) will compile string_to_uint32("false");
20545
// to the compile-time constant 1936482662.
20546
simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(&val, str, sizeof(uint32_t)); return val; }
20547
20548
20549
// Again in str4ncmp we use a memcpy to avoid undefined behavior. The memcpy may appear expensive.
20550
// Yet all decent optimizing compilers will compile memcpy to a single instruction, just about.
20551
simdjson_warn_unused
20552
simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) {
20553
  uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++)
20554
  static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes");
20555
  std::memcpy(&srcval, src, sizeof(uint32_t));
20556
  return srcval ^ string_to_uint32(atom);
20557
}
20558
20559
simdjson_warn_unused
20560
simdjson_inline bool is_valid_true_atom(const uint8_t *src) {
20561
  return (str4ncmp(src, "true") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
20562
}
20563
20564
simdjson_warn_unused
20565
simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) {
20566
  if (len > 4) { return is_valid_true_atom(src); }
20567
  else if (len == 4) { return !str4ncmp(src, "true"); }
20568
  else { return false; }
20569
}
20570
20571
simdjson_warn_unused
20572
simdjson_inline bool is_valid_false_atom(const uint8_t *src) {
20573
  return (str4ncmp(src+1, "alse") | jsoncharutils::is_not_structural_or_whitespace(src[5])) == 0;
20574
}
20575
20576
simdjson_warn_unused
20577
simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) {
20578
  if (len > 5) { return is_valid_false_atom(src); }
20579
  else if (len == 5) { return !str4ncmp(src+1, "alse"); }
20580
  else { return false; }
20581
}
20582
20583
simdjson_warn_unused
20584
simdjson_inline bool is_valid_null_atom(const uint8_t *src) {
20585
  return (str4ncmp(src, "null") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
20586
}
20587
20588
simdjson_warn_unused
20589
simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
20590
  if (len > 4) { return is_valid_null_atom(src); }
20591
  else if (len == 4) { return !str4ncmp(src, "null"); }
20592
  else { return false; }
20593
}
20594
20595
} // namespace atomparsing
20596
} // unnamed namespace
20597
} // namespace ppc64
20598
} // namespace simdjson
20599
20600
#endif // SIMDJSON_GENERIC_ATOMPARSING_H
20601
/* end file simdjson/generic/atomparsing.h for ppc64 */
20602
/* including simdjson/generic/dom_parser_implementation.h for ppc64: #include "simdjson/generic/dom_parser_implementation.h" */
20603
/* begin file simdjson/generic/dom_parser_implementation.h for ppc64 */
20604
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
20605
20606
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
20607
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H */
20608
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
20609
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
20610
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
20611
20612
namespace simdjson {
20613
namespace ppc64 {
20614
20615
// expectation: sizeof(open_container) = 64/8.
20616
struct open_container {
20617
  uint32_t tape_index; // where, on the tape, does the scope ([,{) begins
20618
  uint32_t count; // how many elements in the scope
20619
}; // struct open_container
20620
20621
static_assert(sizeof(open_container) == 64/8, "Open container must be 64 bits");
20622
20623
class dom_parser_implementation final : public internal::dom_parser_implementation {
20624
public:
20625
  /** Tape location of each open { or [ */
20626
  std::unique_ptr<open_container[]> open_containers{};
20627
  /** Whether each open container is a [ or { */
20628
  std::unique_ptr<bool[]> is_array{};
20629
  /** Buffer passed to stage 1 */
20630
  const uint8_t *buf{};
20631
  /** Length passed to stage 1 */
20632
  size_t len{0};
20633
  /** Document passed to stage 2 */
20634
  dom::document *doc{};
20635
20636
  inline dom_parser_implementation() noexcept;
20637
  inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
20638
  inline dom_parser_implementation &operator=(dom_parser_implementation &&other) noexcept;
20639
  dom_parser_implementation(const dom_parser_implementation &) = delete;
20640
  dom_parser_implementation &operator=(const dom_parser_implementation &) = delete;
20641
20642
  simdjson_warn_unused error_code parse(const uint8_t *buf, size_t len, dom::document &doc) noexcept final;
20643
  simdjson_warn_unused error_code stage1(const uint8_t *buf, size_t len, stage1_mode partial) noexcept final;
20644
  simdjson_warn_unused error_code stage2(dom::document &doc) noexcept final;
20645
  simdjson_warn_unused error_code stage2_next(dom::document &doc) noexcept final;
20646
  simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept final;
20647
  simdjson_warn_unused uint8_t *parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept final;
20648
  inline simdjson_warn_unused error_code set_capacity(size_t capacity) noexcept final;
20649
  inline simdjson_warn_unused error_code set_max_depth(size_t max_depth) noexcept final;
20650
private:
20651
  simdjson_inline simdjson_warn_unused error_code set_capacity_stage1(size_t capacity);
20652
20653
};
20654
20655
} // namespace ppc64
20656
} // namespace simdjson
20657
20658
namespace simdjson {
20659
namespace ppc64 {
20660
20661
inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
20662
inline dom_parser_implementation::dom_parser_implementation(dom_parser_implementation &&other) noexcept = default;
20663
inline dom_parser_implementation &dom_parser_implementation::operator=(dom_parser_implementation &&other) noexcept = default;
20664
20665
// Leaving these here so they can be inlined if so desired
20666
inline simdjson_warn_unused error_code dom_parser_implementation::set_capacity(size_t capacity) noexcept {
20667
  if(capacity > SIMDJSON_MAXSIZE_BYTES) { return CAPACITY; }
20668
  // Stage 1 index output
20669
  size_t max_structures = SIMDJSON_ROUNDUP_N(capacity, 64) + 2 + 7;
20670
  structural_indexes.reset( new (std::nothrow) uint32_t[max_structures] );
20671
  if (!structural_indexes) { _capacity = 0; return MEMALLOC; }
20672
  structural_indexes[0] = 0;
20673
  n_structural_indexes = 0;
20674
20675
  _capacity = capacity;
20676
  return SUCCESS;
20677
}
20678
20679
inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(size_t max_depth) noexcept {
20680
  // Stage 2 stacks
20681
  open_containers.reset(new (std::nothrow) open_container[max_depth]);
20682
  is_array.reset(new (std::nothrow) bool[max_depth]);
20683
  if (!is_array || !open_containers) { _max_depth = 0; return MEMALLOC; }
20684
20685
  _max_depth = max_depth;
20686
  return SUCCESS;
20687
}
20688
20689
} // namespace ppc64
20690
} // namespace simdjson
20691
20692
#endif // SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
20693
/* end file simdjson/generic/dom_parser_implementation.h for ppc64 */
20694
/* including simdjson/generic/implementation_simdjson_result_base.h for ppc64: #include "simdjson/generic/implementation_simdjson_result_base.h" */
20695
/* begin file simdjson/generic/implementation_simdjson_result_base.h for ppc64 */
20696
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
20697
20698
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
20699
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H */
20700
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
20701
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
20702
20703
namespace simdjson {
20704
namespace ppc64 {
20705
20706
// This is a near copy of include/error.h's implementation_simdjson_result_base, except it doesn't use std::pair
20707
// so we can avoid inlining errors
20708
// TODO reconcile these!
20709
/**
20710
 * The result of a simdjson operation that could fail.
20711
 *
20712
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
20713
 *
20714
 * This is a base class for implementations that want to add functions to the result type for
20715
 * chaining.
20716
 *
20717
 * Override like:
20718
 *
20719
 *   struct simdjson_result<T> : public internal::implementation_simdjson_result_base<T> {
20720
 *     simdjson_result() noexcept : internal::implementation_simdjson_result_base<T>() {}
20721
 *     simdjson_result(error_code error) noexcept : internal::implementation_simdjson_result_base<T>(error) {}
20722
 *     simdjson_result(T &&value) noexcept : internal::implementation_simdjson_result_base<T>(std::forward(value)) {}
20723
 *     simdjson_result(T &&value, error_code error) noexcept : internal::implementation_simdjson_result_base<T>(value, error) {}
20724
 *     // Your extra methods here
20725
 *   }
20726
 *
20727
 * Then any method returning simdjson_result<T> will be chainable with your methods.
20728
 */
20729
template<typename T>
20730
struct implementation_simdjson_result_base {
20731
20732
  /**
20733
   * Create a new empty result with error = UNINITIALIZED.
20734
   */
20735
  simdjson_inline implementation_simdjson_result_base() noexcept = default;
20736
20737
  /**
20738
   * Create a new error result.
20739
   */
20740
  simdjson_inline implementation_simdjson_result_base(error_code error) noexcept;
20741
20742
  /**
20743
   * Create a new successful result.
20744
   */
20745
  simdjson_inline implementation_simdjson_result_base(T &&value) noexcept;
20746
20747
  /**
20748
   * Create a new result with both things (use if you don't want to branch when creating the result).
20749
   */
20750
  simdjson_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
20751
20752
  /**
20753
   * Move the value and the error to the provided variables.
20754
   *
20755
   * @param value The variable to assign the value to. May not be set if there is an error.
20756
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
20757
   */
20758
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
20759
20760
  /**
20761
   * Move the value to the provided variable.
20762
   *
20763
   * @param value The variable to assign the value to. May not be set if there is an error.
20764
   */
20765
  simdjson_inline error_code get(T &value) && noexcept;
20766
20767
  /**
20768
   * The error.
20769
   */
20770
  simdjson_inline error_code error() const noexcept;
20771
20772
#if SIMDJSON_EXCEPTIONS
20773
20774
  /**
20775
   * Get the result value.
20776
   *
20777
   * @throw simdjson_error if there was an error.
20778
   */
20779
  simdjson_inline T& value() & noexcept(false);
20780
20781
  /**
20782
   * Take the result value (move it).
20783
   *
20784
   * @throw simdjson_error if there was an error.
20785
   */
20786
  simdjson_inline T&& value() && noexcept(false);
20787
20788
  /**
20789
   * Take the result value (move it).
20790
   *
20791
   * @throw simdjson_error if there was an error.
20792
   */
20793
  simdjson_inline T&& take_value() && noexcept(false);
20794
20795
  /**
20796
   * Cast to the value (will throw on error).
20797
   *
20798
   * @throw simdjson_error if there was an error.
20799
   */
20800
  simdjson_inline operator T&&() && noexcept(false);
20801
20802
20803
#endif // SIMDJSON_EXCEPTIONS
20804
20805
  /**
20806
   * Get the result value. This function is safe if and only
20807
   * the error() method returns a value that evaluates to false.
20808
   */
20809
  simdjson_inline const T& value_unsafe() const& noexcept;
20810
  /**
20811
   * Get the result value. This function is safe if and only
20812
   * the error() method returns a value that evaluates to false.
20813
   */
20814
  simdjson_inline T& value_unsafe() & noexcept;
20815
  /**
20816
   * Take the result value (move it). This function is safe if and only
20817
   * the error() method returns a value that evaluates to false.
20818
   */
20819
  simdjson_inline T&& value_unsafe() && noexcept;
20820
protected:
20821
  /** users should never directly access first and second. **/
20822
  T first{}; /** Users should never directly access 'first'. **/
20823
  error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
20824
}; // struct implementation_simdjson_result_base
20825
20826
} // namespace ppc64
20827
} // namespace simdjson
20828
20829
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
20830
/* end file simdjson/generic/implementation_simdjson_result_base.h for ppc64 */
20831
/* including simdjson/generic/numberparsing.h for ppc64: #include "simdjson/generic/numberparsing.h" */
20832
/* begin file simdjson/generic/numberparsing.h for ppc64 */
20833
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
20834
20835
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
20836
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_NUMBERPARSING_H */
20837
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
20838
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
20839
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
20840
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
20841
20842
#include <limits>
20843
#include <ostream>
20844
#include <cstring>
20845
20846
namespace simdjson {
20847
namespace ppc64 {
20848
namespace numberparsing {
20849
20850
#ifdef JSON_TEST_NUMBERS
20851
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
20852
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
20853
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
20854
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
20855
#define BIGINT_NUMBER(SRC) (found_invalid_number((SRC)), BIGINT_ERROR)
20856
#else
20857
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
20858
#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
20859
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
20860
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
20861
#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
20862
#endif
20863
20864
namespace {
20865
20866
// Convert a mantissa, an exponent and a sign bit into an ieee64 double.
20867
// The real_exponent needs to be in [0, 2046] (technically real_exponent = 2047 would be acceptable).
20868
// The mantissa should be in [0,1<<53). The bit at index (1ULL << 52) while be zeroed.
20869
simdjson_inline double to_double(uint64_t mantissa, uint64_t real_exponent, bool negative) {
20870
    double d;
20871
    mantissa &= ~(1ULL << 52);
20872
    mantissa |= real_exponent << 52;
20873
    mantissa |= ((static_cast<uint64_t>(negative)) << 63);
20874
    std::memcpy(&d, &mantissa, sizeof(d));
20875
    return d;
20876
}
20877
20878
// Attempts to compute i * 10^(power) exactly; and if "negative" is
20879
// true, negate the result.
20880
// This function will only work in some cases, when it does not work, success is
20881
// set to false. This should work *most of the time* (like 99% of the time).
20882
// We assume that power is in the [smallest_power,
20883
// largest_power] interval: the caller is responsible for this check.
20884
simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, double &d) {
20885
  // we start with a fast path
20886
  // It was described in
20887
  // Clinger WD. How to read floating point numbers accurately.
20888
  // ACM SIGPLAN Notices. 1990
20889
#ifndef FLT_EVAL_METHOD
20890
#error "FLT_EVAL_METHOD should be defined, please include cfloat."
20891
#endif
20892
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
20893
  // We cannot be certain that x/y is rounded to nearest.
20894
  if (0 <= power && power <= 22 && i <= 9007199254740991)
20895
#else
20896
  if (-22 <= power && power <= 22 && i <= 9007199254740991)
20897
#endif
20898
  {
20899
    // convert the integer into a double. This is lossless since
20900
    // 0 <= i <= 2^53 - 1.
20901
    d = double(i);
20902
    //
20903
    // The general idea is as follows.
20904
    // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
20905
    // 1) Both s and p can be represented exactly as 64-bit floating-point
20906
    // values
20907
    // (binary64).
20908
    // 2) Because s and p can be represented exactly as floating-point values,
20909
    // then s * p
20910
    // and s / p will produce correctly rounded values.
20911
    //
20912
    if (power < 0) {
20913
      d = d / simdjson::internal::power_of_ten[-power];
20914
    } else {
20915
      d = d * simdjson::internal::power_of_ten[power];
20916
    }
20917
    if (negative) {
20918
      d = -d;
20919
    }
20920
    return true;
20921
  }
20922
  // When 22 < power && power <  22 + 16, we could
20923
  // hope for another, secondary fast path.  It was
20924
  // described by David M. Gay in  "Correctly rounded
20925
  // binary-decimal and decimal-binary conversions." (1990)
20926
  // If you need to compute i * 10^(22 + x) for x < 16,
20927
  // first compute i * 10^x, if you know that result is exact
20928
  // (e.g., when i * 10^x < 2^53),
20929
  // then you can still proceed and do (i * 10^x) * 10^22.
20930
  // Is this worth your time?
20931
  // You need  22 < power *and* power <  22 + 16 *and* (i * 10^(x-22) < 2^53)
20932
  // for this second fast path to work.
20933
  // If you you have 22 < power *and* power <  22 + 16, and then you
20934
  // optimistically compute "i * 10^(x-22)", there is still a chance that you
20935
  // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
20936
  // this optimization maybe less common than we would like. Source:
20937
  // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
20938
  // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
20939
20940
  // The fast path has now failed, so we are failing back on the slower path.
20941
20942
  // In the slow path, we need to adjust i so that it is > 1<<63 which is always
20943
  // possible, except if i == 0, so we handle i == 0 separately.
20944
  if(i == 0) {
20945
    d = negative ? -0.0 : 0.0;
20946
    return true;
20947
  }
20948
20949
20950
  // The exponent is 1024 + 63 + power
20951
  //     + floor(log(5**power)/log(2)).
20952
  // The 1024 comes from the ieee64 standard.
20953
  // The 63 comes from the fact that we use a 64-bit word.
20954
  //
20955
  // Computing floor(log(5**power)/log(2)) could be
20956
  // slow. Instead we use a fast function.
20957
  //
20958
  // For power in (-400,350), we have that
20959
  // (((152170 + 65536) * power ) >> 16);
20960
  // is equal to
20961
  //  floor(log(5**power)/log(2)) + power when power >= 0
20962
  // and it is equal to
20963
  //  ceil(log(5**-power)/log(2)) + power when power < 0
20964
  //
20965
  // The 65536 is (1<<16) and corresponds to
20966
  // (65536 * power) >> 16 ---> power
20967
  //
20968
  // ((152170 * power ) >> 16) is equal to
20969
  // floor(log(5**power)/log(2))
20970
  //
20971
  // Note that this is not magic: 152170/(1<<16) is
20972
  // approximatively equal to log(5)/log(2).
20973
  // The 1<<16 value is a power of two; we could use a
20974
  // larger power of 2 if we wanted to.
20975
  //
20976
  int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
20977
20978
20979
  // We want the most significant bit of i to be 1. Shift if needed.
20980
  int lz = leading_zeroes(i);
20981
  i <<= lz;
20982
20983
20984
  // We are going to need to do some 64-bit arithmetic to get a precise product.
20985
  // We use a table lookup approach.
20986
  // It is safe because
20987
  // power >= smallest_power
20988
  // and power <= largest_power
20989
  // We recover the mantissa of the power, it has a leading 1. It is always
20990
  // rounded down.
20991
  //
20992
  // We want the most significant 64 bits of the product. We know
20993
  // this will be non-zero because the most significant bit of i is
20994
  // 1.
20995
  const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
20996
  // Optimization: It may be that materializing the index as a variable might confuse some compilers and prevent effective complex-addressing loads. (Done for code clarity.)
20997
  //
20998
  // The full_multiplication function computes the 128-bit product of two 64-bit words
20999
  // with a returned value of type value128 with a "low component" corresponding to the
21000
  // 64-bit least significant bits of the product and with a "high component" corresponding
21001
  // to the 64-bit most significant bits of the product.
21002
  simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
21003
  // Both i and power_of_five_128[index] have their most significant bit set to 1 which
21004
  // implies that the either the most or the second most significant bit of the product
21005
  // is 1. We pack values in this manner for efficiency reasons: it maximizes the use
21006
  // we make of the product. It also makes it easy to reason about the product: there
21007
  // is 0 or 1 leading zero in the product.
21008
21009
  // Unless the least significant 9 bits of the high (64-bit) part of the full
21010
  // product are all 1s, then we know that the most significant 55 bits are
21011
  // exact and no further work is needed. Having 55 bits is necessary because
21012
  // we need 53 bits for the mantissa but we have to have one rounding bit and
21013
  // we can waste a bit if the most significant bit of the product is zero.
21014
  if((firstproduct.high & 0x1FF) == 0x1FF) {
21015
    // We want to compute i * 5^q, but only care about the top 55 bits at most.
21016
    // Consider the scenario where q>=0. Then 5^q may not fit in 64-bits. Doing
21017
    // the full computation is wasteful. So we do what is called a "truncated
21018
    // multiplication".
21019
    // We take the most significant 64-bits, and we put them in
21020
    // power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
21021
    // to the desired approximation using one multiplication. Sometimes it does not suffice.
21022
    // Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
21023
    // then we get a better approximation to i * 5^q.
21024
    //
21025
    // That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
21026
    // more complicated.
21027
    //
21028
    // There is an extra layer of complexity in that we need more than 55 bits of
21029
    // accuracy in the round-to-even scenario.
21030
    //
21031
    // The full_multiplication function computes the 128-bit product of two 64-bit words
21032
    // with a returned value of type value128 with a "low component" corresponding to the
21033
    // 64-bit least significant bits of the product and with a "high component" corresponding
21034
    // to the 64-bit most significant bits of the product.
21035
    simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
21036
    firstproduct.low += secondproduct.high;
21037
    if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
21038
    // As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
21039
    // Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
21040
    // is sufficiently accurate, and more computation is not needed.
21041
  }
21042
  uint64_t lower = firstproduct.low;
21043
  uint64_t upper = firstproduct.high;
21044
  // The final mantissa should be 53 bits with a leading 1.
21045
  // We shift it so that it occupies 54 bits with a leading 1.
21046
  ///////
21047
  uint64_t upperbit = upper >> 63;
21048
  uint64_t mantissa = upper >> (upperbit + 9);
21049
  lz += int(1 ^ upperbit);
21050
21051
  // Here we have mantissa < (1<<54).
21052
  int64_t real_exponent = exponent - lz;
21053
  if (simdjson_unlikely(real_exponent <= 0)) { // we have a subnormal?
21054
    // Here have that real_exponent <= 0 so -real_exponent >= 0
21055
    if(-real_exponent + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
21056
      d = negative ? -0.0 : 0.0;
21057
      return true;
21058
    }
21059
    // next line is safe because -real_exponent + 1 < 0
21060
    mantissa >>= -real_exponent + 1;
21061
    // Thankfully, we can't have both "round-to-even" and subnormals because
21062
    // "round-to-even" only occurs for powers close to 0.
21063
    mantissa += (mantissa & 1); // round up
21064
    mantissa >>= 1;
21065
    // There is a weird scenario where we don't have a subnormal but just.
21066
    // Suppose we start with 2.2250738585072013e-308, we end up
21067
    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
21068
    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
21069
    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
21070
    // subnormal, but we can only know this after rounding.
21071
    // So we only declare a subnormal if we are smaller than the threshold.
21072
    real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
21073
    d = to_double(mantissa, real_exponent, negative);
21074
    return true;
21075
  }
21076
  // We have to round to even. The "to even" part
21077
  // is only a problem when we are right in between two floats
21078
  // which we guard against.
21079
  // If we have lots of trailing zeros, we may fall right between two
21080
  // floating-point values.
21081
  //
21082
  // The round-to-even cases take the form of a number 2m+1 which is in (2^53,2^54]
21083
  // times a power of two. That is, it is right between a number with binary significand
21084
  // m and another number with binary significand m+1; and it must be the case
21085
  // that it cannot be represented by a float itself.
21086
  //
21087
  // We must have that w * 10 ^q == (2m+1) * 2^p for some power of two 2^p.
21088
  // Recall that 10^q = 5^q * 2^q.
21089
  // When q >= 0, we must have that (2m+1) is divible by 5^q, so 5^q <= 2^54. We have that
21090
  //  5^23 <=  2^54 and it is the last power of five to qualify, so q <= 23.
21091
  // When q<0, we have  w  >=  (2m+1) x 5^{-q}.  We must have that w<2^{64} so
21092
  // (2m+1) x 5^{-q} < 2^{64}. We have that 2m+1>2^{53}. Hence, we must have
21093
  // 2^{53} x 5^{-q} < 2^{64}.
21094
  // Hence we have 5^{-q} < 2^{11}$ or q>= -4.
21095
  //
21096
  // We require lower <= 1 and not lower == 0 because we could not prove that
21097
  // that lower == 0 is implied; but we could prove that lower <= 1 is a necessary and sufficient test.
21098
  if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
21099
    if((mantissa  << (upperbit + 64 - 53 - 2)) ==  upper) {
21100
      mantissa &= ~1;             // flip it so that we do not round up
21101
    }
21102
  }
21103
21104
  mantissa += mantissa & 1;
21105
  mantissa >>= 1;
21106
21107
  // Here we have mantissa < (1<<53), unless there was an overflow
21108
  if (mantissa >= (1ULL << 53)) {
21109
    //////////
21110
    // This will happen when parsing values such as 7.2057594037927933e+16
21111
    ////////
21112
    mantissa = (1ULL << 52);
21113
    real_exponent++;
21114
  }
21115
  mantissa &= ~(1ULL << 52);
21116
  // we have to check that real_exponent is in range, otherwise we bail out
21117
  if (simdjson_unlikely(real_exponent > 2046)) {
21118
    // We have an infinite value!!! We could actually throw an error here if we could.
21119
    return false;
21120
  }
21121
  d = to_double(mantissa, real_exponent, negative);
21122
  return true;
21123
}
21124
21125
// We call a fallback floating-point parser that might be slow. Note
21126
// it will accept JSON numbers, but the JSON spec. is more restrictive so
21127
// before you call parse_float_fallback, you need to have validated the input
21128
// string with the JSON grammar.
21129
// It will return an error (false) if the parsed number is infinite.
21130
// The string parsing itself always succeeds. We know that there is at least
21131
// one digit.
21132
static bool parse_float_fallback(const uint8_t *ptr, double *outDouble) {
21133
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr));
21134
  // We do not accept infinite values.
21135
21136
  // Detecting finite values in a portable manner is ridiculously hard, ideally
21137
  // we would want to do:
21138
  // return !std::isfinite(*outDouble);
21139
  // but that mysteriously fails under legacy/old libc++ libraries, see
21140
  // https://github.com/simdjson/simdjson/issues/1286
21141
  //
21142
  // Therefore, fall back to this solution (the extra parens are there
21143
  // to handle that max may be a macro on windows).
21144
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
21145
}
21146
21147
static bool parse_float_fallback(const uint8_t *ptr, const uint8_t *end_ptr, double *outDouble) {
21148
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr), reinterpret_cast<const char *>(end_ptr));
21149
  // We do not accept infinite values.
21150
21151
  // Detecting finite values in a portable manner is ridiculously hard, ideally
21152
  // we would want to do:
21153
  // return !std::isfinite(*outDouble);
21154
  // but that mysteriously fails under legacy/old libc++ libraries, see
21155
  // https://github.com/simdjson/simdjson/issues/1286
21156
  //
21157
  // Therefore, fall back to this solution (the extra parens are there
21158
  // to handle that max may be a macro on windows).
21159
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
21160
}
21161
21162
// check quickly whether the next 8 chars are made of digits
21163
// at a glance, it looks better than Mula's
21164
// http://0x80.pl/articles/swar-digits-validate.html
21165
simdjson_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
21166
  uint64_t val;
21167
  // this can read up to 7 bytes beyond the buffer size, but we require
21168
  // SIMDJSON_PADDING of padding
21169
  static_assert(7 <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be bigger than 7");
21170
  std::memcpy(&val, chars, 8);
21171
  // a branchy method might be faster:
21172
  // return (( val & 0xF0F0F0F0F0F0F0F0 ) == 0x3030303030303030)
21173
  //  && (( (val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0 ) ==
21174
  //  0x3030303030303030);
21175
  return (((val & 0xF0F0F0F0F0F0F0F0) |
21176
           (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
21177
          0x3333333333333333);
21178
}
21179
21180
template<typename I>
21181
SIMDJSON_NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
21182
simdjson_inline bool parse_digit(const uint8_t c, I &i) {
21183
  const uint8_t digit = static_cast<uint8_t>(c - '0');
21184
  if (digit > 9) {
21185
    return false;
21186
  }
21187
  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
21188
  i = 10 * i + digit; // might overflow, we will handle the overflow later
21189
  return true;
21190
}
21191
21192
simdjson_inline bool is_digit(const uint8_t c) {
21193
  return static_cast<uint8_t>(c - '0') <= 9;
21194
}
21195
21196
simdjson_inline error_code parse_decimal_after_separator(simdjson_unused const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
21197
  // we continue with the fiction that we have an integer. If the
21198
  // floating point number is representable as x * 10^z for some integer
21199
  // z that fits in 53 bits, then we will be able to convert back the
21200
  // the integer into a float in a lossless manner.
21201
  const uint8_t *const first_after_period = p;
21202
21203
#ifdef SIMDJSON_SWAR_NUMBER_PARSING
21204
#if SIMDJSON_SWAR_NUMBER_PARSING
21205
  // this helps if we have lots of decimals!
21206
  // this turns out to be frequent enough.
21207
  if (is_made_of_eight_digits_fast(p)) {
21208
    i = i * 100000000 + parse_eight_digits_unrolled(p);
21209
    p += 8;
21210
  }
21211
#endif // SIMDJSON_SWAR_NUMBER_PARSING
21212
#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
21213
  // Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
21214
  if (parse_digit(*p, i)) { ++p; }
21215
  while (parse_digit(*p, i)) { p++; }
21216
  exponent = first_after_period - p;
21217
  // Decimal without digits (123.) is illegal
21218
  if (exponent == 0) {
21219
    return INVALID_NUMBER(src);
21220
  }
21221
  return SUCCESS;
21222
}
21223
21224
simdjson_inline error_code parse_exponent(simdjson_unused const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
21225
  // Exp Sign: -123.456e[-]78
21226
  bool neg_exp = ('-' == *p);
21227
  if (neg_exp || '+' == *p) { p++; } // Skip + as well
21228
21229
  // Exponent: -123.456e-[78]
21230
  auto start_exp = p;
21231
  int64_t exp_number = 0;
21232
  while (parse_digit(*p, exp_number)) { ++p; }
21233
  // It is possible for parse_digit to overflow.
21234
  // In particular, it could overflow to INT64_MIN, and we cannot do - INT64_MIN.
21235
  // Thus we *must* check for possible overflow before we negate exp_number.
21236
21237
  // Performance notes: it may seem like combining the two "simdjson_unlikely checks" below into
21238
  // a single simdjson_unlikely path would be faster. The reasoning is sound, but the compiler may
21239
  // not oblige and may, in fact, generate two distinct paths in any case. It might be
21240
  // possible to do uint64_t(p - start_exp - 1) >= 18 but it could end up trading off
21241
  // instructions for a simdjson_likely branch, an unconclusive gain.
21242
21243
  // If there were no digits, it's an error.
21244
  if (simdjson_unlikely(p == start_exp)) {
21245
    return INVALID_NUMBER(src);
21246
  }
21247
  // We have a valid positive exponent in exp_number at this point, except that
21248
  // it may have overflowed.
21249
21250
  // If there were more than 18 digits, we may have overflowed the integer. We have to do
21251
  // something!!!!
21252
  if (simdjson_unlikely(p > start_exp+18)) {
21253
    // Skip leading zeroes: 1e000000000000000000001 is technically valid and does not overflow
21254
    while (*start_exp == '0') { start_exp++; }
21255
    // 19 digits could overflow int64_t and is kind of absurd anyway. We don't
21256
    // support exponents smaller than -999,999,999,999,999,999 and bigger
21257
    // than 999,999,999,999,999,999.
21258
    // We can truncate.
21259
    // Note that 999999999999999999 is assuredly too large. The maximal ieee64 value before
21260
    // infinity is ~1.8e308. The smallest subnormal is ~5e-324. So, actually, we could
21261
    // truncate at 324.
21262
    // Note that there is no reason to fail per se at this point in time.
21263
    // E.g., 0e999999999999999999999 is a fine number.
21264
    if (p > start_exp+18) { exp_number = 999999999999999999; }
21265
  }
21266
  // At this point, we know that exp_number is a sane, positive, signed integer.
21267
  // It is <= 999,999,999,999,999,999. As long as 'exponent' is in
21268
  // [-8223372036854775808, 8223372036854775808], we won't overflow. Because 'exponent'
21269
  // is bounded in magnitude by the size of the JSON input, we are fine in this universe.
21270
  // To sum it up: the next line should never overflow.
21271
  exponent += (neg_exp ? -exp_number : exp_number);
21272
  return SUCCESS;
21273
}
21274
21275
simdjson_inline bool check_if_integer(const uint8_t *const src, size_t max_length) {
21276
  const uint8_t *const srcend = src + max_length;
21277
  bool negative = (*src == '-'); // we can always read at least one character after the '-'
21278
  const uint8_t *p = src + uint8_t(negative);
21279
  if(p == srcend) { return false; }
21280
  if(*p == '0') {
21281
    ++p;
21282
    if(p == srcend) { return true; }
21283
    if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
21284
    return true;
21285
  }
21286
  while(p != srcend && is_digit(*p)) { ++p; }
21287
  if(p == srcend) { return true; }
21288
  if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
21289
  return true;
21290
}
21291
21292
simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
21293
  // It is possible that the integer had an overflow.
21294
  // We have to handle the case where we have 0.0000somenumber.
21295
  const uint8_t *start = start_digits;
21296
  while ((*start == '0') || (*start == '.')) { ++start; }
21297
  // we over-decrement by one when there is a '.'
21298
  return digit_count - size_t(start - start_digits);
21299
}
21300
21301
} // unnamed namespace
21302
21303
/** @private */
21304
static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
21305
  if (parse_float_fallback(src, answer)) {
21306
    return SUCCESS;
21307
  }
21308
  return INVALID_NUMBER(src);
21309
}
21310
21311
/** @private */
21312
template<typename W>
21313
simdjson_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
21314
  // If we frequently had to deal with long strings of digits,
21315
  // we could extend our code by using a 128-bit integer instead
21316
  // of a 64-bit integer. However, this is uncommon in practice.
21317
  //
21318
  // 9999999999999999999 < 2**64 so we can accommodate 19 digits.
21319
  // If we have a decimal separator, then digit_count - 1 is the number of digits, but we
21320
  // may not have a decimal separator!
21321
  if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
21322
    // Ok, chances are good that we had an overflow!
21323
    // this is almost never going to get called!!!
21324
    // we start anew, going slowly!!!
21325
    // This will happen in the following examples:
21326
    // 10000000000000000000000000000000000000000000e+308
21327
    // 3.1415926535897932384626433832795028841971693993751
21328
    //
21329
    // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
21330
    // reference to it, it would force it to be stored in memory, preventing the compiler from
21331
    // picking it apart and putting into registers. i.e. if we pass it as reference,
21332
    // it gets slow.
21333
    double d;
21334
    error_code error = slow_float_parsing(src, &d);
21335
    writer.append_double(d);
21336
    return error;
21337
  }
21338
  // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
21339
  // way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331
21340
  // To future reader: we'd love if someone found a better way, or at least could explain this result!
21341
  if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
21342
    //
21343
    // Important: smallest_power is such that it leads to a zero value.
21344
    // Observe that 18446744073709551615e-343 == 0, i.e. (2**64 - 1) e -343 is zero
21345
    // so something x 10^-343 goes to zero, but not so with  something x 10^-342.
21346
    static_assert(simdjson::internal::smallest_power <= -342, "smallest_power is not small enough");
21347
    //
21348
    if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
21349
      // E.g. Parse "-0.0e-999" into the same value as "-0.0". See https://en.wikipedia.org/wiki/Signed_zero
21350
      WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
21351
      return SUCCESS;
21352
    } else { // (exponent > largest_power) and (i != 0)
21353
      // We have, for sure, an infinite value and simdjson refuses to parse infinite values.
21354
      return INVALID_NUMBER(src);
21355
    }
21356
  }
21357
  double d;
21358
  if (!compute_float_64(exponent, i, negative, d)) {
21359
    // we are almost never going to get here.
21360
    if (!parse_float_fallback(src, &d)) { return INVALID_NUMBER(src); }
21361
  }
21362
  WRITE_DOUBLE(d, src, writer);
21363
  return SUCCESS;
21364
}
21365
21366
// parse the number at src
21367
// define JSON_TEST_NUMBERS for unit testing
21368
//
21369
// It is assumed that the number is followed by a structural ({,},],[) character
21370
// or a white space character. If that is not the case (e.g., when the JSON
21371
// document is made of a single number), then it is necessary to copy the
21372
// content and append a space before calling this function.
21373
//
21374
// Our objective is accurate parsing (ULP of 0) at high speed.
21375
template<typename W>
21376
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer);
21377
21378
// for performance analysis, it is sometimes  useful to skip parsing
21379
#ifdef SIMDJSON_SKIPNUMBERPARSING
21380
21381
template<typename W>
21382
simdjson_inline error_code parse_number(const uint8_t *const, W &writer) {
21383
  writer.append_s64(0);        // always write zero
21384
  return SUCCESS;              // always succeeds
21385
}
21386
21387
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
21388
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
21389
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
21390
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept { return 0; }
21391
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t * const src) noexcept { return 0; }
21392
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * const src) noexcept { return 0; }
21393
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept  { return false; }
21394
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept  { return false; }
21395
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept { return number_type::signed_integer; }
21396
#else
21397
21398
// parse the number at src
21399
// define JSON_TEST_NUMBERS for unit testing
21400
//
21401
// It is assumed that the number is followed by a structural ({,},],[) character
21402
// or a white space character. If that is not the case (e.g., when the JSON
21403
// document is made of a single number), then it is necessary to copy the
21404
// content and append a space before calling this function.
21405
//
21406
// Our objective is accurate parsing (ULP of 0) at high speed.
21407
template<typename W>
21408
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) {
21409
21410
  //
21411
  // Check for minus sign
21412
  //
21413
  bool negative = (*src == '-');
21414
  const uint8_t *p = src + uint8_t(negative);
21415
21416
  //
21417
  // Parse the integer part.
21418
  //
21419
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
21420
  const uint8_t *const start_digits = p;
21421
  uint64_t i = 0;
21422
  while (parse_digit(*p, i)) { p++; }
21423
21424
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
21425
  // Optimization note: size_t is expected to be unsigned.
21426
  size_t digit_count = size_t(p - start_digits);
21427
  if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
21428
21429
  //
21430
  // Handle floats if there is a . or e (or both)
21431
  //
21432
  int64_t exponent = 0;
21433
  bool is_float = false;
21434
  if ('.' == *p) {
21435
    is_float = true;
21436
    ++p;
21437
    SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
21438
    digit_count = int(p - start_digits); // used later to guard against overflows
21439
  }
21440
  if (('e' == *p) || ('E' == *p)) {
21441
    is_float = true;
21442
    ++p;
21443
    SIMDJSON_TRY( parse_exponent(src, p, exponent) );
21444
  }
21445
  if (is_float) {
21446
    const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
21447
    SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
21448
    if (dirty_end) { return INVALID_NUMBER(src); }
21449
    return SUCCESS;
21450
  }
21451
21452
  // The longest negative 64-bit number is 19 digits.
21453
  // The longest positive 64-bit number is 20 digits.
21454
  // We do it this way so we don't trigger this branch unless we must.
21455
  size_t longest_digit_count = negative ? 19 : 20;
21456
  if (digit_count > longest_digit_count) { return BIGINT_NUMBER(src); }
21457
  if (digit_count == longest_digit_count) {
21458
    if (negative) {
21459
      // Anything negative above INT64_MAX+1 is invalid
21460
      if (i > uint64_t(INT64_MAX)+1) { return BIGINT_NUMBER(src);  }
21461
      WRITE_INTEGER(~i+1, src, writer);
21462
      if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
21463
      return SUCCESS;
21464
    // Positive overflow check:
21465
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
21466
    //   biggest uint64_t.
21467
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
21468
    //   If we got here, it's a 20 digit number starting with the digit "1".
21469
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
21470
    //   than 1,553,255,926,290,448,384.
21471
    // - That is smaller than the smallest possible 20-digit number the user could write:
21472
    //   10,000,000,000,000,000,000.
21473
    // - Therefore, if the number is positive and lower than that, it's overflow.
21474
    // - The value we are looking at is less than or equal to INT64_MAX.
21475
    //
21476
    }  else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
21477
  }
21478
21479
  // Write unsigned if it does not fit in a signed integer.
21480
  if (i > uint64_t(INT64_MAX)) {
21481
    WRITE_UNSIGNED(i, src, writer);
21482
  } else {
21483
    WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
21484
  }
21485
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
21486
  return SUCCESS;
21487
}
21488
21489
// Inlineable functions
21490
namespace {
21491
21492
// This table can be used to characterize the final character of an integer
21493
// string. For JSON structural character and allowable white space characters,
21494
// we return SUCCESS. For 'e', '.' and 'E', we return INCORRECT_TYPE. Otherwise
21495
// we return NUMBER_ERROR.
21496
// Optimization note: we could easily reduce the size of the table by half (to 128)
21497
// at the cost of an extra branch.
21498
// Optimization note: we want the values to use at most 8 bits (not, e.g., 32 bits):
21499
static_assert(error_code(uint8_t(NUMBER_ERROR))== NUMBER_ERROR, "bad NUMBER_ERROR cast");
21500
static_assert(error_code(uint8_t(SUCCESS))== SUCCESS, "bad NUMBER_ERROR cast");
21501
static_assert(error_code(uint8_t(INCORRECT_TYPE))== INCORRECT_TYPE, "bad NUMBER_ERROR cast");
21502
21503
const uint8_t integer_string_finisher[256] = {
21504
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21505
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
21506
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
21507
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21508
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21509
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21510
    NUMBER_ERROR, NUMBER_ERROR,   SUCCESS,      NUMBER_ERROR, NUMBER_ERROR,
21511
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21512
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
21513
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21514
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21515
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
21516
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21517
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, INCORRECT_TYPE,
21518
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21519
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21520
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21521
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21522
    NUMBER_ERROR, SUCCESS,        NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
21523
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21524
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21525
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21526
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21527
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21528
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
21529
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21530
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21531
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21532
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21533
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21534
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21535
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21536
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21537
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21538
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21539
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21540
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21541
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21542
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21543
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21544
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21545
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21546
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21547
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21548
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21549
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21550
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21551
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21552
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21553
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21554
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
21555
    NUMBER_ERROR};
21556
21557
// Parse any number from 0 to 18,446,744,073,709,551,615
21558
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept {
21559
  const uint8_t *p = src;
21560
  //
21561
  // Parse the integer part.
21562
  //
21563
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
21564
  const uint8_t *const start_digits = p;
21565
  uint64_t i = 0;
21566
  while (parse_digit(*p, i)) { p++; }
21567
21568
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
21569
  // Optimization note: size_t is expected to be unsigned.
21570
  size_t digit_count = size_t(p - start_digits);
21571
  // The longest positive 64-bit number is 20 digits.
21572
  // We do it this way so we don't trigger this branch unless we must.
21573
  // Optimization note: the compiler can probably merge
21574
  // ((digit_count == 0) || (digit_count > 20))
21575
  // into a single  branch since digit_count is unsigned.
21576
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
21577
  // Here digit_count > 0.
21578
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
21579
  // We can do the following...
21580
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
21581
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
21582
  // }
21583
  // as a single table lookup:
21584
  if (integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
21585
21586
  if (digit_count == 20) {
21587
    // Positive overflow check:
21588
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
21589
    //   biggest uint64_t.
21590
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
21591
    //   If we got here, it's a 20 digit number starting with the digit "1".
21592
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
21593
    //   than 1,553,255,926,290,448,384.
21594
    // - That is smaller than the smallest possible 20-digit number the user could write:
21595
    //   10,000,000,000,000,000,000.
21596
    // - Therefore, if the number is positive and lower than that, it's overflow.
21597
    // - The value we are looking at is less than or equal to INT64_MAX.
21598
    //
21599
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
21600
  }
21601
21602
  return i;
21603
}
21604
21605
21606
// Parse any number from 0 to 18,446,744,073,709,551,615
21607
// Never read at src_end or beyond
21608
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src, const uint8_t * const src_end) noexcept {
21609
  const uint8_t *p = src;
21610
  //
21611
  // Parse the integer part.
21612
  //
21613
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
21614
  const uint8_t *const start_digits = p;
21615
  uint64_t i = 0;
21616
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
21617
21618
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
21619
  // Optimization note: size_t is expected to be unsigned.
21620
  size_t digit_count = size_t(p - start_digits);
21621
  // The longest positive 64-bit number is 20 digits.
21622
  // We do it this way so we don't trigger this branch unless we must.
21623
  // Optimization note: the compiler can probably merge
21624
  // ((digit_count == 0) || (digit_count > 20))
21625
  // into a single  branch since digit_count is unsigned.
21626
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
21627
  // Here digit_count > 0.
21628
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
21629
  // We can do the following...
21630
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
21631
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
21632
  // }
21633
  // as a single table lookup:
21634
  if ((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
21635
21636
  if (digit_count == 20) {
21637
    // Positive overflow check:
21638
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
21639
    //   biggest uint64_t.
21640
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
21641
    //   If we got here, it's a 20 digit number starting with the digit "1".
21642
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
21643
    //   than 1,553,255,926,290,448,384.
21644
    // - That is smaller than the smallest possible 20-digit number the user could write:
21645
    //   10,000,000,000,000,000,000.
21646
    // - Therefore, if the number is positive and lower than that, it's overflow.
21647
    // - The value we are looking at is less than or equal to INT64_MAX.
21648
    //
21649
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
21650
  }
21651
21652
  return i;
21653
}
21654
21655
// Parse any number from 0 to 18,446,744,073,709,551,615
21656
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept {
21657
  const uint8_t *p = src + 1;
21658
  //
21659
  // Parse the integer part.
21660
  //
21661
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
21662
  const uint8_t *const start_digits = p;
21663
  uint64_t i = 0;
21664
  while (parse_digit(*p, i)) { p++; }
21665
21666
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
21667
  // Optimization note: size_t is expected to be unsigned.
21668
  size_t digit_count = size_t(p - start_digits);
21669
  // The longest positive 64-bit number is 20 digits.
21670
  // We do it this way so we don't trigger this branch unless we must.
21671
  // Optimization note: the compiler can probably merge
21672
  // ((digit_count == 0) || (digit_count > 20))
21673
  // into a single  branch since digit_count is unsigned.
21674
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
21675
  // Here digit_count > 0.
21676
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
21677
  // We can do the following...
21678
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
21679
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
21680
  // }
21681
  // as a single table lookup:
21682
  if (*p != '"') { return NUMBER_ERROR; }
21683
21684
  if (digit_count == 20) {
21685
    // Positive overflow check:
21686
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
21687
    //   biggest uint64_t.
21688
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
21689
    //   If we got here, it's a 20 digit number starting with the digit "1".
21690
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
21691
    //   than 1,553,255,926,290,448,384.
21692
    // - That is smaller than the smallest possible 20-digit number the user could write:
21693
    //   10,000,000,000,000,000,000.
21694
    // - Therefore, if the number is positive and lower than that, it's overflow.
21695
    // - The value we are looking at is less than or equal to INT64_MAX.
21696
    //
21697
    // Note: we use src[1] and not src[0] because src[0] is the quote character in this
21698
    // instance.
21699
    if (src[1] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
21700
  }
21701
21702
  return i;
21703
}
21704
21705
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
21706
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
21707
  //
21708
  // Check for minus sign
21709
  //
21710
  bool negative = (*src == '-');
21711
  const uint8_t *p = src + uint8_t(negative);
21712
21713
  //
21714
  // Parse the integer part.
21715
  //
21716
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
21717
  const uint8_t *const start_digits = p;
21718
  uint64_t i = 0;
21719
  while (parse_digit(*p, i)) { p++; }
21720
21721
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
21722
  // Optimization note: size_t is expected to be unsigned.
21723
  size_t digit_count = size_t(p - start_digits);
21724
  // We go from
21725
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
21726
  // so we can never represent numbers that have more than 19 digits.
21727
  size_t longest_digit_count = 19;
21728
  // Optimization note: the compiler can probably merge
21729
  // ((digit_count == 0) || (digit_count > longest_digit_count))
21730
  // into a single  branch since digit_count is unsigned.
21731
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
21732
  // Here digit_count > 0.
21733
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
21734
  // We can do the following...
21735
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
21736
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
21737
  // }
21738
  // as a single table lookup:
21739
  if(integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
21740
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
21741
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
21742
  // so cheap that we might as well always make it.
21743
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
21744
  return negative ? (~i+1) : i;
21745
}
21746
21747
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
21748
// Never read at src_end or beyond
21749
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src, const uint8_t * const src_end) noexcept {
21750
  //
21751
  // Check for minus sign
21752
  //
21753
  if(src == src_end) { return NUMBER_ERROR; }
21754
  bool negative = (*src == '-');
21755
  const uint8_t *p = src + uint8_t(negative);
21756
21757
  //
21758
  // Parse the integer part.
21759
  //
21760
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
21761
  const uint8_t *const start_digits = p;
21762
  uint64_t i = 0;
21763
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
21764
21765
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
21766
  // Optimization note: size_t is expected to be unsigned.
21767
  size_t digit_count = size_t(p - start_digits);
21768
  // We go from
21769
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
21770
  // so we can never represent numbers that have more than 19 digits.
21771
  size_t longest_digit_count = 19;
21772
  // Optimization note: the compiler can probably merge
21773
  // ((digit_count == 0) || (digit_count > longest_digit_count))
21774
  // into a single  branch since digit_count is unsigned.
21775
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
21776
  // Here digit_count > 0.
21777
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
21778
  // We can do the following...
21779
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
21780
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
21781
  // }
21782
  // as a single table lookup:
21783
  if((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
21784
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
21785
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
21786
  // so cheap that we might as well always make it.
21787
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
21788
  return negative ? (~i+1) : i;
21789
}
21790
21791
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
21792
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t *src) noexcept {
21793
  //
21794
  // Check for minus sign
21795
  //
21796
  bool negative = (*(src + 1) == '-');
21797
  src += uint8_t(negative) + 1;
21798
21799
  //
21800
  // Parse the integer part.
21801
  //
21802
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
21803
  const uint8_t *const start_digits = src;
21804
  uint64_t i = 0;
21805
  while (parse_digit(*src, i)) { src++; }
21806
21807
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
21808
  // Optimization note: size_t is expected to be unsigned.
21809
  size_t digit_count = size_t(src - start_digits);
21810
  // We go from
21811
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
21812
  // so we can never represent numbers that have more than 19 digits.
21813
  size_t longest_digit_count = 19;
21814
  // Optimization note: the compiler can probably merge
21815
  // ((digit_count == 0) || (digit_count > longest_digit_count))
21816
  // into a single  branch since digit_count is unsigned.
21817
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
21818
  // Here digit_count > 0.
21819
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
21820
  // We can do the following...
21821
  // if (!jsoncharutils::is_structural_or_whitespace(*src)) {
21822
  //  return (*src == '.' || *src == 'e' || *src == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
21823
  // }
21824
  // as a single table lookup:
21825
  if(*src != '"') { return NUMBER_ERROR; }
21826
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
21827
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
21828
  // so cheap that we might as well always make it.
21829
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
21830
  return negative ? (~i+1) : i;
21831
}
21832
21833
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
21834
  //
21835
  // Check for minus sign
21836
  //
21837
  bool negative = (*src == '-');
21838
  src += uint8_t(negative);
21839
21840
  //
21841
  // Parse the integer part.
21842
  //
21843
  uint64_t i = 0;
21844
  const uint8_t *p = src;
21845
  p += parse_digit(*p, i);
21846
  bool leading_zero = (i == 0);
21847
  while (parse_digit(*p, i)) { p++; }
21848
  // no integer digits, or 0123 (zero must be solo)
21849
  if ( p == src ) { return INCORRECT_TYPE; }
21850
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
21851
21852
  //
21853
  // Parse the decimal part.
21854
  //
21855
  int64_t exponent = 0;
21856
  bool overflow;
21857
  if (simdjson_likely(*p == '.')) {
21858
    p++;
21859
    const uint8_t *start_decimal_digits = p;
21860
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
21861
    p++;
21862
    while (parse_digit(*p, i)) { p++; }
21863
    exponent = -(p - start_decimal_digits);
21864
21865
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
21866
    overflow = p-src-1 > 19;
21867
    if (simdjson_unlikely(overflow && leading_zero)) {
21868
      // Skip leading 0.00000 and see if it still overflows
21869
      const uint8_t *start_digits = src + 2;
21870
      while (*start_digits == '0') { start_digits++; }
21871
      overflow = p-start_digits > 19;
21872
    }
21873
  } else {
21874
    overflow = p-src > 19;
21875
  }
21876
21877
  //
21878
  // Parse the exponent
21879
  //
21880
  if (*p == 'e' || *p == 'E') {
21881
    p++;
21882
    bool exp_neg = *p == '-';
21883
    p += exp_neg || *p == '+';
21884
21885
    uint64_t exp = 0;
21886
    const uint8_t *start_exp_digits = p;
21887
    while (parse_digit(*p, exp)) { p++; }
21888
    // no exp digits, or 20+ exp digits
21889
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
21890
21891
    exponent += exp_neg ? 0-exp : exp;
21892
  }
21893
21894
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
21895
21896
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
21897
21898
  //
21899
  // Assemble (or slow-parse) the float
21900
  //
21901
  double d;
21902
  if (simdjson_likely(!overflow)) {
21903
    if (compute_float_64(exponent, i, negative, d)) { return d; }
21904
  }
21905
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
21906
    return NUMBER_ERROR;
21907
  }
21908
  return d;
21909
}
21910
21911
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept {
21912
  return (*src == '-');
21913
}
21914
21915
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept {
21916
  bool negative = (*src == '-');
21917
  src += uint8_t(negative);
21918
  const uint8_t *p = src;
21919
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
21920
  if ( p == src ) { return NUMBER_ERROR; }
21921
  if (jsoncharutils::is_structural_or_whitespace(*p)) { return true; }
21922
  return false;
21923
}
21924
21925
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept {
21926
  bool negative = (*src == '-');
21927
  src += uint8_t(negative);
21928
  const uint8_t *p = src;
21929
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
21930
  size_t digit_count = size_t(p - src);
21931
  if ( p == src ) { return NUMBER_ERROR; }
21932
  if (jsoncharutils::is_structural_or_whitespace(*p)) {
21933
    static const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
21934
    // We have an integer.
21935
    if(simdjson_unlikely(digit_count > 20)) {
21936
      return number_type::big_integer;
21937
    }
21938
    // If the number is negative and valid, it must be a signed integer.
21939
    if(negative) {
21940
      if (simdjson_unlikely(digit_count > 19)) return number_type::big_integer;
21941
      if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) {
21942
        return number_type::big_integer;
21943
      }
21944
      return number_type::signed_integer;
21945
    }
21946
    // Let us check if we have a big integer (>=2**64).
21947
    static const uint8_t * two_to_sixtyfour = reinterpret_cast<const uint8_t *>("18446744073709551616");
21948
    if((digit_count > 20) || (digit_count == 20 && memcmp(src, two_to_sixtyfour, 20) >= 0)) {
21949
      return number_type::big_integer;
21950
    }
21951
    // The number is positive and smaller than 18446744073709551616 (or 2**64).
21952
    // We want values larger or equal to 9223372036854775808 to be unsigned
21953
    // integers, and the other values to be signed integers.
21954
    if((digit_count == 20) || (digit_count >= 19 && memcmp(src, smaller_big_integer, 19) >= 0)) {
21955
      return number_type::unsigned_integer;
21956
    }
21957
    return number_type::signed_integer;
21958
  }
21959
  // Hopefully, we have 'e' or 'E' or '.'.
21960
  return number_type::floating_point_number;
21961
}
21962
21963
// Never read at src_end or beyond
21964
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
21965
  if(src == src_end) { return NUMBER_ERROR; }
21966
  //
21967
  // Check for minus sign
21968
  //
21969
  bool negative = (*src == '-');
21970
  src += uint8_t(negative);
21971
21972
  //
21973
  // Parse the integer part.
21974
  //
21975
  uint64_t i = 0;
21976
  const uint8_t *p = src;
21977
  if(p == src_end) { return NUMBER_ERROR; }
21978
  p += parse_digit(*p, i);
21979
  bool leading_zero = (i == 0);
21980
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
21981
  // no integer digits, or 0123 (zero must be solo)
21982
  if ( p == src ) { return INCORRECT_TYPE; }
21983
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
21984
21985
  //
21986
  // Parse the decimal part.
21987
  //
21988
  int64_t exponent = 0;
21989
  bool overflow;
21990
  if (simdjson_likely((p != src_end) && (*p == '.'))) {
21991
    p++;
21992
    const uint8_t *start_decimal_digits = p;
21993
    if ((p == src_end) || !parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
21994
    p++;
21995
    while ((p != src_end) && parse_digit(*p, i)) { p++; }
21996
    exponent = -(p - start_decimal_digits);
21997
21998
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
21999
    overflow = p-src-1 > 19;
22000
    if (simdjson_unlikely(overflow && leading_zero)) {
22001
      // Skip leading 0.00000 and see if it still overflows
22002
      const uint8_t *start_digits = src + 2;
22003
      while (*start_digits == '0') { start_digits++; }
22004
      overflow = start_digits-src > 19;
22005
    }
22006
  } else {
22007
    overflow = p-src > 19;
22008
  }
22009
22010
  //
22011
  // Parse the exponent
22012
  //
22013
  if ((p != src_end) && (*p == 'e' || *p == 'E')) {
22014
    p++;
22015
    if(p == src_end) { return NUMBER_ERROR; }
22016
    bool exp_neg = *p == '-';
22017
    p += exp_neg || *p == '+';
22018
22019
    uint64_t exp = 0;
22020
    const uint8_t *start_exp_digits = p;
22021
    while ((p != src_end) && parse_digit(*p, exp)) { p++; }
22022
    // no exp digits, or 20+ exp digits
22023
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
22024
22025
    exponent += exp_neg ? 0-exp : exp;
22026
  }
22027
22028
  if ((p != src_end) && jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
22029
22030
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
22031
22032
  //
22033
  // Assemble (or slow-parse) the float
22034
  //
22035
  double d;
22036
  if (simdjson_likely(!overflow)) {
22037
    if (compute_float_64(exponent, i, negative, d)) { return d; }
22038
  }
22039
  if (!parse_float_fallback(src - uint8_t(negative), src_end, &d)) {
22040
    return NUMBER_ERROR;
22041
  }
22042
  return d;
22043
}
22044
22045
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * src) noexcept {
22046
  //
22047
  // Check for minus sign
22048
  //
22049
  bool negative = (*(src + 1) == '-');
22050
  src += uint8_t(negative) + 1;
22051
22052
  //
22053
  // Parse the integer part.
22054
  //
22055
  uint64_t i = 0;
22056
  const uint8_t *p = src;
22057
  p += parse_digit(*p, i);
22058
  bool leading_zero = (i == 0);
22059
  while (parse_digit(*p, i)) { p++; }
22060
  // no integer digits, or 0123 (zero must be solo)
22061
  if ( p == src ) { return INCORRECT_TYPE; }
22062
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
22063
22064
  //
22065
  // Parse the decimal part.
22066
  //
22067
  int64_t exponent = 0;
22068
  bool overflow;
22069
  if (simdjson_likely(*p == '.')) {
22070
    p++;
22071
    const uint8_t *start_decimal_digits = p;
22072
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
22073
    p++;
22074
    while (parse_digit(*p, i)) { p++; }
22075
    exponent = -(p - start_decimal_digits);
22076
22077
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
22078
    overflow = p-src-1 > 19;
22079
    if (simdjson_unlikely(overflow && leading_zero)) {
22080
      // Skip leading 0.00000 and see if it still overflows
22081
      const uint8_t *start_digits = src + 2;
22082
      while (*start_digits == '0') { start_digits++; }
22083
      overflow = p-start_digits > 19;
22084
    }
22085
  } else {
22086
    overflow = p-src > 19;
22087
  }
22088
22089
  //
22090
  // Parse the exponent
22091
  //
22092
  if (*p == 'e' || *p == 'E') {
22093
    p++;
22094
    bool exp_neg = *p == '-';
22095
    p += exp_neg || *p == '+';
22096
22097
    uint64_t exp = 0;
22098
    const uint8_t *start_exp_digits = p;
22099
    while (parse_digit(*p, exp)) { p++; }
22100
    // no exp digits, or 20+ exp digits
22101
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
22102
22103
    exponent += exp_neg ? 0-exp : exp;
22104
  }
22105
22106
  if (*p != '"') { return NUMBER_ERROR; }
22107
22108
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
22109
22110
  //
22111
  // Assemble (or slow-parse) the float
22112
  //
22113
  double d;
22114
  if (simdjson_likely(!overflow)) {
22115
    if (compute_float_64(exponent, i, negative, d)) { return d; }
22116
  }
22117
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
22118
    return NUMBER_ERROR;
22119
  }
22120
  return d;
22121
}
22122
22123
} // unnamed namespace
22124
#endif // SIMDJSON_SKIPNUMBERPARSING
22125
22126
} // namespace numberparsing
22127
22128
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
22129
    switch (type) {
22130
        case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
22131
        case number_type::unsigned_integer: out << "unsigned integer in [9223372036854775808,18446744073709551616)"; break;
22132
        case number_type::floating_point_number: out << "floating-point number (binary64)"; break;
22133
        case number_type::big_integer: out << "big integer"; break;
22134
        default: SIMDJSON_UNREACHABLE();
22135
    }
22136
    return out;
22137
}
22138
22139
} // namespace ppc64
22140
} // namespace simdjson
22141
22142
#endif // SIMDJSON_GENERIC_NUMBERPARSING_H
22143
/* end file simdjson/generic/numberparsing.h for ppc64 */
22144
22145
/* including simdjson/generic/implementation_simdjson_result_base-inl.h for ppc64: #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
22146
/* begin file simdjson/generic/implementation_simdjson_result_base-inl.h for ppc64 */
22147
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
22148
22149
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22150
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H */
22151
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
22152
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
22153
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22154
22155
namespace simdjson {
22156
namespace ppc64 {
22157
22158
//
22159
// internal::implementation_simdjson_result_base<T> inline implementation
22160
//
22161
22162
template<typename T>
22163
simdjson_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
22164
  error = this->second;
22165
  if (!error) {
22166
    value = std::forward<implementation_simdjson_result_base<T>>(*this).first;
22167
  }
22168
}
22169
22170
template<typename T>
22171
simdjson_warn_unused simdjson_inline error_code implementation_simdjson_result_base<T>::get(T &value) && noexcept {
22172
  error_code error;
22173
  std::forward<implementation_simdjson_result_base<T>>(*this).tie(value, error);
22174
  return error;
22175
}
22176
22177
template<typename T>
22178
simdjson_inline error_code implementation_simdjson_result_base<T>::error() const noexcept {
22179
  return this->second;
22180
}
22181
22182
#if SIMDJSON_EXCEPTIONS
22183
22184
template<typename T>
22185
simdjson_inline T& implementation_simdjson_result_base<T>::value() & noexcept(false) {
22186
  if (error()) { throw simdjson_error(error()); }
22187
  return this->first;
22188
}
22189
22190
template<typename T>
22191
simdjson_inline T&& implementation_simdjson_result_base<T>::value() && noexcept(false) {
22192
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
22193
}
22194
22195
template<typename T>
22196
simdjson_inline T&& implementation_simdjson_result_base<T>::take_value() && noexcept(false) {
22197
  if (error()) { throw simdjson_error(error()); }
22198
  return std::forward<T>(this->first);
22199
}
22200
22201
template<typename T>
22202
simdjson_inline implementation_simdjson_result_base<T>::operator T&&() && noexcept(false) {
22203
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
22204
}
22205
22206
#endif // SIMDJSON_EXCEPTIONS
22207
22208
template<typename T>
22209
simdjson_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
22210
  return this->first;
22211
}
22212
22213
template<typename T>
22214
simdjson_inline T& implementation_simdjson_result_base<T>::value_unsafe() & noexcept {
22215
  return this->first;
22216
}
22217
22218
template<typename T>
22219
simdjson_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
22220
  return std::forward<T>(this->first);
22221
}
22222
22223
template<typename T>
22224
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
22225
    : first{std::forward<T>(value)}, second{error} {}
22226
template<typename T>
22227
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(error_code error) noexcept
22228
    : implementation_simdjson_result_base(T{}, error) {}
22229
template<typename T>
22230
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
22231
    : implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
22232
22233
} // namespace ppc64
22234
} // namespace simdjson
22235
22236
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
22237
/* end file simdjson/generic/implementation_simdjson_result_base-inl.h for ppc64 */
22238
/* end file simdjson/generic/amalgamated.h for ppc64 */
22239
/* including simdjson/ppc64/end.h: #include "simdjson/ppc64/end.h" */
22240
/* begin file simdjson/ppc64/end.h */
22241
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22242
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
22243
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22244
22245
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
22246
/* undefining SIMDJSON_IMPLEMENTATION from "ppc64" */
22247
#undef SIMDJSON_IMPLEMENTATION
22248
/* end file simdjson/ppc64/end.h */
22249
22250
#endif // SIMDJSON_PPC64_H
22251
/* end file simdjson/ppc64.h */
22252
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
22253
/* including simdjson/westmere.h: #include "simdjson/westmere.h" */
22254
/* begin file simdjson/westmere.h */
22255
#ifndef SIMDJSON_WESTMERE_H
22256
#define SIMDJSON_WESTMERE_H
22257
22258
/* including simdjson/westmere/begin.h: #include "simdjson/westmere/begin.h" */
22259
/* begin file simdjson/westmere/begin.h */
22260
/* defining SIMDJSON_IMPLEMENTATION to "westmere" */
22261
#define SIMDJSON_IMPLEMENTATION westmere
22262
/* including simdjson/westmere/base.h: #include "simdjson/westmere/base.h" */
22263
/* begin file simdjson/westmere/base.h */
22264
#ifndef SIMDJSON_WESTMERE_BASE_H
22265
#define SIMDJSON_WESTMERE_BASE_H
22266
22267
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22268
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
22269
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22270
22271
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_WESTMERE
22272
namespace simdjson {
22273
/**
22274
 * Implementation for Westmere (Intel SSE4.2).
22275
 */
22276
namespace westmere {
22277
22278
class implementation;
22279
22280
namespace {
22281
namespace simd {
22282
22283
template <typename T> struct simd8;
22284
template <typename T> struct simd8x64;
22285
22286
} // namespace simd
22287
} // unnamed namespace
22288
22289
} // namespace westmere
22290
} // namespace simdjson
22291
22292
#endif // SIMDJSON_WESTMERE_BASE_H
22293
/* end file simdjson/westmere/base.h */
22294
/* including simdjson/westmere/intrinsics.h: #include "simdjson/westmere/intrinsics.h" */
22295
/* begin file simdjson/westmere/intrinsics.h */
22296
#ifndef SIMDJSON_WESTMERE_INTRINSICS_H
22297
#define SIMDJSON_WESTMERE_INTRINSICS_H
22298
22299
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22300
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
22301
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22302
22303
#if SIMDJSON_VISUAL_STUDIO
22304
// under clang within visual studio, this will include <x86intrin.h>
22305
#include <intrin.h> // visual studio or clang
22306
#else
22307
#include <x86intrin.h> // elsewhere
22308
#endif // SIMDJSON_VISUAL_STUDIO
22309
22310
22311
#if SIMDJSON_CLANG_VISUAL_STUDIO
22312
/**
22313
 * You are not supposed, normally, to include these
22314
 * headers directly. Instead you should either include intrin.h
22315
 * or x86intrin.h. However, when compiling with clang
22316
 * under Windows (i.e., when _MSC_VER is set), these headers
22317
 * only get included *if* the corresponding features are detected
22318
 * from macros:
22319
 */
22320
#include <smmintrin.h>  // for _mm_alignr_epi8
22321
#include <wmmintrin.h>  // for  _mm_clmulepi64_si128
22322
#endif
22323
22324
static_assert(sizeof(__m128i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for westmere");
22325
22326
#endif // SIMDJSON_WESTMERE_INTRINSICS_H
22327
/* end file simdjson/westmere/intrinsics.h */
22328
22329
#if !SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
22330
SIMDJSON_TARGET_REGION("sse4.2,pclmul,popcnt")
22331
#endif
22332
22333
/* including simdjson/westmere/bitmanipulation.h: #include "simdjson/westmere/bitmanipulation.h" */
22334
/* begin file simdjson/westmere/bitmanipulation.h */
22335
#ifndef SIMDJSON_WESTMERE_BITMANIPULATION_H
22336
#define SIMDJSON_WESTMERE_BITMANIPULATION_H
22337
22338
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22339
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
22340
/* amalgamation skipped (editor-only): #include "simdjson/westmere/intrinsics.h" */
22341
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22342
22343
namespace simdjson {
22344
namespace westmere {
22345
namespace {
22346
22347
// We sometimes call trailing_zero on inputs that are zero,
22348
// but the algorithms do not end up using the returned value.
22349
// Sadly, sanitizers are not smart enough to figure it out.
22350
SIMDJSON_NO_SANITIZE_UNDEFINED
22351
// This function can be used safely even if not all bytes have been
22352
// initialized.
22353
// See issue https://github.com/simdjson/simdjson/issues/1965
22354
SIMDJSON_NO_SANITIZE_MEMORY
22355
simdjson_inline int trailing_zeroes(uint64_t input_num) {
22356
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22357
  unsigned long ret;
22358
  // Search the mask data from least significant bit (LSB)
22359
  // to the most significant bit (MSB) for a set bit (1).
22360
  _BitScanForward64(&ret, input_num);
22361
  return (int)ret;
22362
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
22363
  return __builtin_ctzll(input_num);
22364
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
22365
}
22366
22367
/* result might be undefined when input_num is zero */
22368
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
22369
  return input_num & (input_num-1);
22370
}
22371
22372
/* result might be undefined when input_num is zero */
22373
simdjson_inline int leading_zeroes(uint64_t input_num) {
22374
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22375
  unsigned long leading_zero = 0;
22376
  // Search the mask data from most significant bit (MSB)
22377
  // to least significant bit (LSB) for a set bit (1).
22378
  if (_BitScanReverse64(&leading_zero, input_num))
22379
    return (int)(63 - leading_zero);
22380
  else
22381
    return 64;
22382
#else
22383
  return __builtin_clzll(input_num);
22384
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
22385
}
22386
22387
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22388
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
22389
  // note: we do not support legacy 32-bit Windows in this kernel
22390
  return __popcnt64(input_num);// Visual Studio wants two underscores
22391
}
22392
#else
22393
simdjson_inline long long int count_ones(uint64_t input_num) {
22394
  return _popcnt64(input_num);
22395
}
22396
#endif
22397
22398
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
22399
                                uint64_t *result) {
22400
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22401
  return _addcarry_u64(0, value1, value2,
22402
                       reinterpret_cast<unsigned __int64 *>(result));
22403
#else
22404
  return __builtin_uaddll_overflow(value1, value2,
22405
                                   reinterpret_cast<unsigned long long *>(result));
22406
#endif
22407
}
22408
22409
} // unnamed namespace
22410
} // namespace westmere
22411
} // namespace simdjson
22412
22413
#endif // SIMDJSON_WESTMERE_BITMANIPULATION_H
22414
/* end file simdjson/westmere/bitmanipulation.h */
22415
/* including simdjson/westmere/bitmask.h: #include "simdjson/westmere/bitmask.h" */
22416
/* begin file simdjson/westmere/bitmask.h */
22417
#ifndef SIMDJSON_WESTMERE_BITMASK_H
22418
#define SIMDJSON_WESTMERE_BITMASK_H
22419
22420
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22421
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
22422
/* amalgamation skipped (editor-only): #include "simdjson/westmere/intrinsics.h" */
22423
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22424
22425
namespace simdjson {
22426
namespace westmere {
22427
namespace {
22428
22429
//
22430
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
22431
//
22432
// For example, prefix_xor(00100100) == 00011100
22433
//
22434
simdjson_inline uint64_t prefix_xor(const uint64_t bitmask) {
22435
  // There should be no such thing with a processing supporting avx2
22436
  // but not clmul.
22437
  __m128i all_ones = _mm_set1_epi8('\xFF');
22438
  __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, bitmask), all_ones, 0);
22439
  return _mm_cvtsi128_si64(result);
22440
}
22441
22442
} // unnamed namespace
22443
} // namespace westmere
22444
} // namespace simdjson
22445
22446
#endif // SIMDJSON_WESTMERE_BITMASK_H
22447
/* end file simdjson/westmere/bitmask.h */
22448
/* including simdjson/westmere/numberparsing_defs.h: #include "simdjson/westmere/numberparsing_defs.h" */
22449
/* begin file simdjson/westmere/numberparsing_defs.h */
22450
#ifndef SIMDJSON_WESTMERE_NUMBERPARSING_DEFS_H
22451
#define SIMDJSON_WESTMERE_NUMBERPARSING_DEFS_H
22452
22453
/* including simdjson/westmere/base.h: #include "simdjson/westmere/base.h" */
22454
/* begin file simdjson/westmere/base.h */
22455
#ifndef SIMDJSON_WESTMERE_BASE_H
22456
#define SIMDJSON_WESTMERE_BASE_H
22457
22458
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22459
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
22460
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22461
22462
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_WESTMERE
22463
namespace simdjson {
22464
/**
22465
 * Implementation for Westmere (Intel SSE4.2).
22466
 */
22467
namespace westmere {
22468
22469
class implementation;
22470
22471
namespace {
22472
namespace simd {
22473
22474
template <typename T> struct simd8;
22475
template <typename T> struct simd8x64;
22476
22477
} // namespace simd
22478
} // unnamed namespace
22479
22480
} // namespace westmere
22481
} // namespace simdjson
22482
22483
#endif // SIMDJSON_WESTMERE_BASE_H
22484
/* end file simdjson/westmere/base.h */
22485
/* including simdjson/westmere/intrinsics.h: #include "simdjson/westmere/intrinsics.h" */
22486
/* begin file simdjson/westmere/intrinsics.h */
22487
#ifndef SIMDJSON_WESTMERE_INTRINSICS_H
22488
#define SIMDJSON_WESTMERE_INTRINSICS_H
22489
22490
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22491
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
22492
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22493
22494
#if SIMDJSON_VISUAL_STUDIO
22495
// under clang within visual studio, this will include <x86intrin.h>
22496
#include <intrin.h> // visual studio or clang
22497
#else
22498
#include <x86intrin.h> // elsewhere
22499
#endif // SIMDJSON_VISUAL_STUDIO
22500
22501
22502
#if SIMDJSON_CLANG_VISUAL_STUDIO
22503
/**
22504
 * You are not supposed, normally, to include these
22505
 * headers directly. Instead you should either include intrin.h
22506
 * or x86intrin.h. However, when compiling with clang
22507
 * under Windows (i.e., when _MSC_VER is set), these headers
22508
 * only get included *if* the corresponding features are detected
22509
 * from macros:
22510
 */
22511
#include <smmintrin.h>  // for _mm_alignr_epi8
22512
#include <wmmintrin.h>  // for  _mm_clmulepi64_si128
22513
#endif
22514
22515
static_assert(sizeof(__m128i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for westmere");
22516
22517
#endif // SIMDJSON_WESTMERE_INTRINSICS_H
22518
/* end file simdjson/westmere/intrinsics.h */
22519
22520
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22521
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
22522
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22523
22524
namespace simdjson {
22525
namespace westmere {
22526
namespace numberparsing {
22527
22528
/** @private */
22529
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
22530
  // this actually computes *16* values so we are being wasteful.
22531
  const __m128i ascii0 = _mm_set1_epi8('0');
22532
  const __m128i mul_1_10 =
22533
      _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1);
22534
  const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1);
22535
  const __m128i mul_1_10000 =
22536
      _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1);
22537
  const __m128i input = _mm_sub_epi8(
22538
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0);
22539
  const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10);
22540
  const __m128i t2 = _mm_madd_epi16(t1, mul_1_100);
22541
  const __m128i t3 = _mm_packus_epi32(t2, t2);
22542
  const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000);
22543
  return _mm_cvtsi128_si32(
22544
      t4); // only captures the sum of the first 8 digits, drop the rest
22545
}
22546
22547
/** @private */
22548
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
22549
  internal::value128 answer;
22550
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
22551
#ifdef _M_ARM64
22552
  // ARM64 has native support for 64-bit multiplications, no need to emultate
22553
  answer.high = __umulh(value1, value2);
22554
  answer.low = value1 * value2;
22555
#else
22556
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
22557
#endif // _M_ARM64
22558
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
22559
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
22560
  answer.low = uint64_t(r);
22561
  answer.high = uint64_t(r >> 64);
22562
#endif
22563
  return answer;
22564
}
22565
22566
} // namespace numberparsing
22567
} // namespace westmere
22568
} // namespace simdjson
22569
22570
#define SIMDJSON_SWAR_NUMBER_PARSING 1
22571
22572
#endif //  SIMDJSON_WESTMERE_NUMBERPARSING_DEFS_H
22573
/* end file simdjson/westmere/numberparsing_defs.h */
22574
/* including simdjson/westmere/simd.h: #include "simdjson/westmere/simd.h" */
22575
/* begin file simdjson/westmere/simd.h */
22576
#ifndef SIMDJSON_WESTMERE_SIMD_H
22577
#define SIMDJSON_WESTMERE_SIMD_H
22578
22579
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22580
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
22581
/* amalgamation skipped (editor-only): #include "simdjson/westmere/bitmanipulation.h" */
22582
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
22583
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22584
22585
namespace simdjson {
22586
namespace westmere {
22587
namespace {
22588
namespace simd {
22589
22590
  template<typename Child>
22591
  struct base {
22592
    __m128i value;
22593
22594
    // Zero constructor
22595
    simdjson_inline base() : value{__m128i()} {}
22596
22597
    // Conversion from SIMD register
22598
    simdjson_inline base(const __m128i _value) : value(_value) {}
22599
22600
    // Conversion to SIMD register
22601
    simdjson_inline operator const __m128i&() const { return this->value; }
22602
    simdjson_inline operator __m128i&() { return this->value; }
22603
22604
    // Bit operations
22605
    simdjson_inline Child operator|(const Child other) const { return _mm_or_si128(*this, other); }
22606
    simdjson_inline Child operator&(const Child other) const { return _mm_and_si128(*this, other); }
22607
    simdjson_inline Child operator^(const Child other) const { return _mm_xor_si128(*this, other); }
22608
    simdjson_inline Child bit_andnot(const Child other) const { return _mm_andnot_si128(other, *this); }
22609
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
22610
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
22611
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
22612
  };
22613
22614
  template<typename T, typename Mask=simd8<bool>>
22615
  struct base8: base<simd8<T>> {
22616
    typedef uint16_t bitmask_t;
22617
    typedef uint32_t bitmask2_t;
22618
22619
    simdjson_inline base8() : base<simd8<T>>() {}
22620
    simdjson_inline base8(const __m128i _value) : base<simd8<T>>(_value) {}
22621
22622
    friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return _mm_cmpeq_epi8(lhs, rhs); }
22623
22624
    static const int SIZE = sizeof(base<simd8<T>>::value);
22625
22626
    template<int N=1>
22627
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
22628
      return _mm_alignr_epi8(*this, prev_chunk, 16 - N);
22629
    }
22630
  };
22631
22632
  // SIMD byte mask type (returned by things like eq and gt)
22633
  template<>
22634
  struct simd8<bool>: base8<bool> {
22635
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm_set1_epi8(uint8_t(-(!!_value))); }
22636
22637
    simdjson_inline simd8<bool>() : base8() {}
22638
    simdjson_inline simd8<bool>(const __m128i _value) : base8<bool>(_value) {}
22639
    // Splat constructor
22640
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
22641
22642
    simdjson_inline int to_bitmask() const { return _mm_movemask_epi8(*this); }
22643
    simdjson_inline bool any() const { return !_mm_testz_si128(*this, *this); }
22644
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
22645
  };
22646
22647
  template<typename T>
22648
  struct base8_numeric: base8<T> {
22649
    static simdjson_inline simd8<T> splat(T _value) { return _mm_set1_epi8(_value); }
22650
    static simdjson_inline simd8<T> zero() { return _mm_setzero_si128(); }
22651
    static simdjson_inline simd8<T> load(const T values[16]) {
22652
      return _mm_loadu_si128(reinterpret_cast<const __m128i *>(values));
22653
    }
22654
    // Repeat 16 values as many times as necessary (usually for lookup tables)
22655
    static simdjson_inline simd8<T> repeat_16(
22656
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
22657
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
22658
    ) {
22659
      return simd8<T>(
22660
        v0, v1, v2, v3, v4, v5, v6, v7,
22661
        v8, v9, v10,v11,v12,v13,v14,v15
22662
      );
22663
    }
22664
22665
    simdjson_inline base8_numeric() : base8<T>() {}
22666
    simdjson_inline base8_numeric(const __m128i _value) : base8<T>(_value) {}
22667
22668
    // Store to array
22669
    simdjson_inline void store(T dst[16]) const { return _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), *this); }
22670
22671
    // Override to distinguish from bool version
22672
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
22673
22674
    // Addition/subtraction are the same for signed and unsigned
22675
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm_add_epi8(*this, other); }
22676
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm_sub_epi8(*this, other); }
22677
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
22678
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
22679
22680
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
22681
    template<typename L>
22682
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
22683
      return _mm_shuffle_epi8(lookup_table, *this);
22684
    }
22685
22686
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
22687
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
22688
    // Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
22689
    // get written.
22690
    // Design consideration: it seems like a function with the
22691
    // signature simd8<L> compress(uint32_t mask) would be
22692
    // sensible, but the AVX ISA makes this kind of approach difficult.
22693
    template<typename L>
22694
    simdjson_inline void compress(uint16_t mask, L * output) const {
22695
      using internal::thintable_epi8;
22696
      using internal::BitsSetTable256mul2;
22697
      using internal::pshufb_combine_table;
22698
      // this particular implementation was inspired by work done by @animetosho
22699
      // we do it in two steps, first 8 bytes and then second 8 bytes
22700
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
22701
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
22702
      // next line just loads the 64-bit values thintable_epi8[mask1] and
22703
      // thintable_epi8[mask2] into a 128-bit register, using only
22704
      // two instructions on most compilers.
22705
      __m128i shufmask =  _mm_set_epi64x(thintable_epi8[mask2], thintable_epi8[mask1]);
22706
      // we increment by 0x08 the second half of the mask
22707
      shufmask =
22708
      _mm_add_epi8(shufmask, _mm_set_epi32(0x08080808, 0x08080808, 0, 0));
22709
      // this is the version "nearly pruned"
22710
      __m128i pruned = _mm_shuffle_epi8(*this, shufmask);
22711
      // we still need to put the two halves together.
22712
      // we compute the popcount of the first half:
22713
      int pop1 = BitsSetTable256mul2[mask1];
22714
      // then load the corresponding mask, what it does is to write
22715
      // only the first pop1 bytes from the first 8 bytes, and then
22716
      // it fills in with the bytes from the second 8 bytes + some filling
22717
      // at the end.
22718
      __m128i compactmask =
22719
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop1 * 8));
22720
      __m128i answer = _mm_shuffle_epi8(pruned, compactmask);
22721
      _mm_storeu_si128(reinterpret_cast<__m128i *>(output), answer);
22722
    }
22723
22724
    template<typename L>
22725
    simdjson_inline simd8<L> lookup_16(
22726
        L replace0,  L replace1,  L replace2,  L replace3,
22727
        L replace4,  L replace5,  L replace6,  L replace7,
22728
        L replace8,  L replace9,  L replace10, L replace11,
22729
        L replace12, L replace13, L replace14, L replace15) const {
22730
      return lookup_16(simd8<L>::repeat_16(
22731
        replace0,  replace1,  replace2,  replace3,
22732
        replace4,  replace5,  replace6,  replace7,
22733
        replace8,  replace9,  replace10, replace11,
22734
        replace12, replace13, replace14, replace15
22735
      ));
22736
    }
22737
  };
22738
22739
  // Signed bytes
22740
  template<>
22741
  struct simd8<int8_t> : base8_numeric<int8_t> {
22742
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
22743
    simdjson_inline simd8(const __m128i _value) : base8_numeric<int8_t>(_value) {}
22744
    // Splat constructor
22745
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
22746
    // Array constructor
22747
    simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {}
22748
    // Member-by-member initialization
22749
    simdjson_inline simd8(
22750
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
22751
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
22752
    ) : simd8(_mm_setr_epi8(
22753
      v0, v1, v2, v3, v4, v5, v6, v7,
22754
      v8, v9, v10,v11,v12,v13,v14,v15
22755
    )) {}
22756
    // Repeat 16 values as many times as necessary (usually for lookup tables)
22757
    simdjson_inline static simd8<int8_t> repeat_16(
22758
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
22759
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
22760
    ) {
22761
      return simd8<int8_t>(
22762
        v0, v1, v2, v3, v4, v5, v6, v7,
22763
        v8, v9, v10,v11,v12,v13,v14,v15
22764
      );
22765
    }
22766
22767
    // Order-sensitive comparisons
22768
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm_max_epi8(*this, other); }
22769
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm_min_epi8(*this, other); }
22770
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(*this, other); }
22771
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(other, *this); }
22772
  };
22773
22774
  // Unsigned bytes
22775
  template<>
22776
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
22777
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
22778
    simdjson_inline simd8(const __m128i _value) : base8_numeric<uint8_t>(_value) {}
22779
    // Splat constructor
22780
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
22781
    // Array constructor
22782
    simdjson_inline simd8(const uint8_t* values) : simd8(load(values)) {}
22783
    // Member-by-member initialization
22784
    simdjson_inline simd8(
22785
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
22786
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
22787
    ) : simd8(_mm_setr_epi8(
22788
      v0, v1, v2, v3, v4, v5, v6, v7,
22789
      v8, v9, v10,v11,v12,v13,v14,v15
22790
    )) {}
22791
    // Repeat 16 values as many times as necessary (usually for lookup tables)
22792
    simdjson_inline static simd8<uint8_t> repeat_16(
22793
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
22794
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
22795
    ) {
22796
      return simd8<uint8_t>(
22797
        v0, v1, v2, v3, v4, v5, v6, v7,
22798
        v8, v9, v10,v11,v12,v13,v14,v15
22799
      );
22800
    }
22801
22802
    // Saturated math
22803
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm_adds_epu8(*this, other); }
22804
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm_subs_epu8(*this, other); }
22805
22806
    // Order-specific operations
22807
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm_max_epu8(*this, other); }
22808
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm_min_epu8(*this, other); }
22809
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
22810
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
22811
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
22812
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
22813
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
22814
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
22815
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
22816
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
22817
22818
    // Bit-specific operations
22819
    simdjson_inline simd8<bool> bits_not_set() const { return *this == uint8_t(0); }
22820
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
22821
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
22822
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
22823
    simdjson_inline bool is_ascii() const { return _mm_movemask_epi8(*this) == 0; }
22824
    simdjson_inline bool bits_not_set_anywhere() const { return _mm_testz_si128(*this, *this); }
22825
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
22826
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return _mm_testz_si128(*this, bits); }
22827
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
22828
    template<int N>
22829
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
22830
    template<int N>
22831
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
22832
    // Get one of the bits and make a bitmask out of it.
22833
    // e.g. value.get_bit<7>() gets the high bit
22834
    template<int N>
22835
    simdjson_inline int get_bit() const { return _mm_movemask_epi8(_mm_slli_epi16(*this, 7-N)); }
22836
  };
22837
22838
  template<typename T>
22839
  struct simd8x64 {
22840
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
22841
    static_assert(NUM_CHUNKS == 4, "Westmere kernel should use four registers per 64-byte block.");
22842
    const simd8<T> chunks[NUM_CHUNKS];
22843
22844
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
22845
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
22846
    simd8x64() = delete; // no default constructor allowed
22847
22848
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
22849
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
22850
22851
    simdjson_inline void store(T ptr[64]) const {
22852
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
22853
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
22854
      this->chunks[2].store(ptr+sizeof(simd8<T>)*2);
22855
      this->chunks[3].store(ptr+sizeof(simd8<T>)*3);
22856
    }
22857
22858
    simdjson_inline simd8<T> reduce_or() const {
22859
      return (this->chunks[0] | this->chunks[1]) | (this->chunks[2] | this->chunks[3]);
22860
    }
22861
22862
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
22863
      this->chunks[0].compress(uint16_t(mask), output);
22864
      this->chunks[1].compress(uint16_t(mask >> 16), output + 16 - count_ones(mask & 0xFFFF));
22865
      this->chunks[2].compress(uint16_t(mask >> 32), output + 32 - count_ones(mask & 0xFFFFFFFF));
22866
      this->chunks[3].compress(uint16_t(mask >> 48), output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
22867
      return 64 - count_ones(mask);
22868
    }
22869
22870
    simdjson_inline uint64_t to_bitmask() const {
22871
      uint64_t r0 = uint32_t(this->chunks[0].to_bitmask() );
22872
      uint64_t r1 =          this->chunks[1].to_bitmask() ;
22873
      uint64_t r2 =          this->chunks[2].to_bitmask() ;
22874
      uint64_t r3 =          this->chunks[3].to_bitmask() ;
22875
      return r0 | (r1 << 16) | (r2 << 32) | (r3 << 48);
22876
    }
22877
22878
    simdjson_inline uint64_t eq(const T m) const {
22879
      const simd8<T> mask = simd8<T>::splat(m);
22880
      return  simd8x64<bool>(
22881
        this->chunks[0] == mask,
22882
        this->chunks[1] == mask,
22883
        this->chunks[2] == mask,
22884
        this->chunks[3] == mask
22885
      ).to_bitmask();
22886
    }
22887
22888
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
22889
      return  simd8x64<bool>(
22890
        this->chunks[0] == other.chunks[0],
22891
        this->chunks[1] == other.chunks[1],
22892
        this->chunks[2] == other.chunks[2],
22893
        this->chunks[3] == other.chunks[3]
22894
      ).to_bitmask();
22895
    }
22896
22897
    simdjson_inline uint64_t lteq(const T m) const {
22898
      const simd8<T> mask = simd8<T>::splat(m);
22899
      return  simd8x64<bool>(
22900
        this->chunks[0] <= mask,
22901
        this->chunks[1] <= mask,
22902
        this->chunks[2] <= mask,
22903
        this->chunks[3] <= mask
22904
      ).to_bitmask();
22905
    }
22906
  }; // struct simd8x64<T>
22907
22908
} // namespace simd
22909
} // unnamed namespace
22910
} // namespace westmere
22911
} // namespace simdjson
22912
22913
#endif // SIMDJSON_WESTMERE_SIMD_INPUT_H
22914
/* end file simdjson/westmere/simd.h */
22915
/* including simdjson/westmere/stringparsing_defs.h: #include "simdjson/westmere/stringparsing_defs.h" */
22916
/* begin file simdjson/westmere/stringparsing_defs.h */
22917
#ifndef SIMDJSON_WESTMERE_STRINGPARSING_DEFS_H
22918
#define SIMDJSON_WESTMERE_STRINGPARSING_DEFS_H
22919
22920
/* including simdjson/westmere/bitmanipulation.h: #include "simdjson/westmere/bitmanipulation.h" */
22921
/* begin file simdjson/westmere/bitmanipulation.h */
22922
#ifndef SIMDJSON_WESTMERE_BITMANIPULATION_H
22923
#define SIMDJSON_WESTMERE_BITMANIPULATION_H
22924
22925
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
22926
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
22927
/* amalgamation skipped (editor-only): #include "simdjson/westmere/intrinsics.h" */
22928
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
22929
22930
namespace simdjson {
22931
namespace westmere {
22932
namespace {
22933
22934
// We sometimes call trailing_zero on inputs that are zero,
22935
// but the algorithms do not end up using the returned value.
22936
// Sadly, sanitizers are not smart enough to figure it out.
22937
SIMDJSON_NO_SANITIZE_UNDEFINED
22938
// This function can be used safely even if not all bytes have been
22939
// initialized.
22940
// See issue https://github.com/simdjson/simdjson/issues/1965
22941
SIMDJSON_NO_SANITIZE_MEMORY
22942
simdjson_inline int trailing_zeroes(uint64_t input_num) {
22943
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22944
  unsigned long ret;
22945
  // Search the mask data from least significant bit (LSB)
22946
  // to the most significant bit (MSB) for a set bit (1).
22947
  _BitScanForward64(&ret, input_num);
22948
  return (int)ret;
22949
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
22950
  return __builtin_ctzll(input_num);
22951
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
22952
}
22953
22954
/* result might be undefined when input_num is zero */
22955
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
22956
  return input_num & (input_num-1);
22957
}
22958
22959
/* result might be undefined when input_num is zero */
22960
simdjson_inline int leading_zeroes(uint64_t input_num) {
22961
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22962
  unsigned long leading_zero = 0;
22963
  // Search the mask data from most significant bit (MSB)
22964
  // to least significant bit (LSB) for a set bit (1).
22965
  if (_BitScanReverse64(&leading_zero, input_num))
22966
    return (int)(63 - leading_zero);
22967
  else
22968
    return 64;
22969
#else
22970
  return __builtin_clzll(input_num);
22971
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
22972
}
22973
22974
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22975
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
22976
  // note: we do not support legacy 32-bit Windows in this kernel
22977
  return __popcnt64(input_num);// Visual Studio wants two underscores
22978
}
22979
#else
22980
simdjson_inline long long int count_ones(uint64_t input_num) {
22981
  return _popcnt64(input_num);
22982
}
22983
#endif
22984
22985
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
22986
                                uint64_t *result) {
22987
#if SIMDJSON_REGULAR_VISUAL_STUDIO
22988
  return _addcarry_u64(0, value1, value2,
22989
                       reinterpret_cast<unsigned __int64 *>(result));
22990
#else
22991
  return __builtin_uaddll_overflow(value1, value2,
22992
                                   reinterpret_cast<unsigned long long *>(result));
22993
#endif
22994
}
22995
22996
} // unnamed namespace
22997
} // namespace westmere
22998
} // namespace simdjson
22999
23000
#endif // SIMDJSON_WESTMERE_BITMANIPULATION_H
23001
/* end file simdjson/westmere/bitmanipulation.h */
23002
/* including simdjson/westmere/simd.h: #include "simdjson/westmere/simd.h" */
23003
/* begin file simdjson/westmere/simd.h */
23004
#ifndef SIMDJSON_WESTMERE_SIMD_H
23005
#define SIMDJSON_WESTMERE_SIMD_H
23006
23007
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
23008
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
23009
/* amalgamation skipped (editor-only): #include "simdjson/westmere/bitmanipulation.h" */
23010
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
23011
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
23012
23013
namespace simdjson {
23014
namespace westmere {
23015
namespace {
23016
namespace simd {
23017
23018
  template<typename Child>
23019
  struct base {
23020
    __m128i value;
23021
23022
    // Zero constructor
23023
    simdjson_inline base() : value{__m128i()} {}
23024
23025
    // Conversion from SIMD register
23026
    simdjson_inline base(const __m128i _value) : value(_value) {}
23027
23028
    // Conversion to SIMD register
23029
    simdjson_inline operator const __m128i&() const { return this->value; }
23030
    simdjson_inline operator __m128i&() { return this->value; }
23031
23032
    // Bit operations
23033
    simdjson_inline Child operator|(const Child other) const { return _mm_or_si128(*this, other); }
23034
    simdjson_inline Child operator&(const Child other) const { return _mm_and_si128(*this, other); }
23035
    simdjson_inline Child operator^(const Child other) const { return _mm_xor_si128(*this, other); }
23036
    simdjson_inline Child bit_andnot(const Child other) const { return _mm_andnot_si128(other, *this); }
23037
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
23038
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
23039
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
23040
  };
23041
23042
  template<typename T, typename Mask=simd8<bool>>
23043
  struct base8: base<simd8<T>> {
23044
    typedef uint16_t bitmask_t;
23045
    typedef uint32_t bitmask2_t;
23046
23047
    simdjson_inline base8() : base<simd8<T>>() {}
23048
    simdjson_inline base8(const __m128i _value) : base<simd8<T>>(_value) {}
23049
23050
    friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return _mm_cmpeq_epi8(lhs, rhs); }
23051
23052
    static const int SIZE = sizeof(base<simd8<T>>::value);
23053
23054
    template<int N=1>
23055
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
23056
      return _mm_alignr_epi8(*this, prev_chunk, 16 - N);
23057
    }
23058
  };
23059
23060
  // SIMD byte mask type (returned by things like eq and gt)
23061
  template<>
23062
  struct simd8<bool>: base8<bool> {
23063
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm_set1_epi8(uint8_t(-(!!_value))); }
23064
23065
    simdjson_inline simd8<bool>() : base8() {}
23066
    simdjson_inline simd8<bool>(const __m128i _value) : base8<bool>(_value) {}
23067
    // Splat constructor
23068
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
23069
23070
    simdjson_inline int to_bitmask() const { return _mm_movemask_epi8(*this); }
23071
    simdjson_inline bool any() const { return !_mm_testz_si128(*this, *this); }
23072
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
23073
  };
23074
23075
  template<typename T>
23076
  struct base8_numeric: base8<T> {
23077
    static simdjson_inline simd8<T> splat(T _value) { return _mm_set1_epi8(_value); }
23078
    static simdjson_inline simd8<T> zero() { return _mm_setzero_si128(); }
23079
    static simdjson_inline simd8<T> load(const T values[16]) {
23080
      return _mm_loadu_si128(reinterpret_cast<const __m128i *>(values));
23081
    }
23082
    // Repeat 16 values as many times as necessary (usually for lookup tables)
23083
    static simdjson_inline simd8<T> repeat_16(
23084
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
23085
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
23086
    ) {
23087
      return simd8<T>(
23088
        v0, v1, v2, v3, v4, v5, v6, v7,
23089
        v8, v9, v10,v11,v12,v13,v14,v15
23090
      );
23091
    }
23092
23093
    simdjson_inline base8_numeric() : base8<T>() {}
23094
    simdjson_inline base8_numeric(const __m128i _value) : base8<T>(_value) {}
23095
23096
    // Store to array
23097
    simdjson_inline void store(T dst[16]) const { return _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), *this); }
23098
23099
    // Override to distinguish from bool version
23100
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
23101
23102
    // Addition/subtraction are the same for signed and unsigned
23103
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm_add_epi8(*this, other); }
23104
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm_sub_epi8(*this, other); }
23105
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
23106
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
23107
23108
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
23109
    template<typename L>
23110
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
23111
      return _mm_shuffle_epi8(lookup_table, *this);
23112
    }
23113
23114
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
23115
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
23116
    // Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
23117
    // get written.
23118
    // Design consideration: it seems like a function with the
23119
    // signature simd8<L> compress(uint32_t mask) would be
23120
    // sensible, but the AVX ISA makes this kind of approach difficult.
23121
    template<typename L>
23122
    simdjson_inline void compress(uint16_t mask, L * output) const {
23123
      using internal::thintable_epi8;
23124
      using internal::BitsSetTable256mul2;
23125
      using internal::pshufb_combine_table;
23126
      // this particular implementation was inspired by work done by @animetosho
23127
      // we do it in two steps, first 8 bytes and then second 8 bytes
23128
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
23129
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
23130
      // next line just loads the 64-bit values thintable_epi8[mask1] and
23131
      // thintable_epi8[mask2] into a 128-bit register, using only
23132
      // two instructions on most compilers.
23133
      __m128i shufmask =  _mm_set_epi64x(thintable_epi8[mask2], thintable_epi8[mask1]);
23134
      // we increment by 0x08 the second half of the mask
23135
      shufmask =
23136
      _mm_add_epi8(shufmask, _mm_set_epi32(0x08080808, 0x08080808, 0, 0));
23137
      // this is the version "nearly pruned"
23138
      __m128i pruned = _mm_shuffle_epi8(*this, shufmask);
23139
      // we still need to put the two halves together.
23140
      // we compute the popcount of the first half:
23141
      int pop1 = BitsSetTable256mul2[mask1];
23142
      // then load the corresponding mask, what it does is to write
23143
      // only the first pop1 bytes from the first 8 bytes, and then
23144
      // it fills in with the bytes from the second 8 bytes + some filling
23145
      // at the end.
23146
      __m128i compactmask =
23147
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop1 * 8));
23148
      __m128i answer = _mm_shuffle_epi8(pruned, compactmask);
23149
      _mm_storeu_si128(reinterpret_cast<__m128i *>(output), answer);
23150
    }
23151
23152
    template<typename L>
23153
    simdjson_inline simd8<L> lookup_16(
23154
        L replace0,  L replace1,  L replace2,  L replace3,
23155
        L replace4,  L replace5,  L replace6,  L replace7,
23156
        L replace8,  L replace9,  L replace10, L replace11,
23157
        L replace12, L replace13, L replace14, L replace15) const {
23158
      return lookup_16(simd8<L>::repeat_16(
23159
        replace0,  replace1,  replace2,  replace3,
23160
        replace4,  replace5,  replace6,  replace7,
23161
        replace8,  replace9,  replace10, replace11,
23162
        replace12, replace13, replace14, replace15
23163
      ));
23164
    }
23165
  };
23166
23167
  // Signed bytes
23168
  template<>
23169
  struct simd8<int8_t> : base8_numeric<int8_t> {
23170
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
23171
    simdjson_inline simd8(const __m128i _value) : base8_numeric<int8_t>(_value) {}
23172
    // Splat constructor
23173
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
23174
    // Array constructor
23175
    simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {}
23176
    // Member-by-member initialization
23177
    simdjson_inline simd8(
23178
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
23179
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
23180
    ) : simd8(_mm_setr_epi8(
23181
      v0, v1, v2, v3, v4, v5, v6, v7,
23182
      v8, v9, v10,v11,v12,v13,v14,v15
23183
    )) {}
23184
    // Repeat 16 values as many times as necessary (usually for lookup tables)
23185
    simdjson_inline static simd8<int8_t> repeat_16(
23186
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
23187
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
23188
    ) {
23189
      return simd8<int8_t>(
23190
        v0, v1, v2, v3, v4, v5, v6, v7,
23191
        v8, v9, v10,v11,v12,v13,v14,v15
23192
      );
23193
    }
23194
23195
    // Order-sensitive comparisons
23196
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm_max_epi8(*this, other); }
23197
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm_min_epi8(*this, other); }
23198
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(*this, other); }
23199
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(other, *this); }
23200
  };
23201
23202
  // Unsigned bytes
23203
  template<>
23204
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
23205
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
23206
    simdjson_inline simd8(const __m128i _value) : base8_numeric<uint8_t>(_value) {}
23207
    // Splat constructor
23208
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
23209
    // Array constructor
23210
    simdjson_inline simd8(const uint8_t* values) : simd8(load(values)) {}
23211
    // Member-by-member initialization
23212
    simdjson_inline simd8(
23213
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
23214
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
23215
    ) : simd8(_mm_setr_epi8(
23216
      v0, v1, v2, v3, v4, v5, v6, v7,
23217
      v8, v9, v10,v11,v12,v13,v14,v15
23218
    )) {}
23219
    // Repeat 16 values as many times as necessary (usually for lookup tables)
23220
    simdjson_inline static simd8<uint8_t> repeat_16(
23221
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
23222
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
23223
    ) {
23224
      return simd8<uint8_t>(
23225
        v0, v1, v2, v3, v4, v5, v6, v7,
23226
        v8, v9, v10,v11,v12,v13,v14,v15
23227
      );
23228
    }
23229
23230
    // Saturated math
23231
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm_adds_epu8(*this, other); }
23232
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm_subs_epu8(*this, other); }
23233
23234
    // Order-specific operations
23235
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm_max_epu8(*this, other); }
23236
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm_min_epu8(*this, other); }
23237
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
23238
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
23239
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
23240
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
23241
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
23242
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
23243
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
23244
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
23245
23246
    // Bit-specific operations
23247
    simdjson_inline simd8<bool> bits_not_set() const { return *this == uint8_t(0); }
23248
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
23249
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
23250
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
23251
    simdjson_inline bool is_ascii() const { return _mm_movemask_epi8(*this) == 0; }
23252
    simdjson_inline bool bits_not_set_anywhere() const { return _mm_testz_si128(*this, *this); }
23253
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
23254
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return _mm_testz_si128(*this, bits); }
23255
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
23256
    template<int N>
23257
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
23258
    template<int N>
23259
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
23260
    // Get one of the bits and make a bitmask out of it.
23261
    // e.g. value.get_bit<7>() gets the high bit
23262
    template<int N>
23263
    simdjson_inline int get_bit() const { return _mm_movemask_epi8(_mm_slli_epi16(*this, 7-N)); }
23264
  };
23265
23266
  template<typename T>
23267
  struct simd8x64 {
23268
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
23269
    static_assert(NUM_CHUNKS == 4, "Westmere kernel should use four registers per 64-byte block.");
23270
    const simd8<T> chunks[NUM_CHUNKS];
23271
23272
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
23273
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
23274
    simd8x64() = delete; // no default constructor allowed
23275
23276
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
23277
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
23278
23279
    simdjson_inline void store(T ptr[64]) const {
23280
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
23281
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
23282
      this->chunks[2].store(ptr+sizeof(simd8<T>)*2);
23283
      this->chunks[3].store(ptr+sizeof(simd8<T>)*3);
23284
    }
23285
23286
    simdjson_inline simd8<T> reduce_or() const {
23287
      return (this->chunks[0] | this->chunks[1]) | (this->chunks[2] | this->chunks[3]);
23288
    }
23289
23290
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
23291
      this->chunks[0].compress(uint16_t(mask), output);
23292
      this->chunks[1].compress(uint16_t(mask >> 16), output + 16 - count_ones(mask & 0xFFFF));
23293
      this->chunks[2].compress(uint16_t(mask >> 32), output + 32 - count_ones(mask & 0xFFFFFFFF));
23294
      this->chunks[3].compress(uint16_t(mask >> 48), output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
23295
      return 64 - count_ones(mask);
23296
    }
23297
23298
    simdjson_inline uint64_t to_bitmask() const {
23299
      uint64_t r0 = uint32_t(this->chunks[0].to_bitmask() );
23300
      uint64_t r1 =          this->chunks[1].to_bitmask() ;
23301
      uint64_t r2 =          this->chunks[2].to_bitmask() ;
23302
      uint64_t r3 =          this->chunks[3].to_bitmask() ;
23303
      return r0 | (r1 << 16) | (r2 << 32) | (r3 << 48);
23304
    }
23305
23306
    simdjson_inline uint64_t eq(const T m) const {
23307
      const simd8<T> mask = simd8<T>::splat(m);
23308
      return  simd8x64<bool>(
23309
        this->chunks[0] == mask,
23310
        this->chunks[1] == mask,
23311
        this->chunks[2] == mask,
23312
        this->chunks[3] == mask
23313
      ).to_bitmask();
23314
    }
23315
23316
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
23317
      return  simd8x64<bool>(
23318
        this->chunks[0] == other.chunks[0],
23319
        this->chunks[1] == other.chunks[1],
23320
        this->chunks[2] == other.chunks[2],
23321
        this->chunks[3] == other.chunks[3]
23322
      ).to_bitmask();
23323
    }
23324
23325
    simdjson_inline uint64_t lteq(const T m) const {
23326
      const simd8<T> mask = simd8<T>::splat(m);
23327
      return  simd8x64<bool>(
23328
        this->chunks[0] <= mask,
23329
        this->chunks[1] <= mask,
23330
        this->chunks[2] <= mask,
23331
        this->chunks[3] <= mask
23332
      ).to_bitmask();
23333
    }
23334
  }; // struct simd8x64<T>
23335
23336
} // namespace simd
23337
} // unnamed namespace
23338
} // namespace westmere
23339
} // namespace simdjson
23340
23341
#endif // SIMDJSON_WESTMERE_SIMD_INPUT_H
23342
/* end file simdjson/westmere/simd.h */
23343
23344
namespace simdjson {
23345
namespace westmere {
23346
namespace {
23347
23348
using namespace simd;
23349
23350
// Holds backslashes and quotes locations.
23351
struct backslash_and_quote {
23352
public:
23353
  static constexpr uint32_t BYTES_PROCESSED = 32;
23354
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
23355
23356
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
23357
  simdjson_inline bool has_backslash() { return bs_bits != 0; }
23358
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
23359
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
23360
23361
  uint32_t bs_bits;
23362
  uint32_t quote_bits;
23363
}; // struct backslash_and_quote
23364
23365
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
23366
  // this can read up to 31 bytes beyond the buffer size, but we require
23367
  // SIMDJSON_PADDING of padding
23368
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
23369
  simd8<uint8_t> v0(src);
23370
  simd8<uint8_t> v1(src + 16);
23371
  v0.store(dst);
23372
  v1.store(dst + 16);
23373
  uint64_t bs_and_quote = simd8x64<bool>(v0 == '\\', v1 == '\\', v0 == '"', v1 == '"').to_bitmask();
23374
  return {
23375
    uint32_t(bs_and_quote),      // bs_bits
23376
    uint32_t(bs_and_quote >> 32) // quote_bits
23377
  };
23378
}
23379
23380
} // unnamed namespace
23381
} // namespace westmere
23382
} // namespace simdjson
23383
23384
#endif // SIMDJSON_WESTMERE_STRINGPARSING_DEFS_H
23385
/* end file simdjson/westmere/stringparsing_defs.h */
23386
/* end file simdjson/westmere/begin.h */
23387
/* including simdjson/generic/amalgamated.h for westmere: #include "simdjson/generic/amalgamated.h" */
23388
/* begin file simdjson/generic/amalgamated.h for westmere */
23389
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
23390
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
23391
#endif
23392
23393
/* including simdjson/generic/base.h for westmere: #include "simdjson/generic/base.h" */
23394
/* begin file simdjson/generic/base.h for westmere */
23395
#ifndef SIMDJSON_GENERIC_BASE_H
23396
23397
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
23398
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_BASE_H */
23399
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
23400
/* amalgamation skipped (editor-only): // If we haven't got an implementation yet, we're in the editor, editing a generic file! Just */
23401
/* amalgamation skipped (editor-only): // use the most advanced one we can so the most possible stuff can be tested. */
23402
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_IMPLEMENTATION */
23403
/* amalgamation skipped (editor-only): #include "simdjson/implementation_detection.h" */
23404
/* amalgamation skipped (editor-only): #if SIMDJSON_IMPLEMENTATION_ICELAKE */
23405
/* amalgamation skipped (editor-only): #include "simdjson/icelake/begin.h" */
23406
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_HASWELL */
23407
/* amalgamation skipped (editor-only): #include "simdjson/haswell/begin.h" */
23408
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_WESTMERE */
23409
/* amalgamation skipped (editor-only): #include "simdjson/westmere/begin.h" */
23410
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_ARM64 */
23411
/* amalgamation skipped (editor-only): #include "simdjson/arm64/begin.h" */
23412
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_PPC64 */
23413
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/begin.h" */
23414
/* amalgamation skipped (editor-only): #elif SIMDJSON_IMPLEMENTATION_FALLBACK */
23415
/* amalgamation skipped (editor-only): #include "simdjson/fallback/begin.h" */
23416
/* amalgamation skipped (editor-only): #else */
23417
/* amalgamation skipped (editor-only): #error "All possible implementations (including fallback) have been disabled! simdjson will not run." */
23418
/* amalgamation skipped (editor-only): #endif */
23419
/* amalgamation skipped (editor-only): #endif // SIMDJSON_IMPLEMENTATION */
23420
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
23421
23422
namespace simdjson {
23423
namespace westmere {
23424
23425
struct open_container;
23426
class dom_parser_implementation;
23427
23428
/**
23429
 * The type of a JSON number
23430
 */
23431
enum class number_type {
23432
    floating_point_number=1, /// a binary64 number
23433
    signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
23434
    unsigned_integer,        /// a positive integer larger or equal to 1<<63
23435
    big_integer              /// a big integer that does not fit in a 64-bit word
23436
};
23437
23438
} // namespace westmere
23439
} // namespace simdjson
23440
23441
#endif // SIMDJSON_GENERIC_BASE_H
23442
/* end file simdjson/generic/base.h for westmere */
23443
/* including simdjson/generic/jsoncharutils.h for westmere: #include "simdjson/generic/jsoncharutils.h" */
23444
/* begin file simdjson/generic/jsoncharutils.h for westmere */
23445
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
23446
23447
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
23448
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_JSONCHARUTILS_H */
23449
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
23450
/* amalgamation skipped (editor-only): #include "simdjson/internal/jsoncharutils_tables.h" */
23451
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
23452
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
23453
23454
namespace simdjson {
23455
namespace westmere {
23456
namespace {
23457
namespace jsoncharutils {
23458
23459
// return non-zero if not a structural or whitespace char
23460
// zero otherwise
23461
simdjson_inline uint32_t is_not_structural_or_whitespace(uint8_t c) {
23462
  return internal::structural_or_whitespace_negated[c];
23463
}
23464
23465
simdjson_inline uint32_t is_structural_or_whitespace(uint8_t c) {
23466
  return internal::structural_or_whitespace[c];
23467
}
23468
23469
// returns a value with the high 16 bits set if not valid
23470
// otherwise returns the conversion of the 4 hex digits at src into the bottom
23471
// 16 bits of the 32-bit return register
23472
//
23473
// see
23474
// https://lemire.me/blog/2019/04/17/parsing-short-hexadecimal-strings-efficiently/
23475
static inline uint32_t hex_to_u32_nocheck(
23476
    const uint8_t *src) { // strictly speaking, static inline is a C-ism
23477
  uint32_t v1 = internal::digit_to_val32[630 + src[0]];
23478
  uint32_t v2 = internal::digit_to_val32[420 + src[1]];
23479
  uint32_t v3 = internal::digit_to_val32[210 + src[2]];
23480
  uint32_t v4 = internal::digit_to_val32[0 + src[3]];
23481
  return v1 | v2 | v3 | v4;
23482
}
23483
23484
// given a code point cp, writes to c
23485
// the utf-8 code, outputting the length in
23486
// bytes, if the length is zero, the code point
23487
// is invalid
23488
//
23489
// This can possibly be made faster using pdep
23490
// and clz and table lookups, but JSON documents
23491
// have few escaped code points, and the following
23492
// function looks cheap.
23493
//
23494
// Note: we assume that surrogates are treated separately
23495
//
23496
simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
23497
  if (cp <= 0x7F) {
23498
    c[0] = uint8_t(cp);
23499
    return 1; // ascii
23500
  }
23501
  if (cp <= 0x7FF) {
23502
    c[0] = uint8_t((cp >> 6) + 192);
23503
    c[1] = uint8_t((cp & 63) + 128);
23504
    return 2; // universal plane
23505
    //  Surrogates are treated elsewhere...
23506
    //} //else if (0xd800 <= cp && cp <= 0xdfff) {
23507
    //  return 0; // surrogates // could put assert here
23508
  } else if (cp <= 0xFFFF) {
23509
    c[0] = uint8_t((cp >> 12) + 224);
23510
    c[1] = uint8_t(((cp >> 6) & 63) + 128);
23511
    c[2] = uint8_t((cp & 63) + 128);
23512
    return 3;
23513
  } else if (cp <= 0x10FFFF) { // if you know you have a valid code point, this
23514
                               // is not needed
23515
    c[0] = uint8_t((cp >> 18) + 240);
23516
    c[1] = uint8_t(((cp >> 12) & 63) + 128);
23517
    c[2] = uint8_t(((cp >> 6) & 63) + 128);
23518
    c[3] = uint8_t((cp & 63) + 128);
23519
    return 4;
23520
  }
23521
  // will return 0 when the code point was too large.
23522
  return 0; // bad r
23523
}
23524
23525
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
23526
// this is a slow emulation routine for 32-bit
23527
//
23528
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
23529
  return x * (uint64_t)y;
23530
}
23531
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
23532
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
23533
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
23534
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
23535
  uint64_t adbc_carry = !!(adbc < ad);
23536
  uint64_t lo = bd + (adbc << 32);
23537
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
23538
        (adbc_carry << 32) + !!(lo < bd);
23539
  return lo;
23540
}
23541
#endif
23542
23543
} // namespace jsoncharutils
23544
} // unnamed namespace
23545
} // namespace westmere
23546
} // namespace simdjson
23547
23548
#endif // SIMDJSON_GENERIC_JSONCHARUTILS_H
23549
/* end file simdjson/generic/jsoncharutils.h for westmere */
23550
/* including simdjson/generic/atomparsing.h for westmere: #include "simdjson/generic/atomparsing.h" */
23551
/* begin file simdjson/generic/atomparsing.h for westmere */
23552
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
23553
23554
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
23555
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ATOMPARSING_H */
23556
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
23557
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
23558
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
23559
23560
#include <cstring>
23561
23562
namespace simdjson {
23563
namespace westmere {
23564
namespace {
23565
/// @private
23566
namespace atomparsing {
23567
23568
// The string_to_uint32 is exclusively used to map literal strings to 32-bit values.
23569
// We use memcpy instead of a pointer cast to avoid undefined behaviors since we cannot
23570
// be certain that the character pointer will be properly aligned.
23571
// You might think that using memcpy makes this function expensive, but you'd be wrong.
23572
// All decent optimizing compilers (GCC, clang, Visual Studio) will compile string_to_uint32("false");
23573
// to the compile-time constant 1936482662.
23574
simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(&val, str, sizeof(uint32_t)); return val; }
23575
23576
23577
// Again in str4ncmp we use a memcpy to avoid undefined behavior. The memcpy may appear expensive.
23578
// Yet all decent optimizing compilers will compile memcpy to a single instruction, just about.
23579
simdjson_warn_unused
23580
simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) {
23581
  uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++)
23582
  static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes");
23583
  std::memcpy(&srcval, src, sizeof(uint32_t));
23584
  return srcval ^ string_to_uint32(atom);
23585
}
23586
23587
simdjson_warn_unused
23588
simdjson_inline bool is_valid_true_atom(const uint8_t *src) {
23589
  return (str4ncmp(src, "true") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
23590
}
23591
23592
simdjson_warn_unused
23593
simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) {
23594
  if (len > 4) { return is_valid_true_atom(src); }
23595
  else if (len == 4) { return !str4ncmp(src, "true"); }
23596
  else { return false; }
23597
}
23598
23599
simdjson_warn_unused
23600
simdjson_inline bool is_valid_false_atom(const uint8_t *src) {
23601
  return (str4ncmp(src+1, "alse") | jsoncharutils::is_not_structural_or_whitespace(src[5])) == 0;
23602
}
23603
23604
simdjson_warn_unused
23605
simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) {
23606
  if (len > 5) { return is_valid_false_atom(src); }
23607
  else if (len == 5) { return !str4ncmp(src+1, "alse"); }
23608
  else { return false; }
23609
}
23610
23611
simdjson_warn_unused
23612
simdjson_inline bool is_valid_null_atom(const uint8_t *src) {
23613
  return (str4ncmp(src, "null") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
23614
}
23615
23616
simdjson_warn_unused
23617
simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
23618
  if (len > 4) { return is_valid_null_atom(src); }
23619
  else if (len == 4) { return !str4ncmp(src, "null"); }
23620
  else { return false; }
23621
}
23622
23623
} // namespace atomparsing
23624
} // unnamed namespace
23625
} // namespace westmere
23626
} // namespace simdjson
23627
23628
#endif // SIMDJSON_GENERIC_ATOMPARSING_H
23629
/* end file simdjson/generic/atomparsing.h for westmere */
23630
/* including simdjson/generic/dom_parser_implementation.h for westmere: #include "simdjson/generic/dom_parser_implementation.h" */
23631
/* begin file simdjson/generic/dom_parser_implementation.h for westmere */
23632
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
23633
23634
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
23635
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H */
23636
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
23637
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
23638
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
23639
23640
namespace simdjson {
23641
namespace westmere {
23642
23643
// expectation: sizeof(open_container) = 64/8.
23644
struct open_container {
23645
  uint32_t tape_index; // where, on the tape, does the scope ([,{) begins
23646
  uint32_t count; // how many elements in the scope
23647
}; // struct open_container
23648
23649
static_assert(sizeof(open_container) == 64/8, "Open container must be 64 bits");
23650
23651
class dom_parser_implementation final : public internal::dom_parser_implementation {
23652
public:
23653
  /** Tape location of each open { or [ */
23654
  std::unique_ptr<open_container[]> open_containers{};
23655
  /** Whether each open container is a [ or { */
23656
  std::unique_ptr<bool[]> is_array{};
23657
  /** Buffer passed to stage 1 */
23658
  const uint8_t *buf{};
23659
  /** Length passed to stage 1 */
23660
  size_t len{0};
23661
  /** Document passed to stage 2 */
23662
  dom::document *doc{};
23663
23664
  inline dom_parser_implementation() noexcept;
23665
  inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
23666
  inline dom_parser_implementation &operator=(dom_parser_implementation &&other) noexcept;
23667
  dom_parser_implementation(const dom_parser_implementation &) = delete;
23668
  dom_parser_implementation &operator=(const dom_parser_implementation &) = delete;
23669
23670
  simdjson_warn_unused error_code parse(const uint8_t *buf, size_t len, dom::document &doc) noexcept final;
23671
  simdjson_warn_unused error_code stage1(const uint8_t *buf, size_t len, stage1_mode partial) noexcept final;
23672
  simdjson_warn_unused error_code stage2(dom::document &doc) noexcept final;
23673
  simdjson_warn_unused error_code stage2_next(dom::document &doc) noexcept final;
23674
  simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept final;
23675
  simdjson_warn_unused uint8_t *parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept final;
23676
  inline simdjson_warn_unused error_code set_capacity(size_t capacity) noexcept final;
23677
  inline simdjson_warn_unused error_code set_max_depth(size_t max_depth) noexcept final;
23678
private:
23679
  simdjson_inline simdjson_warn_unused error_code set_capacity_stage1(size_t capacity);
23680
23681
};
23682
23683
} // namespace westmere
23684
} // namespace simdjson
23685
23686
namespace simdjson {
23687
namespace westmere {
23688
23689
inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
23690
inline dom_parser_implementation::dom_parser_implementation(dom_parser_implementation &&other) noexcept = default;
23691
inline dom_parser_implementation &dom_parser_implementation::operator=(dom_parser_implementation &&other) noexcept = default;
23692
23693
// Leaving these here so they can be inlined if so desired
23694
inline simdjson_warn_unused error_code dom_parser_implementation::set_capacity(size_t capacity) noexcept {
23695
  if(capacity > SIMDJSON_MAXSIZE_BYTES) { return CAPACITY; }
23696
  // Stage 1 index output
23697
  size_t max_structures = SIMDJSON_ROUNDUP_N(capacity, 64) + 2 + 7;
23698
  structural_indexes.reset( new (std::nothrow) uint32_t[max_structures] );
23699
  if (!structural_indexes) { _capacity = 0; return MEMALLOC; }
23700
  structural_indexes[0] = 0;
23701
  n_structural_indexes = 0;
23702
23703
  _capacity = capacity;
23704
  return SUCCESS;
23705
}
23706
23707
inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(size_t max_depth) noexcept {
23708
  // Stage 2 stacks
23709
  open_containers.reset(new (std::nothrow) open_container[max_depth]);
23710
  is_array.reset(new (std::nothrow) bool[max_depth]);
23711
  if (!is_array || !open_containers) { _max_depth = 0; return MEMALLOC; }
23712
23713
  _max_depth = max_depth;
23714
  return SUCCESS;
23715
}
23716
23717
} // namespace westmere
23718
} // namespace simdjson
23719
23720
#endif // SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
23721
/* end file simdjson/generic/dom_parser_implementation.h for westmere */
23722
/* including simdjson/generic/implementation_simdjson_result_base.h for westmere: #include "simdjson/generic/implementation_simdjson_result_base.h" */
23723
/* begin file simdjson/generic/implementation_simdjson_result_base.h for westmere */
23724
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
23725
23726
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
23727
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H */
23728
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
23729
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
23730
23731
namespace simdjson {
23732
namespace westmere {
23733
23734
// This is a near copy of include/error.h's implementation_simdjson_result_base, except it doesn't use std::pair
23735
// so we can avoid inlining errors
23736
// TODO reconcile these!
23737
/**
23738
 * The result of a simdjson operation that could fail.
23739
 *
23740
 * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
23741
 *
23742
 * This is a base class for implementations that want to add functions to the result type for
23743
 * chaining.
23744
 *
23745
 * Override like:
23746
 *
23747
 *   struct simdjson_result<T> : public internal::implementation_simdjson_result_base<T> {
23748
 *     simdjson_result() noexcept : internal::implementation_simdjson_result_base<T>() {}
23749
 *     simdjson_result(error_code error) noexcept : internal::implementation_simdjson_result_base<T>(error) {}
23750
 *     simdjson_result(T &&value) noexcept : internal::implementation_simdjson_result_base<T>(std::forward(value)) {}
23751
 *     simdjson_result(T &&value, error_code error) noexcept : internal::implementation_simdjson_result_base<T>(value, error) {}
23752
 *     // Your extra methods here
23753
 *   }
23754
 *
23755
 * Then any method returning simdjson_result<T> will be chainable with your methods.
23756
 */
23757
template<typename T>
23758
struct implementation_simdjson_result_base {
23759
23760
  /**
23761
   * Create a new empty result with error = UNINITIALIZED.
23762
   */
23763
  simdjson_inline implementation_simdjson_result_base() noexcept = default;
23764
23765
  /**
23766
   * Create a new error result.
23767
   */
23768
  simdjson_inline implementation_simdjson_result_base(error_code error) noexcept;
23769
23770
  /**
23771
   * Create a new successful result.
23772
   */
23773
  simdjson_inline implementation_simdjson_result_base(T &&value) noexcept;
23774
23775
  /**
23776
   * Create a new result with both things (use if you don't want to branch when creating the result).
23777
   */
23778
  simdjson_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
23779
23780
  /**
23781
   * Move the value and the error to the provided variables.
23782
   *
23783
   * @param value The variable to assign the value to. May not be set if there is an error.
23784
   * @param error The variable to assign the error to. Set to SUCCESS if there is no error.
23785
   */
23786
  simdjson_inline void tie(T &value, error_code &error) && noexcept;
23787
23788
  /**
23789
   * Move the value to the provided variable.
23790
   *
23791
   * @param value The variable to assign the value to. May not be set if there is an error.
23792
   */
23793
  simdjson_inline error_code get(T &value) && noexcept;
23794
23795
  /**
23796
   * The error.
23797
   */
23798
  simdjson_inline error_code error() const noexcept;
23799
23800
#if SIMDJSON_EXCEPTIONS
23801
23802
  /**
23803
   * Get the result value.
23804
   *
23805
   * @throw simdjson_error if there was an error.
23806
   */
23807
  simdjson_inline T& value() & noexcept(false);
23808
23809
  /**
23810
   * Take the result value (move it).
23811
   *
23812
   * @throw simdjson_error if there was an error.
23813
   */
23814
  simdjson_inline T&& value() && noexcept(false);
23815
23816
  /**
23817
   * Take the result value (move it).
23818
   *
23819
   * @throw simdjson_error if there was an error.
23820
   */
23821
  simdjson_inline T&& take_value() && noexcept(false);
23822
23823
  /**
23824
   * Cast to the value (will throw on error).
23825
   *
23826
   * @throw simdjson_error if there was an error.
23827
   */
23828
  simdjson_inline operator T&&() && noexcept(false);
23829
23830
23831
#endif // SIMDJSON_EXCEPTIONS
23832
23833
  /**
23834
   * Get the result value. This function is safe if and only
23835
   * the error() method returns a value that evaluates to false.
23836
   */
23837
  simdjson_inline const T& value_unsafe() const& noexcept;
23838
  /**
23839
   * Get the result value. This function is safe if and only
23840
   * the error() method returns a value that evaluates to false.
23841
   */
23842
  simdjson_inline T& value_unsafe() & noexcept;
23843
  /**
23844
   * Take the result value (move it). This function is safe if and only
23845
   * the error() method returns a value that evaluates to false.
23846
   */
23847
  simdjson_inline T&& value_unsafe() && noexcept;
23848
protected:
23849
  /** users should never directly access first and second. **/
23850
  T first{}; /** Users should never directly access 'first'. **/
23851
  error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
23852
}; // struct implementation_simdjson_result_base
23853
23854
} // namespace westmere
23855
} // namespace simdjson
23856
23857
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
23858
/* end file simdjson/generic/implementation_simdjson_result_base.h for westmere */
23859
/* including simdjson/generic/numberparsing.h for westmere: #include "simdjson/generic/numberparsing.h" */
23860
/* begin file simdjson/generic/numberparsing.h for westmere */
23861
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
23862
23863
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
23864
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_NUMBERPARSING_H */
23865
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
23866
/* amalgamation skipped (editor-only): #include "simdjson/generic/jsoncharutils.h" */
23867
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
23868
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
23869
23870
#include <limits>
23871
#include <ostream>
23872
#include <cstring>
23873
23874
namespace simdjson {
23875
namespace westmere {
23876
namespace numberparsing {
23877
23878
#ifdef JSON_TEST_NUMBERS
23879
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
23880
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
23881
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
23882
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
23883
#define BIGINT_NUMBER(SRC) (found_invalid_number((SRC)), BIGINT_ERROR)
23884
#else
23885
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
23886
#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
23887
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
23888
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
23889
#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
23890
#endif
23891
23892
namespace {
23893
23894
// Convert a mantissa, an exponent and a sign bit into an ieee64 double.
23895
// The real_exponent needs to be in [0, 2046] (technically real_exponent = 2047 would be acceptable).
23896
// The mantissa should be in [0,1<<53). The bit at index (1ULL << 52) while be zeroed.
23897
simdjson_inline double to_double(uint64_t mantissa, uint64_t real_exponent, bool negative) {
23898
    double d;
23899
    mantissa &= ~(1ULL << 52);
23900
    mantissa |= real_exponent << 52;
23901
    mantissa |= ((static_cast<uint64_t>(negative)) << 63);
23902
    std::memcpy(&d, &mantissa, sizeof(d));
23903
    return d;
23904
}
23905
23906
// Attempts to compute i * 10^(power) exactly; and if "negative" is
23907
// true, negate the result.
23908
// This function will only work in some cases, when it does not work, success is
23909
// set to false. This should work *most of the time* (like 99% of the time).
23910
// We assume that power is in the [smallest_power,
23911
// largest_power] interval: the caller is responsible for this check.
23912
simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, double &d) {
23913
  // we start with a fast path
23914
  // It was described in
23915
  // Clinger WD. How to read floating point numbers accurately.
23916
  // ACM SIGPLAN Notices. 1990
23917
#ifndef FLT_EVAL_METHOD
23918
#error "FLT_EVAL_METHOD should be defined, please include cfloat."
23919
#endif
23920
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
23921
  // We cannot be certain that x/y is rounded to nearest.
23922
  if (0 <= power && power <= 22 && i <= 9007199254740991)
23923
#else
23924
  if (-22 <= power && power <= 22 && i <= 9007199254740991)
23925
#endif
23926
  {
23927
    // convert the integer into a double. This is lossless since
23928
    // 0 <= i <= 2^53 - 1.
23929
    d = double(i);
23930
    //
23931
    // The general idea is as follows.
23932
    // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
23933
    // 1) Both s and p can be represented exactly as 64-bit floating-point
23934
    // values
23935
    // (binary64).
23936
    // 2) Because s and p can be represented exactly as floating-point values,
23937
    // then s * p
23938
    // and s / p will produce correctly rounded values.
23939
    //
23940
    if (power < 0) {
23941
      d = d / simdjson::internal::power_of_ten[-power];
23942
    } else {
23943
      d = d * simdjson::internal::power_of_ten[power];
23944
    }
23945
    if (negative) {
23946
      d = -d;
23947
    }
23948
    return true;
23949
  }
23950
  // When 22 < power && power <  22 + 16, we could
23951
  // hope for another, secondary fast path.  It was
23952
  // described by David M. Gay in  "Correctly rounded
23953
  // binary-decimal and decimal-binary conversions." (1990)
23954
  // If you need to compute i * 10^(22 + x) for x < 16,
23955
  // first compute i * 10^x, if you know that result is exact
23956
  // (e.g., when i * 10^x < 2^53),
23957
  // then you can still proceed and do (i * 10^x) * 10^22.
23958
  // Is this worth your time?
23959
  // You need  22 < power *and* power <  22 + 16 *and* (i * 10^(x-22) < 2^53)
23960
  // for this second fast path to work.
23961
  // If you you have 22 < power *and* power <  22 + 16, and then you
23962
  // optimistically compute "i * 10^(x-22)", there is still a chance that you
23963
  // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
23964
  // this optimization maybe less common than we would like. Source:
23965
  // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
23966
  // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
23967
23968
  // The fast path has now failed, so we are failing back on the slower path.
23969
23970
  // In the slow path, we need to adjust i so that it is > 1<<63 which is always
23971
  // possible, except if i == 0, so we handle i == 0 separately.
23972
  if(i == 0) {
23973
    d = negative ? -0.0 : 0.0;
23974
    return true;
23975
  }
23976
23977
23978
  // The exponent is 1024 + 63 + power
23979
  //     + floor(log(5**power)/log(2)).
23980
  // The 1024 comes from the ieee64 standard.
23981
  // The 63 comes from the fact that we use a 64-bit word.
23982
  //
23983
  // Computing floor(log(5**power)/log(2)) could be
23984
  // slow. Instead we use a fast function.
23985
  //
23986
  // For power in (-400,350), we have that
23987
  // (((152170 + 65536) * power ) >> 16);
23988
  // is equal to
23989
  //  floor(log(5**power)/log(2)) + power when power >= 0
23990
  // and it is equal to
23991
  //  ceil(log(5**-power)/log(2)) + power when power < 0
23992
  //
23993
  // The 65536 is (1<<16) and corresponds to
23994
  // (65536 * power) >> 16 ---> power
23995
  //
23996
  // ((152170 * power ) >> 16) is equal to
23997
  // floor(log(5**power)/log(2))
23998
  //
23999
  // Note that this is not magic: 152170/(1<<16) is
24000
  // approximatively equal to log(5)/log(2).
24001
  // The 1<<16 value is a power of two; we could use a
24002
  // larger power of 2 if we wanted to.
24003
  //
24004
  int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
24005
24006
24007
  // We want the most significant bit of i to be 1. Shift if needed.
24008
  int lz = leading_zeroes(i);
24009
  i <<= lz;
24010
24011
24012
  // We are going to need to do some 64-bit arithmetic to get a precise product.
24013
  // We use a table lookup approach.
24014
  // It is safe because
24015
  // power >= smallest_power
24016
  // and power <= largest_power
24017
  // We recover the mantissa of the power, it has a leading 1. It is always
24018
  // rounded down.
24019
  //
24020
  // We want the most significant 64 bits of the product. We know
24021
  // this will be non-zero because the most significant bit of i is
24022
  // 1.
24023
  const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
24024
  // Optimization: It may be that materializing the index as a variable might confuse some compilers and prevent effective complex-addressing loads. (Done for code clarity.)
24025
  //
24026
  // The full_multiplication function computes the 128-bit product of two 64-bit words
24027
  // with a returned value of type value128 with a "low component" corresponding to the
24028
  // 64-bit least significant bits of the product and with a "high component" corresponding
24029
  // to the 64-bit most significant bits of the product.
24030
  simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
24031
  // Both i and power_of_five_128[index] have their most significant bit set to 1 which
24032
  // implies that the either the most or the second most significant bit of the product
24033
  // is 1. We pack values in this manner for efficiency reasons: it maximizes the use
24034
  // we make of the product. It also makes it easy to reason about the product: there
24035
  // is 0 or 1 leading zero in the product.
24036
24037
  // Unless the least significant 9 bits of the high (64-bit) part of the full
24038
  // product are all 1s, then we know that the most significant 55 bits are
24039
  // exact and no further work is needed. Having 55 bits is necessary because
24040
  // we need 53 bits for the mantissa but we have to have one rounding bit and
24041
  // we can waste a bit if the most significant bit of the product is zero.
24042
  if((firstproduct.high & 0x1FF) == 0x1FF) {
24043
    // We want to compute i * 5^q, but only care about the top 55 bits at most.
24044
    // Consider the scenario where q>=0. Then 5^q may not fit in 64-bits. Doing
24045
    // the full computation is wasteful. So we do what is called a "truncated
24046
    // multiplication".
24047
    // We take the most significant 64-bits, and we put them in
24048
    // power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
24049
    // to the desired approximation using one multiplication. Sometimes it does not suffice.
24050
    // Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
24051
    // then we get a better approximation to i * 5^q.
24052
    //
24053
    // That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
24054
    // more complicated.
24055
    //
24056
    // There is an extra layer of complexity in that we need more than 55 bits of
24057
    // accuracy in the round-to-even scenario.
24058
    //
24059
    // The full_multiplication function computes the 128-bit product of two 64-bit words
24060
    // with a returned value of type value128 with a "low component" corresponding to the
24061
    // 64-bit least significant bits of the product and with a "high component" corresponding
24062
    // to the 64-bit most significant bits of the product.
24063
    simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
24064
    firstproduct.low += secondproduct.high;
24065
    if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
24066
    // As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
24067
    // Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
24068
    // is sufficiently accurate, and more computation is not needed.
24069
  }
24070
  uint64_t lower = firstproduct.low;
24071
  uint64_t upper = firstproduct.high;
24072
  // The final mantissa should be 53 bits with a leading 1.
24073
  // We shift it so that it occupies 54 bits with a leading 1.
24074
  ///////
24075
  uint64_t upperbit = upper >> 63;
24076
  uint64_t mantissa = upper >> (upperbit + 9);
24077
  lz += int(1 ^ upperbit);
24078
24079
  // Here we have mantissa < (1<<54).
24080
  int64_t real_exponent = exponent - lz;
24081
  if (simdjson_unlikely(real_exponent <= 0)) { // we have a subnormal?
24082
    // Here have that real_exponent <= 0 so -real_exponent >= 0
24083
    if(-real_exponent + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
24084
      d = negative ? -0.0 : 0.0;
24085
      return true;
24086
    }
24087
    // next line is safe because -real_exponent + 1 < 0
24088
    mantissa >>= -real_exponent + 1;
24089
    // Thankfully, we can't have both "round-to-even" and subnormals because
24090
    // "round-to-even" only occurs for powers close to 0.
24091
    mantissa += (mantissa & 1); // round up
24092
    mantissa >>= 1;
24093
    // There is a weird scenario where we don't have a subnormal but just.
24094
    // Suppose we start with 2.2250738585072013e-308, we end up
24095
    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
24096
    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
24097
    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
24098
    // subnormal, but we can only know this after rounding.
24099
    // So we only declare a subnormal if we are smaller than the threshold.
24100
    real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
24101
    d = to_double(mantissa, real_exponent, negative);
24102
    return true;
24103
  }
24104
  // We have to round to even. The "to even" part
24105
  // is only a problem when we are right in between two floats
24106
  // which we guard against.
24107
  // If we have lots of trailing zeros, we may fall right between two
24108
  // floating-point values.
24109
  //
24110
  // The round-to-even cases take the form of a number 2m+1 which is in (2^53,2^54]
24111
  // times a power of two. That is, it is right between a number with binary significand
24112
  // m and another number with binary significand m+1; and it must be the case
24113
  // that it cannot be represented by a float itself.
24114
  //
24115
  // We must have that w * 10 ^q == (2m+1) * 2^p for some power of two 2^p.
24116
  // Recall that 10^q = 5^q * 2^q.
24117
  // When q >= 0, we must have that (2m+1) is divible by 5^q, so 5^q <= 2^54. We have that
24118
  //  5^23 <=  2^54 and it is the last power of five to qualify, so q <= 23.
24119
  // When q<0, we have  w  >=  (2m+1) x 5^{-q}.  We must have that w<2^{64} so
24120
  // (2m+1) x 5^{-q} < 2^{64}. We have that 2m+1>2^{53}. Hence, we must have
24121
  // 2^{53} x 5^{-q} < 2^{64}.
24122
  // Hence we have 5^{-q} < 2^{11}$ or q>= -4.
24123
  //
24124
  // We require lower <= 1 and not lower == 0 because we could not prove that
24125
  // that lower == 0 is implied; but we could prove that lower <= 1 is a necessary and sufficient test.
24126
  if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
24127
    if((mantissa  << (upperbit + 64 - 53 - 2)) ==  upper) {
24128
      mantissa &= ~1;             // flip it so that we do not round up
24129
    }
24130
  }
24131
24132
  mantissa += mantissa & 1;
24133
  mantissa >>= 1;
24134
24135
  // Here we have mantissa < (1<<53), unless there was an overflow
24136
  if (mantissa >= (1ULL << 53)) {
24137
    //////////
24138
    // This will happen when parsing values such as 7.2057594037927933e+16
24139
    ////////
24140
    mantissa = (1ULL << 52);
24141
    real_exponent++;
24142
  }
24143
  mantissa &= ~(1ULL << 52);
24144
  // we have to check that real_exponent is in range, otherwise we bail out
24145
  if (simdjson_unlikely(real_exponent > 2046)) {
24146
    // We have an infinite value!!! We could actually throw an error here if we could.
24147
    return false;
24148
  }
24149
  d = to_double(mantissa, real_exponent, negative);
24150
  return true;
24151
}
24152
24153
// We call a fallback floating-point parser that might be slow. Note
24154
// it will accept JSON numbers, but the JSON spec. is more restrictive so
24155
// before you call parse_float_fallback, you need to have validated the input
24156
// string with the JSON grammar.
24157
// It will return an error (false) if the parsed number is infinite.
24158
// The string parsing itself always succeeds. We know that there is at least
24159
// one digit.
24160
static bool parse_float_fallback(const uint8_t *ptr, double *outDouble) {
24161
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr));
24162
  // We do not accept infinite values.
24163
24164
  // Detecting finite values in a portable manner is ridiculously hard, ideally
24165
  // we would want to do:
24166
  // return !std::isfinite(*outDouble);
24167
  // but that mysteriously fails under legacy/old libc++ libraries, see
24168
  // https://github.com/simdjson/simdjson/issues/1286
24169
  //
24170
  // Therefore, fall back to this solution (the extra parens are there
24171
  // to handle that max may be a macro on windows).
24172
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
24173
}
24174
24175
static bool parse_float_fallback(const uint8_t *ptr, const uint8_t *end_ptr, double *outDouble) {
24176
  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr), reinterpret_cast<const char *>(end_ptr));
24177
  // We do not accept infinite values.
24178
24179
  // Detecting finite values in a portable manner is ridiculously hard, ideally
24180
  // we would want to do:
24181
  // return !std::isfinite(*outDouble);
24182
  // but that mysteriously fails under legacy/old libc++ libraries, see
24183
  // https://github.com/simdjson/simdjson/issues/1286
24184
  //
24185
  // Therefore, fall back to this solution (the extra parens are there
24186
  // to handle that max may be a macro on windows).
24187
  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
24188
}
24189
24190
// check quickly whether the next 8 chars are made of digits
24191
// at a glance, it looks better than Mula's
24192
// http://0x80.pl/articles/swar-digits-validate.html
24193
simdjson_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
24194
  uint64_t val;
24195
  // this can read up to 7 bytes beyond the buffer size, but we require
24196
  // SIMDJSON_PADDING of padding
24197
  static_assert(7 <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be bigger than 7");
24198
  std::memcpy(&val, chars, 8);
24199
  // a branchy method might be faster:
24200
  // return (( val & 0xF0F0F0F0F0F0F0F0 ) == 0x3030303030303030)
24201
  //  && (( (val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0 ) ==
24202
  //  0x3030303030303030);
24203
  return (((val & 0xF0F0F0F0F0F0F0F0) |
24204
           (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
24205
          0x3333333333333333);
24206
}
24207
24208
template<typename I>
24209
SIMDJSON_NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
24210
simdjson_inline bool parse_digit(const uint8_t c, I &i) {
24211
  const uint8_t digit = static_cast<uint8_t>(c - '0');
24212
  if (digit > 9) {
24213
    return false;
24214
  }
24215
  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
24216
  i = 10 * i + digit; // might overflow, we will handle the overflow later
24217
  return true;
24218
}
24219
24220
simdjson_inline bool is_digit(const uint8_t c) {
24221
  return static_cast<uint8_t>(c - '0') <= 9;
24222
}
24223
24224
simdjson_inline error_code parse_decimal_after_separator(simdjson_unused const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
24225
  // we continue with the fiction that we have an integer. If the
24226
  // floating point number is representable as x * 10^z for some integer
24227
  // z that fits in 53 bits, then we will be able to convert back the
24228
  // the integer into a float in a lossless manner.
24229
  const uint8_t *const first_after_period = p;
24230
24231
#ifdef SIMDJSON_SWAR_NUMBER_PARSING
24232
#if SIMDJSON_SWAR_NUMBER_PARSING
24233
  // this helps if we have lots of decimals!
24234
  // this turns out to be frequent enough.
24235
  if (is_made_of_eight_digits_fast(p)) {
24236
    i = i * 100000000 + parse_eight_digits_unrolled(p);
24237
    p += 8;
24238
  }
24239
#endif // SIMDJSON_SWAR_NUMBER_PARSING
24240
#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
24241
  // Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
24242
  if (parse_digit(*p, i)) { ++p; }
24243
  while (parse_digit(*p, i)) { p++; }
24244
  exponent = first_after_period - p;
24245
  // Decimal without digits (123.) is illegal
24246
  if (exponent == 0) {
24247
    return INVALID_NUMBER(src);
24248
  }
24249
  return SUCCESS;
24250
}
24251
24252
simdjson_inline error_code parse_exponent(simdjson_unused const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
24253
  // Exp Sign: -123.456e[-]78
24254
  bool neg_exp = ('-' == *p);
24255
  if (neg_exp || '+' == *p) { p++; } // Skip + as well
24256
24257
  // Exponent: -123.456e-[78]
24258
  auto start_exp = p;
24259
  int64_t exp_number = 0;
24260
  while (parse_digit(*p, exp_number)) { ++p; }
24261
  // It is possible for parse_digit to overflow.
24262
  // In particular, it could overflow to INT64_MIN, and we cannot do - INT64_MIN.
24263
  // Thus we *must* check for possible overflow before we negate exp_number.
24264
24265
  // Performance notes: it may seem like combining the two "simdjson_unlikely checks" below into
24266
  // a single simdjson_unlikely path would be faster. The reasoning is sound, but the compiler may
24267
  // not oblige and may, in fact, generate two distinct paths in any case. It might be
24268
  // possible to do uint64_t(p - start_exp - 1) >= 18 but it could end up trading off
24269
  // instructions for a simdjson_likely branch, an unconclusive gain.
24270
24271
  // If there were no digits, it's an error.
24272
  if (simdjson_unlikely(p == start_exp)) {
24273
    return INVALID_NUMBER(src);
24274
  }
24275
  // We have a valid positive exponent in exp_number at this point, except that
24276
  // it may have overflowed.
24277
24278
  // If there were more than 18 digits, we may have overflowed the integer. We have to do
24279
  // something!!!!
24280
  if (simdjson_unlikely(p > start_exp+18)) {
24281
    // Skip leading zeroes: 1e000000000000000000001 is technically valid and does not overflow
24282
    while (*start_exp == '0') { start_exp++; }
24283
    // 19 digits could overflow int64_t and is kind of absurd anyway. We don't
24284
    // support exponents smaller than -999,999,999,999,999,999 and bigger
24285
    // than 999,999,999,999,999,999.
24286
    // We can truncate.
24287
    // Note that 999999999999999999 is assuredly too large. The maximal ieee64 value before
24288
    // infinity is ~1.8e308. The smallest subnormal is ~5e-324. So, actually, we could
24289
    // truncate at 324.
24290
    // Note that there is no reason to fail per se at this point in time.
24291
    // E.g., 0e999999999999999999999 is a fine number.
24292
    if (p > start_exp+18) { exp_number = 999999999999999999; }
24293
  }
24294
  // At this point, we know that exp_number is a sane, positive, signed integer.
24295
  // It is <= 999,999,999,999,999,999. As long as 'exponent' is in
24296
  // [-8223372036854775808, 8223372036854775808], we won't overflow. Because 'exponent'
24297
  // is bounded in magnitude by the size of the JSON input, we are fine in this universe.
24298
  // To sum it up: the next line should never overflow.
24299
  exponent += (neg_exp ? -exp_number : exp_number);
24300
  return SUCCESS;
24301
}
24302
24303
simdjson_inline bool check_if_integer(const uint8_t *const src, size_t max_length) {
24304
  const uint8_t *const srcend = src + max_length;
24305
  bool negative = (*src == '-'); // we can always read at least one character after the '-'
24306
  const uint8_t *p = src + uint8_t(negative);
24307
  if(p == srcend) { return false; }
24308
  if(*p == '0') {
24309
    ++p;
24310
    if(p == srcend) { return true; }
24311
    if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
24312
    return true;
24313
  }
24314
  while(p != srcend && is_digit(*p)) { ++p; }
24315
  if(p == srcend) { return true; }
24316
  if(jsoncharutils::is_not_structural_or_whitespace(*p)) { return false; }
24317
  return true;
24318
}
24319
24320
simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
24321
  // It is possible that the integer had an overflow.
24322
  // We have to handle the case where we have 0.0000somenumber.
24323
  const uint8_t *start = start_digits;
24324
  while ((*start == '0') || (*start == '.')) { ++start; }
24325
  // we over-decrement by one when there is a '.'
24326
  return digit_count - size_t(start - start_digits);
24327
}
24328
24329
} // unnamed namespace
24330
24331
/** @private */
24332
static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
24333
  if (parse_float_fallback(src, answer)) {
24334
    return SUCCESS;
24335
  }
24336
  return INVALID_NUMBER(src);
24337
}
24338
24339
/** @private */
24340
template<typename W>
24341
simdjson_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
24342
  // If we frequently had to deal with long strings of digits,
24343
  // we could extend our code by using a 128-bit integer instead
24344
  // of a 64-bit integer. However, this is uncommon in practice.
24345
  //
24346
  // 9999999999999999999 < 2**64 so we can accommodate 19 digits.
24347
  // If we have a decimal separator, then digit_count - 1 is the number of digits, but we
24348
  // may not have a decimal separator!
24349
  if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
24350
    // Ok, chances are good that we had an overflow!
24351
    // this is almost never going to get called!!!
24352
    // we start anew, going slowly!!!
24353
    // This will happen in the following examples:
24354
    // 10000000000000000000000000000000000000000000e+308
24355
    // 3.1415926535897932384626433832795028841971693993751
24356
    //
24357
    // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
24358
    // reference to it, it would force it to be stored in memory, preventing the compiler from
24359
    // picking it apart and putting into registers. i.e. if we pass it as reference,
24360
    // it gets slow.
24361
    double d;
24362
    error_code error = slow_float_parsing(src, &d);
24363
    writer.append_double(d);
24364
    return error;
24365
  }
24366
  // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
24367
  // way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331
24368
  // To future reader: we'd love if someone found a better way, or at least could explain this result!
24369
  if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
24370
    //
24371
    // Important: smallest_power is such that it leads to a zero value.
24372
    // Observe that 18446744073709551615e-343 == 0, i.e. (2**64 - 1) e -343 is zero
24373
    // so something x 10^-343 goes to zero, but not so with  something x 10^-342.
24374
    static_assert(simdjson::internal::smallest_power <= -342, "smallest_power is not small enough");
24375
    //
24376
    if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
24377
      // E.g. Parse "-0.0e-999" into the same value as "-0.0". See https://en.wikipedia.org/wiki/Signed_zero
24378
      WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
24379
      return SUCCESS;
24380
    } else { // (exponent > largest_power) and (i != 0)
24381
      // We have, for sure, an infinite value and simdjson refuses to parse infinite values.
24382
      return INVALID_NUMBER(src);
24383
    }
24384
  }
24385
  double d;
24386
  if (!compute_float_64(exponent, i, negative, d)) {
24387
    // we are almost never going to get here.
24388
    if (!parse_float_fallback(src, &d)) { return INVALID_NUMBER(src); }
24389
  }
24390
  WRITE_DOUBLE(d, src, writer);
24391
  return SUCCESS;
24392
}
24393
24394
// parse the number at src
24395
// define JSON_TEST_NUMBERS for unit testing
24396
//
24397
// It is assumed that the number is followed by a structural ({,},],[) character
24398
// or a white space character. If that is not the case (e.g., when the JSON
24399
// document is made of a single number), then it is necessary to copy the
24400
// content and append a space before calling this function.
24401
//
24402
// Our objective is accurate parsing (ULP of 0) at high speed.
24403
template<typename W>
24404
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer);
24405
24406
// for performance analysis, it is sometimes  useful to skip parsing
24407
#ifdef SIMDJSON_SKIPNUMBERPARSING
24408
24409
template<typename W>
24410
simdjson_inline error_code parse_number(const uint8_t *const, W &writer) {
24411
  writer.append_s64(0);        // always write zero
24412
  return SUCCESS;              // always succeeds
24413
}
24414
24415
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
24416
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
24417
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
24418
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept { return 0; }
24419
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t * const src) noexcept { return 0; }
24420
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * const src) noexcept { return 0; }
24421
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept  { return false; }
24422
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept  { return false; }
24423
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept { return number_type::signed_integer; }
24424
#else
24425
24426
// parse the number at src
24427
// define JSON_TEST_NUMBERS for unit testing
24428
//
24429
// It is assumed that the number is followed by a structural ({,},],[) character
24430
// or a white space character. If that is not the case (e.g., when the JSON
24431
// document is made of a single number), then it is necessary to copy the
24432
// content and append a space before calling this function.
24433
//
24434
// Our objective is accurate parsing (ULP of 0) at high speed.
24435
template<typename W>
24436
simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) {
24437
24438
  //
24439
  // Check for minus sign
24440
  //
24441
  bool negative = (*src == '-');
24442
  const uint8_t *p = src + uint8_t(negative);
24443
24444
  //
24445
  // Parse the integer part.
24446
  //
24447
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
24448
  const uint8_t *const start_digits = p;
24449
  uint64_t i = 0;
24450
  while (parse_digit(*p, i)) { p++; }
24451
24452
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
24453
  // Optimization note: size_t is expected to be unsigned.
24454
  size_t digit_count = size_t(p - start_digits);
24455
  if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
24456
24457
  //
24458
  // Handle floats if there is a . or e (or both)
24459
  //
24460
  int64_t exponent = 0;
24461
  bool is_float = false;
24462
  if ('.' == *p) {
24463
    is_float = true;
24464
    ++p;
24465
    SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
24466
    digit_count = int(p - start_digits); // used later to guard against overflows
24467
  }
24468
  if (('e' == *p) || ('E' == *p)) {
24469
    is_float = true;
24470
    ++p;
24471
    SIMDJSON_TRY( parse_exponent(src, p, exponent) );
24472
  }
24473
  if (is_float) {
24474
    const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
24475
    SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
24476
    if (dirty_end) { return INVALID_NUMBER(src); }
24477
    return SUCCESS;
24478
  }
24479
24480
  // The longest negative 64-bit number is 19 digits.
24481
  // The longest positive 64-bit number is 20 digits.
24482
  // We do it this way so we don't trigger this branch unless we must.
24483
  size_t longest_digit_count = negative ? 19 : 20;
24484
  if (digit_count > longest_digit_count) { return BIGINT_NUMBER(src); }
24485
  if (digit_count == longest_digit_count) {
24486
    if (negative) {
24487
      // Anything negative above INT64_MAX+1 is invalid
24488
      if (i > uint64_t(INT64_MAX)+1) { return BIGINT_NUMBER(src);  }
24489
      WRITE_INTEGER(~i+1, src, writer);
24490
      if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
24491
      return SUCCESS;
24492
    // Positive overflow check:
24493
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
24494
    //   biggest uint64_t.
24495
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
24496
    //   If we got here, it's a 20 digit number starting with the digit "1".
24497
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
24498
    //   than 1,553,255,926,290,448,384.
24499
    // - That is smaller than the smallest possible 20-digit number the user could write:
24500
    //   10,000,000,000,000,000,000.
24501
    // - Therefore, if the number is positive and lower than that, it's overflow.
24502
    // - The value we are looking at is less than or equal to INT64_MAX.
24503
    //
24504
    }  else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
24505
  }
24506
24507
  // Write unsigned if it does not fit in a signed integer.
24508
  if (i > uint64_t(INT64_MAX)) {
24509
    WRITE_UNSIGNED(i, src, writer);
24510
  } else {
24511
    WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
24512
  }
24513
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
24514
  return SUCCESS;
24515
}
24516
24517
// Inlineable functions
24518
namespace {
24519
24520
// This table can be used to characterize the final character of an integer
24521
// string. For JSON structural character and allowable white space characters,
24522
// we return SUCCESS. For 'e', '.' and 'E', we return INCORRECT_TYPE. Otherwise
24523
// we return NUMBER_ERROR.
24524
// Optimization note: we could easily reduce the size of the table by half (to 128)
24525
// at the cost of an extra branch.
24526
// Optimization note: we want the values to use at most 8 bits (not, e.g., 32 bits):
24527
static_assert(error_code(uint8_t(NUMBER_ERROR))== NUMBER_ERROR, "bad NUMBER_ERROR cast");
24528
static_assert(error_code(uint8_t(SUCCESS))== SUCCESS, "bad NUMBER_ERROR cast");
24529
static_assert(error_code(uint8_t(INCORRECT_TYPE))== INCORRECT_TYPE, "bad NUMBER_ERROR cast");
24530
24531
const uint8_t integer_string_finisher[256] = {
24532
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24533
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
24534
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
24535
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24536
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24537
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24538
    NUMBER_ERROR, NUMBER_ERROR,   SUCCESS,      NUMBER_ERROR, NUMBER_ERROR,
24539
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24540
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
24541
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24542
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24543
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
24544
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24545
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, INCORRECT_TYPE,
24546
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24547
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24548
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24549
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24550
    NUMBER_ERROR, SUCCESS,        NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
24551
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24552
    NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24553
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24554
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24555
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24556
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, SUCCESS,      NUMBER_ERROR,
24557
    SUCCESS,      NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24558
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24559
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24560
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24561
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24562
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24563
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24564
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24565
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24566
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24567
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24568
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24569
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24570
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24571
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24572
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24573
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24574
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24575
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24576
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24577
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24578
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24579
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24580
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24581
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24582
    NUMBER_ERROR, NUMBER_ERROR,   NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
24583
    NUMBER_ERROR};
24584
24585
// Parse any number from 0 to 18,446,744,073,709,551,615
24586
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept {
24587
  const uint8_t *p = src;
24588
  //
24589
  // Parse the integer part.
24590
  //
24591
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
24592
  const uint8_t *const start_digits = p;
24593
  uint64_t i = 0;
24594
  while (parse_digit(*p, i)) { p++; }
24595
24596
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
24597
  // Optimization note: size_t is expected to be unsigned.
24598
  size_t digit_count = size_t(p - start_digits);
24599
  // The longest positive 64-bit number is 20 digits.
24600
  // We do it this way so we don't trigger this branch unless we must.
24601
  // Optimization note: the compiler can probably merge
24602
  // ((digit_count == 0) || (digit_count > 20))
24603
  // into a single  branch since digit_count is unsigned.
24604
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
24605
  // Here digit_count > 0.
24606
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
24607
  // We can do the following...
24608
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
24609
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
24610
  // }
24611
  // as a single table lookup:
24612
  if (integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
24613
24614
  if (digit_count == 20) {
24615
    // Positive overflow check:
24616
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
24617
    //   biggest uint64_t.
24618
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
24619
    //   If we got here, it's a 20 digit number starting with the digit "1".
24620
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
24621
    //   than 1,553,255,926,290,448,384.
24622
    // - That is smaller than the smallest possible 20-digit number the user could write:
24623
    //   10,000,000,000,000,000,000.
24624
    // - Therefore, if the number is positive and lower than that, it's overflow.
24625
    // - The value we are looking at is less than or equal to INT64_MAX.
24626
    //
24627
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
24628
  }
24629
24630
  return i;
24631
}
24632
24633
24634
// Parse any number from 0 to 18,446,744,073,709,551,615
24635
// Never read at src_end or beyond
24636
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src, const uint8_t * const src_end) noexcept {
24637
  const uint8_t *p = src;
24638
  //
24639
  // Parse the integer part.
24640
  //
24641
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
24642
  const uint8_t *const start_digits = p;
24643
  uint64_t i = 0;
24644
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
24645
24646
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
24647
  // Optimization note: size_t is expected to be unsigned.
24648
  size_t digit_count = size_t(p - start_digits);
24649
  // The longest positive 64-bit number is 20 digits.
24650
  // We do it this way so we don't trigger this branch unless we must.
24651
  // Optimization note: the compiler can probably merge
24652
  // ((digit_count == 0) || (digit_count > 20))
24653
  // into a single  branch since digit_count is unsigned.
24654
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
24655
  // Here digit_count > 0.
24656
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
24657
  // We can do the following...
24658
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
24659
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
24660
  // }
24661
  // as a single table lookup:
24662
  if ((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
24663
24664
  if (digit_count == 20) {
24665
    // Positive overflow check:
24666
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
24667
    //   biggest uint64_t.
24668
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
24669
    //   If we got here, it's a 20 digit number starting with the digit "1".
24670
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
24671
    //   than 1,553,255,926,290,448,384.
24672
    // - That is smaller than the smallest possible 20-digit number the user could write:
24673
    //   10,000,000,000,000,000,000.
24674
    // - Therefore, if the number is positive and lower than that, it's overflow.
24675
    // - The value we are looking at is less than or equal to INT64_MAX.
24676
    //
24677
    if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
24678
  }
24679
24680
  return i;
24681
}
24682
24683
// Parse any number from 0 to 18,446,744,073,709,551,615
24684
simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept {
24685
  const uint8_t *p = src + 1;
24686
  //
24687
  // Parse the integer part.
24688
  //
24689
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
24690
  const uint8_t *const start_digits = p;
24691
  uint64_t i = 0;
24692
  while (parse_digit(*p, i)) { p++; }
24693
24694
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
24695
  // Optimization note: size_t is expected to be unsigned.
24696
  size_t digit_count = size_t(p - start_digits);
24697
  // The longest positive 64-bit number is 20 digits.
24698
  // We do it this way so we don't trigger this branch unless we must.
24699
  // Optimization note: the compiler can probably merge
24700
  // ((digit_count == 0) || (digit_count > 20))
24701
  // into a single  branch since digit_count is unsigned.
24702
  if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
24703
  // Here digit_count > 0.
24704
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
24705
  // We can do the following...
24706
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
24707
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
24708
  // }
24709
  // as a single table lookup:
24710
  if (*p != '"') { return NUMBER_ERROR; }
24711
24712
  if (digit_count == 20) {
24713
    // Positive overflow check:
24714
    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
24715
    //   biggest uint64_t.
24716
    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
24717
    //   If we got here, it's a 20 digit number starting with the digit "1".
24718
    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
24719
    //   than 1,553,255,926,290,448,384.
24720
    // - That is smaller than the smallest possible 20-digit number the user could write:
24721
    //   10,000,000,000,000,000,000.
24722
    // - Therefore, if the number is positive and lower than that, it's overflow.
24723
    // - The value we are looking at is less than or equal to INT64_MAX.
24724
    //
24725
    // Note: we use src[1] and not src[0] because src[0] is the quote character in this
24726
    // instance.
24727
    if (src[1] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
24728
  }
24729
24730
  return i;
24731
}
24732
24733
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
24734
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
24735
  //
24736
  // Check for minus sign
24737
  //
24738
  bool negative = (*src == '-');
24739
  const uint8_t *p = src + uint8_t(negative);
24740
24741
  //
24742
  // Parse the integer part.
24743
  //
24744
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
24745
  const uint8_t *const start_digits = p;
24746
  uint64_t i = 0;
24747
  while (parse_digit(*p, i)) { p++; }
24748
24749
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
24750
  // Optimization note: size_t is expected to be unsigned.
24751
  size_t digit_count = size_t(p - start_digits);
24752
  // We go from
24753
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
24754
  // so we can never represent numbers that have more than 19 digits.
24755
  size_t longest_digit_count = 19;
24756
  // Optimization note: the compiler can probably merge
24757
  // ((digit_count == 0) || (digit_count > longest_digit_count))
24758
  // into a single  branch since digit_count is unsigned.
24759
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
24760
  // Here digit_count > 0.
24761
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
24762
  // We can do the following...
24763
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
24764
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
24765
  // }
24766
  // as a single table lookup:
24767
  if(integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
24768
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
24769
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
24770
  // so cheap that we might as well always make it.
24771
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
24772
  return negative ? (~i+1) : i;
24773
}
24774
24775
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
24776
// Never read at src_end or beyond
24777
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src, const uint8_t * const src_end) noexcept {
24778
  //
24779
  // Check for minus sign
24780
  //
24781
  if(src == src_end) { return NUMBER_ERROR; }
24782
  bool negative = (*src == '-');
24783
  const uint8_t *p = src + uint8_t(negative);
24784
24785
  //
24786
  // Parse the integer part.
24787
  //
24788
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
24789
  const uint8_t *const start_digits = p;
24790
  uint64_t i = 0;
24791
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
24792
24793
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
24794
  // Optimization note: size_t is expected to be unsigned.
24795
  size_t digit_count = size_t(p - start_digits);
24796
  // We go from
24797
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
24798
  // so we can never represent numbers that have more than 19 digits.
24799
  size_t longest_digit_count = 19;
24800
  // Optimization note: the compiler can probably merge
24801
  // ((digit_count == 0) || (digit_count > longest_digit_count))
24802
  // into a single  branch since digit_count is unsigned.
24803
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
24804
  // Here digit_count > 0.
24805
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
24806
  // We can do the following...
24807
  // if (!jsoncharutils::is_structural_or_whitespace(*p)) {
24808
  //  return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
24809
  // }
24810
  // as a single table lookup:
24811
  if((p != src_end) && integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
24812
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
24813
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
24814
  // so cheap that we might as well always make it.
24815
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
24816
  return negative ? (~i+1) : i;
24817
}
24818
24819
// Parse any number from  -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
24820
simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t *src) noexcept {
24821
  //
24822
  // Check for minus sign
24823
  //
24824
  bool negative = (*(src + 1) == '-');
24825
  src += uint8_t(negative) + 1;
24826
24827
  //
24828
  // Parse the integer part.
24829
  //
24830
  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
24831
  const uint8_t *const start_digits = src;
24832
  uint64_t i = 0;
24833
  while (parse_digit(*src, i)) { src++; }
24834
24835
  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
24836
  // Optimization note: size_t is expected to be unsigned.
24837
  size_t digit_count = size_t(src - start_digits);
24838
  // We go from
24839
  // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
24840
  // so we can never represent numbers that have more than 19 digits.
24841
  size_t longest_digit_count = 19;
24842
  // Optimization note: the compiler can probably merge
24843
  // ((digit_count == 0) || (digit_count > longest_digit_count))
24844
  // into a single  branch since digit_count is unsigned.
24845
  if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
24846
  // Here digit_count > 0.
24847
  if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
24848
  // We can do the following...
24849
  // if (!jsoncharutils::is_structural_or_whitespace(*src)) {
24850
  //  return (*src == '.' || *src == 'e' || *src == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
24851
  // }
24852
  // as a single table lookup:
24853
  if(*src != '"') { return NUMBER_ERROR; }
24854
  // Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
24855
  // Performance note: This check is only needed when digit_count == longest_digit_count but it is
24856
  // so cheap that we might as well always make it.
24857
  if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
24858
  return negative ? (~i+1) : i;
24859
}
24860
24861
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
24862
  //
24863
  // Check for minus sign
24864
  //
24865
  bool negative = (*src == '-');
24866
  src += uint8_t(negative);
24867
24868
  //
24869
  // Parse the integer part.
24870
  //
24871
  uint64_t i = 0;
24872
  const uint8_t *p = src;
24873
  p += parse_digit(*p, i);
24874
  bool leading_zero = (i == 0);
24875
  while (parse_digit(*p, i)) { p++; }
24876
  // no integer digits, or 0123 (zero must be solo)
24877
  if ( p == src ) { return INCORRECT_TYPE; }
24878
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
24879
24880
  //
24881
  // Parse the decimal part.
24882
  //
24883
  int64_t exponent = 0;
24884
  bool overflow;
24885
  if (simdjson_likely(*p == '.')) {
24886
    p++;
24887
    const uint8_t *start_decimal_digits = p;
24888
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
24889
    p++;
24890
    while (parse_digit(*p, i)) { p++; }
24891
    exponent = -(p - start_decimal_digits);
24892
24893
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
24894
    overflow = p-src-1 > 19;
24895
    if (simdjson_unlikely(overflow && leading_zero)) {
24896
      // Skip leading 0.00000 and see if it still overflows
24897
      const uint8_t *start_digits = src + 2;
24898
      while (*start_digits == '0') { start_digits++; }
24899
      overflow = p-start_digits > 19;
24900
    }
24901
  } else {
24902
    overflow = p-src > 19;
24903
  }
24904
24905
  //
24906
  // Parse the exponent
24907
  //
24908
  if (*p == 'e' || *p == 'E') {
24909
    p++;
24910
    bool exp_neg = *p == '-';
24911
    p += exp_neg || *p == '+';
24912
24913
    uint64_t exp = 0;
24914
    const uint8_t *start_exp_digits = p;
24915
    while (parse_digit(*p, exp)) { p++; }
24916
    // no exp digits, or 20+ exp digits
24917
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
24918
24919
    exponent += exp_neg ? 0-exp : exp;
24920
  }
24921
24922
  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
24923
24924
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
24925
24926
  //
24927
  // Assemble (or slow-parse) the float
24928
  //
24929
  double d;
24930
  if (simdjson_likely(!overflow)) {
24931
    if (compute_float_64(exponent, i, negative, d)) { return d; }
24932
  }
24933
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
24934
    return NUMBER_ERROR;
24935
  }
24936
  return d;
24937
}
24938
24939
simdjson_unused simdjson_inline bool is_negative(const uint8_t * src) noexcept {
24940
  return (*src == '-');
24941
}
24942
24943
simdjson_unused simdjson_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept {
24944
  bool negative = (*src == '-');
24945
  src += uint8_t(negative);
24946
  const uint8_t *p = src;
24947
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
24948
  if ( p == src ) { return NUMBER_ERROR; }
24949
  if (jsoncharutils::is_structural_or_whitespace(*p)) { return true; }
24950
  return false;
24951
}
24952
24953
simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(const uint8_t * src) noexcept {
24954
  bool negative = (*src == '-');
24955
  src += uint8_t(negative);
24956
  const uint8_t *p = src;
24957
  while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
24958
  size_t digit_count = size_t(p - src);
24959
  if ( p == src ) { return NUMBER_ERROR; }
24960
  if (jsoncharutils::is_structural_or_whitespace(*p)) {
24961
    static const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
24962
    // We have an integer.
24963
    if(simdjson_unlikely(digit_count > 20)) {
24964
      return number_type::big_integer;
24965
    }
24966
    // If the number is negative and valid, it must be a signed integer.
24967
    if(negative) {
24968
      if (simdjson_unlikely(digit_count > 19)) return number_type::big_integer;
24969
      if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) {
24970
        return number_type::big_integer;
24971
      }
24972
      return number_type::signed_integer;
24973
    }
24974
    // Let us check if we have a big integer (>=2**64).
24975
    static const uint8_t * two_to_sixtyfour = reinterpret_cast<const uint8_t *>("18446744073709551616");
24976
    if((digit_count > 20) || (digit_count == 20 && memcmp(src, two_to_sixtyfour, 20) >= 0)) {
24977
      return number_type::big_integer;
24978
    }
24979
    // The number is positive and smaller than 18446744073709551616 (or 2**64).
24980
    // We want values larger or equal to 9223372036854775808 to be unsigned
24981
    // integers, and the other values to be signed integers.
24982
    if((digit_count == 20) || (digit_count >= 19 && memcmp(src, smaller_big_integer, 19) >= 0)) {
24983
      return number_type::unsigned_integer;
24984
    }
24985
    return number_type::signed_integer;
24986
  }
24987
  // Hopefully, we have 'e' or 'E' or '.'.
24988
  return number_type::floating_point_number;
24989
}
24990
24991
// Never read at src_end or beyond
24992
simdjson_unused simdjson_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
24993
  if(src == src_end) { return NUMBER_ERROR; }
24994
  //
24995
  // Check for minus sign
24996
  //
24997
  bool negative = (*src == '-');
24998
  src += uint8_t(negative);
24999
25000
  //
25001
  // Parse the integer part.
25002
  //
25003
  uint64_t i = 0;
25004
  const uint8_t *p = src;
25005
  if(p == src_end) { return NUMBER_ERROR; }
25006
  p += parse_digit(*p, i);
25007
  bool leading_zero = (i == 0);
25008
  while ((p != src_end) && parse_digit(*p, i)) { p++; }
25009
  // no integer digits, or 0123 (zero must be solo)
25010
  if ( p == src ) { return INCORRECT_TYPE; }
25011
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
25012
25013
  //
25014
  // Parse the decimal part.
25015
  //
25016
  int64_t exponent = 0;
25017
  bool overflow;
25018
  if (simdjson_likely((p != src_end) && (*p == '.'))) {
25019
    p++;
25020
    const uint8_t *start_decimal_digits = p;
25021
    if ((p == src_end) || !parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
25022
    p++;
25023
    while ((p != src_end) && parse_digit(*p, i)) { p++; }
25024
    exponent = -(p - start_decimal_digits);
25025
25026
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
25027
    overflow = p-src-1 > 19;
25028
    if (simdjson_unlikely(overflow && leading_zero)) {
25029
      // Skip leading 0.00000 and see if it still overflows
25030
      const uint8_t *start_digits = src + 2;
25031
      while (*start_digits == '0') { start_digits++; }
25032
      overflow = start_digits-src > 19;
25033
    }
25034
  } else {
25035
    overflow = p-src > 19;
25036
  }
25037
25038
  //
25039
  // Parse the exponent
25040
  //
25041
  if ((p != src_end) && (*p == 'e' || *p == 'E')) {
25042
    p++;
25043
    if(p == src_end) { return NUMBER_ERROR; }
25044
    bool exp_neg = *p == '-';
25045
    p += exp_neg || *p == '+';
25046
25047
    uint64_t exp = 0;
25048
    const uint8_t *start_exp_digits = p;
25049
    while ((p != src_end) && parse_digit(*p, exp)) { p++; }
25050
    // no exp digits, or 20+ exp digits
25051
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
25052
25053
    exponent += exp_neg ? 0-exp : exp;
25054
  }
25055
25056
  if ((p != src_end) && jsoncharutils::is_not_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
25057
25058
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
25059
25060
  //
25061
  // Assemble (or slow-parse) the float
25062
  //
25063
  double d;
25064
  if (simdjson_likely(!overflow)) {
25065
    if (compute_float_64(exponent, i, negative, d)) { return d; }
25066
  }
25067
  if (!parse_float_fallback(src - uint8_t(negative), src_end, &d)) {
25068
    return NUMBER_ERROR;
25069
  }
25070
  return d;
25071
}
25072
25073
simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(const uint8_t * src) noexcept {
25074
  //
25075
  // Check for minus sign
25076
  //
25077
  bool negative = (*(src + 1) == '-');
25078
  src += uint8_t(negative) + 1;
25079
25080
  //
25081
  // Parse the integer part.
25082
  //
25083
  uint64_t i = 0;
25084
  const uint8_t *p = src;
25085
  p += parse_digit(*p, i);
25086
  bool leading_zero = (i == 0);
25087
  while (parse_digit(*p, i)) { p++; }
25088
  // no integer digits, or 0123 (zero must be solo)
25089
  if ( p == src ) { return INCORRECT_TYPE; }
25090
  if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
25091
25092
  //
25093
  // Parse the decimal part.
25094
  //
25095
  int64_t exponent = 0;
25096
  bool overflow;
25097
  if (simdjson_likely(*p == '.')) {
25098
    p++;
25099
    const uint8_t *start_decimal_digits = p;
25100
    if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
25101
    p++;
25102
    while (parse_digit(*p, i)) { p++; }
25103
    exponent = -(p - start_decimal_digits);
25104
25105
    // Overflow check. More than 19 digits (minus the decimal) may be overflow.
25106
    overflow = p-src-1 > 19;
25107
    if (simdjson_unlikely(overflow && leading_zero)) {
25108
      // Skip leading 0.00000 and see if it still overflows
25109
      const uint8_t *start_digits = src + 2;
25110
      while (*start_digits == '0') { start_digits++; }
25111
      overflow = p-start_digits > 19;
25112
    }
25113
  } else {
25114
    overflow = p-src > 19;
25115
  }
25116
25117
  //
25118
  // Parse the exponent
25119
  //
25120
  if (*p == 'e' || *p == 'E') {
25121
    p++;
25122
    bool exp_neg = *p == '-';
25123
    p += exp_neg || *p == '+';
25124
25125
    uint64_t exp = 0;
25126
    const uint8_t *start_exp_digits = p;
25127
    while (parse_digit(*p, exp)) { p++; }
25128
    // no exp digits, or 20+ exp digits
25129
    if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
25130
25131
    exponent += exp_neg ? 0-exp : exp;
25132
  }
25133
25134
  if (*p != '"') { return NUMBER_ERROR; }
25135
25136
  overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
25137
25138
  //
25139
  // Assemble (or slow-parse) the float
25140
  //
25141
  double d;
25142
  if (simdjson_likely(!overflow)) {
25143
    if (compute_float_64(exponent, i, negative, d)) { return d; }
25144
  }
25145
  if (!parse_float_fallback(src - uint8_t(negative), &d)) {
25146
    return NUMBER_ERROR;
25147
  }
25148
  return d;
25149
}
25150
25151
} // unnamed namespace
25152
#endif // SIMDJSON_SKIPNUMBERPARSING
25153
25154
} // namespace numberparsing
25155
25156
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
25157
    switch (type) {
25158
        case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
25159
        case number_type::unsigned_integer: out << "unsigned integer in [9223372036854775808,18446744073709551616)"; break;
25160
        case number_type::floating_point_number: out << "floating-point number (binary64)"; break;
25161
        case number_type::big_integer: out << "big integer"; break;
25162
        default: SIMDJSON_UNREACHABLE();
25163
    }
25164
    return out;
25165
}
25166
25167
} // namespace westmere
25168
} // namespace simdjson
25169
25170
#endif // SIMDJSON_GENERIC_NUMBERPARSING_H
25171
/* end file simdjson/generic/numberparsing.h for westmere */
25172
25173
/* including simdjson/generic/implementation_simdjson_result_base-inl.h for westmere: #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
25174
/* begin file simdjson/generic/implementation_simdjson_result_base-inl.h for westmere */
25175
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
25176
25177
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25178
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H */
25179
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
25180
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
25181
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25182
25183
namespace simdjson {
25184
namespace westmere {
25185
25186
//
25187
// internal::implementation_simdjson_result_base<T> inline implementation
25188
//
25189
25190
template<typename T>
25191
simdjson_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
25192
  error = this->second;
25193
  if (!error) {
25194
    value = std::forward<implementation_simdjson_result_base<T>>(*this).first;
25195
  }
25196
}
25197
25198
template<typename T>
25199
simdjson_warn_unused simdjson_inline error_code implementation_simdjson_result_base<T>::get(T &value) && noexcept {
25200
  error_code error;
25201
  std::forward<implementation_simdjson_result_base<T>>(*this).tie(value, error);
25202
  return error;
25203
}
25204
25205
template<typename T>
25206
simdjson_inline error_code implementation_simdjson_result_base<T>::error() const noexcept {
25207
  return this->second;
25208
}
25209
25210
#if SIMDJSON_EXCEPTIONS
25211
25212
template<typename T>
25213
simdjson_inline T& implementation_simdjson_result_base<T>::value() & noexcept(false) {
25214
  if (error()) { throw simdjson_error(error()); }
25215
  return this->first;
25216
}
25217
25218
template<typename T>
25219
simdjson_inline T&& implementation_simdjson_result_base<T>::value() && noexcept(false) {
25220
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
25221
}
25222
25223
template<typename T>
25224
simdjson_inline T&& implementation_simdjson_result_base<T>::take_value() && noexcept(false) {
25225
  if (error()) { throw simdjson_error(error()); }
25226
  return std::forward<T>(this->first);
25227
}
25228
25229
template<typename T>
25230
simdjson_inline implementation_simdjson_result_base<T>::operator T&&() && noexcept(false) {
25231
  return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
25232
}
25233
25234
#endif // SIMDJSON_EXCEPTIONS
25235
25236
template<typename T>
25237
simdjson_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
25238
  return this->first;
25239
}
25240
25241
template<typename T>
25242
simdjson_inline T& implementation_simdjson_result_base<T>::value_unsafe() & noexcept {
25243
  return this->first;
25244
}
25245
25246
template<typename T>
25247
simdjson_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
25248
  return std::forward<T>(this->first);
25249
}
25250
25251
template<typename T>
25252
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
25253
    : first{std::forward<T>(value)}, second{error} {}
25254
template<typename T>
25255
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(error_code error) noexcept
25256
    : implementation_simdjson_result_base(T{}, error) {}
25257
template<typename T>
25258
simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
25259
    : implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
25260
25261
} // namespace westmere
25262
} // namespace simdjson
25263
25264
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
25265
/* end file simdjson/generic/implementation_simdjson_result_base-inl.h for westmere */
25266
/* end file simdjson/generic/amalgamated.h for westmere */
25267
/* including simdjson/westmere/end.h: #include "simdjson/westmere/end.h" */
25268
/* begin file simdjson/westmere/end.h */
25269
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25270
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
25271
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25272
25273
#if !SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
25274
SIMDJSON_UNTARGET_REGION
25275
#endif
25276
25277
/* undefining SIMDJSON_IMPLEMENTATION from "westmere" */
25278
#undef SIMDJSON_IMPLEMENTATION
25279
/* end file simdjson/westmere/end.h */
25280
25281
#endif // SIMDJSON_WESTMERE_H
25282
/* end file simdjson/westmere.h */
25283
#else
25284
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
25285
#endif
25286
25287
/* undefining SIMDJSON_CONDITIONAL_INCLUDE */
25288
#undef SIMDJSON_CONDITIONAL_INCLUDE
25289
25290
#endif // SIMDJSON_BUILTIN_H
25291
/* end file simdjson/builtin.h */
25292
/* skipped duplicate #include "simdjson/builtin/base.h" */
25293
25294
/* including simdjson/generic/ondemand/dependencies.h: #include "simdjson/generic/ondemand/dependencies.h" */
25295
/* begin file simdjson/generic/ondemand/dependencies.h */
25296
#ifdef SIMDJSON_CONDITIONAL_INCLUDE
25297
#error simdjson/generic/ondemand/dependencies.h must be included before defining SIMDJSON_CONDITIONAL_INCLUDE!
25298
#endif
25299
25300
#ifndef SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H
25301
#define SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H
25302
25303
// Internal headers needed for ondemand generics.
25304
// All includes not under simdjson/generic/ondemand must be here!
25305
// Otherwise, amalgamation will fail.
25306
/* skipped duplicate #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */
25307
/* skipped duplicate #include "simdjson/implementation.h" */
25308
/* skipped duplicate #include "simdjson/padded_string.h" */
25309
/* skipped duplicate #include "simdjson/padded_string_view.h" */
25310
/* skipped duplicate #include "simdjson/internal/dom_parser_implementation.h" */
25311
25312
#endif // SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H
25313
/* end file simdjson/generic/ondemand/dependencies.h */
25314
25315
/* defining SIMDJSON_CONDITIONAL_INCLUDE */
25316
#define SIMDJSON_CONDITIONAL_INCLUDE
25317
25318
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
25319
/* including simdjson/arm64/ondemand.h: #include "simdjson/arm64/ondemand.h" */
25320
/* begin file simdjson/arm64/ondemand.h */
25321
#ifndef SIMDJSON_ARM64_ONDEMAND_H
25322
#define SIMDJSON_ARM64_ONDEMAND_H
25323
25324
/* including simdjson/arm64/begin.h: #include "simdjson/arm64/begin.h" */
25325
/* begin file simdjson/arm64/begin.h */
25326
/* defining SIMDJSON_IMPLEMENTATION to "arm64" */
25327
#define SIMDJSON_IMPLEMENTATION arm64
25328
/* including simdjson/arm64/base.h: #include "simdjson/arm64/base.h" */
25329
/* begin file simdjson/arm64/base.h */
25330
#ifndef SIMDJSON_ARM64_BASE_H
25331
#define SIMDJSON_ARM64_BASE_H
25332
25333
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25334
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
25335
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25336
25337
namespace simdjson {
25338
/**
25339
 * Implementation for NEON (ARMv8).
25340
 */
25341
namespace arm64 {
25342
25343
class implementation;
25344
25345
namespace {
25346
namespace simd {
25347
template <typename T> struct simd8;
25348
template <typename T> struct simd8x64;
25349
} // namespace simd
25350
} // unnamed namespace
25351
25352
} // namespace arm64
25353
} // namespace simdjson
25354
25355
#endif // SIMDJSON_ARM64_BASE_H
25356
/* end file simdjson/arm64/base.h */
25357
/* including simdjson/arm64/intrinsics.h: #include "simdjson/arm64/intrinsics.h" */
25358
/* begin file simdjson/arm64/intrinsics.h */
25359
#ifndef SIMDJSON_ARM64_INTRINSICS_H
25360
#define SIMDJSON_ARM64_INTRINSICS_H
25361
25362
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25363
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
25364
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25365
25366
// This should be the correct header whether
25367
// you use visual studio or other compilers.
25368
#include <arm_neon.h>
25369
25370
static_assert(sizeof(uint8x16_t) <= simdjson::SIMDJSON_PADDING, "insufficient padding for arm64");
25371
25372
#endif //  SIMDJSON_ARM64_INTRINSICS_H
25373
/* end file simdjson/arm64/intrinsics.h */
25374
/* including simdjson/arm64/bitmanipulation.h: #include "simdjson/arm64/bitmanipulation.h" */
25375
/* begin file simdjson/arm64/bitmanipulation.h */
25376
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
25377
#define SIMDJSON_ARM64_BITMANIPULATION_H
25378
25379
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25380
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
25381
/* amalgamation skipped (editor-only): #include "simdjson/arm64/intrinsics.h" */
25382
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25383
25384
namespace simdjson {
25385
namespace arm64 {
25386
namespace {
25387
25388
// We sometimes call trailing_zero on inputs that are zero,
25389
// but the algorithms do not end up using the returned value.
25390
// Sadly, sanitizers are not smart enough to figure it out.
25391
SIMDJSON_NO_SANITIZE_UNDEFINED
25392
// This function can be used safely even if not all bytes have been
25393
// initialized.
25394
// See issue https://github.com/simdjson/simdjson/issues/1965
25395
SIMDJSON_NO_SANITIZE_MEMORY
25396
simdjson_inline int trailing_zeroes(uint64_t input_num) {
25397
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25398
  unsigned long ret;
25399
  // Search the mask data from least significant bit (LSB)
25400
  // to the most significant bit (MSB) for a set bit (1).
25401
  _BitScanForward64(&ret, input_num);
25402
  return (int)ret;
25403
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
25404
  return __builtin_ctzll(input_num);
25405
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
25406
}
25407
25408
/* result might be undefined when input_num is zero */
25409
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
25410
  return input_num & (input_num-1);
25411
}
25412
25413
/* result might be undefined when input_num is zero */
25414
simdjson_inline int leading_zeroes(uint64_t input_num) {
25415
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25416
  unsigned long leading_zero = 0;
25417
  // Search the mask data from most significant bit (MSB)
25418
  // to least significant bit (LSB) for a set bit (1).
25419
  if (_BitScanReverse64(&leading_zero, input_num))
25420
    return (int)(63 - leading_zero);
25421
  else
25422
    return 64;
25423
#else
25424
  return __builtin_clzll(input_num);
25425
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
25426
}
25427
25428
/* result might be undefined when input_num is zero */
25429
simdjson_inline int count_ones(uint64_t input_num) {
25430
   return vaddv_u8(vcnt_u8(vcreate_u8(input_num)));
25431
}
25432
25433
25434
#if defined(__GNUC__) // catches clang and gcc
25435
/**
25436
 * ARM has a fast 64-bit "bit reversal function" that is handy. However,
25437
 * it is not generally available as an intrinsic function under Visual
25438
 * Studio (though this might be changing). Even under clang/gcc, we
25439
 * apparently need to invoke inline assembly.
25440
 */
25441
/*
25442
 * We use SIMDJSON_PREFER_REVERSE_BITS as a hint that algorithms that
25443
 * work well with bit reversal may use it.
25444
 */
25445
#define SIMDJSON_PREFER_REVERSE_BITS 1
25446
25447
/* reverse the bits */
25448
simdjson_inline uint64_t reverse_bits(uint64_t input_num) {
25449
  uint64_t rev_bits;
25450
  __asm("rbit %0, %1" : "=r"(rev_bits) : "r"(input_num));
25451
  return rev_bits;
25452
}
25453
25454
/**
25455
 * Flips bit at index 63 - lz. Thus if you have 'leading_zeroes' leading zeroes,
25456
 * then this will set to zero the leading bit. It is possible for leading_zeroes to be
25457
 * greating or equal to 63 in which case we trigger undefined behavior, but the output
25458
 * of such undefined behavior is never used.
25459
 **/
25460
SIMDJSON_NO_SANITIZE_UNDEFINED
25461
simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
25462
  return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
25463
}
25464
25465
#endif
25466
25467
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
25468
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25469
  *result = value1 + value2;
25470
  return *result < value1;
25471
#else
25472
  return __builtin_uaddll_overflow(value1, value2,
25473
                                   reinterpret_cast<unsigned long long *>(result));
25474
#endif
25475
}
25476
25477
} // unnamed namespace
25478
} // namespace arm64
25479
} // namespace simdjson
25480
25481
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
25482
/* end file simdjson/arm64/bitmanipulation.h */
25483
/* including simdjson/arm64/bitmask.h: #include "simdjson/arm64/bitmask.h" */
25484
/* begin file simdjson/arm64/bitmask.h */
25485
#ifndef SIMDJSON_ARM64_BITMASK_H
25486
#define SIMDJSON_ARM64_BITMASK_H
25487
25488
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25489
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
25490
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25491
25492
namespace simdjson {
25493
namespace arm64 {
25494
namespace {
25495
25496
//
25497
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
25498
//
25499
// For example, prefix_xor(00100100) == 00011100
25500
//
25501
simdjson_inline uint64_t prefix_xor(uint64_t bitmask) {
25502
  /////////////
25503
  // We could do this with PMULL, but it is apparently slow.
25504
  //
25505
  //#ifdef __ARM_FEATURE_CRYPTO // some ARM processors lack this extension
25506
  //return vmull_p64(-1ULL, bitmask);
25507
  //#else
25508
  // Analysis by @sebpop:
25509
  // When diffing the assembly for src/stage1_find_marks.cpp I see that the eors are all spread out
25510
  // in between other vector code, so effectively the extra cycles of the sequence do not matter
25511
  // because the GPR units are idle otherwise and the critical path is on the FP side.
25512
  // Also the PMULL requires two extra fmovs: GPR->FP (3 cycles in N1, 5 cycles in A72 )
25513
  // and FP->GPR (2 cycles on N1 and 5 cycles on A72.)
25514
  ///////////
25515
  bitmask ^= bitmask << 1;
25516
  bitmask ^= bitmask << 2;
25517
  bitmask ^= bitmask << 4;
25518
  bitmask ^= bitmask << 8;
25519
  bitmask ^= bitmask << 16;
25520
  bitmask ^= bitmask << 32;
25521
  return bitmask;
25522
}
25523
25524
} // unnamed namespace
25525
} // namespace arm64
25526
} // namespace simdjson
25527
25528
#endif
25529
/* end file simdjson/arm64/bitmask.h */
25530
/* including simdjson/arm64/numberparsing_defs.h: #include "simdjson/arm64/numberparsing_defs.h" */
25531
/* begin file simdjson/arm64/numberparsing_defs.h */
25532
#ifndef SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
25533
#define SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
25534
25535
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25536
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
25537
/* amalgamation skipped (editor-only): #include "simdjson/arm64/intrinsics.h" */
25538
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
25539
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25540
25541
#include <cstring>
25542
25543
#if _M_ARM64
25544
// __umulh requires intrin.h
25545
#include <intrin.h>
25546
#endif // _M_ARM64
25547
25548
namespace simdjson {
25549
namespace arm64 {
25550
namespace numberparsing {
25551
25552
// we don't have SSE, so let us use a scalar function
25553
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
25554
/** @private */
25555
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
25556
  uint64_t val;
25557
  std::memcpy(&val, chars, sizeof(uint64_t));
25558
  val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
25559
  val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
25560
  return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
25561
}
25562
25563
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
25564
  internal::value128 answer;
25565
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
25566
#ifdef _M_ARM64
25567
  // ARM64 has native support for 64-bit multiplications, no need to emultate
25568
  answer.high = __umulh(value1, value2);
25569
  answer.low = value1 * value2;
25570
#else
25571
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
25572
#endif // _M_ARM64
25573
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
25574
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
25575
  answer.low = uint64_t(r);
25576
  answer.high = uint64_t(r >> 64);
25577
#endif
25578
  return answer;
25579
}
25580
25581
} // namespace numberparsing
25582
} // namespace arm64
25583
} // namespace simdjson
25584
25585
#define SIMDJSON_SWAR_NUMBER_PARSING 1
25586
25587
#endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
25588
/* end file simdjson/arm64/numberparsing_defs.h */
25589
/* including simdjson/arm64/simd.h: #include "simdjson/arm64/simd.h" */
25590
/* begin file simdjson/arm64/simd.h */
25591
#ifndef SIMDJSON_ARM64_SIMD_H
25592
#define SIMDJSON_ARM64_SIMD_H
25593
25594
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
25595
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
25596
/* amalgamation skipped (editor-only): #include "simdjson/arm64/bitmanipulation.h" */
25597
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
25598
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
25599
25600
namespace simdjson {
25601
namespace arm64 {
25602
namespace {
25603
namespace simd {
25604
25605
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25606
namespace {
25607
// Start of private section with Visual Studio workaround
25608
25609
25610
#ifndef simdjson_make_uint8x16_t
25611
#define simdjson_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
25612
                             x13, x14, x15, x16)                                   \
25613
   ([=]() {                                                                        \
25614
     uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,                    \
25615
                                 x9, x10, x11, x12, x13, x14, x15, x16};           \
25616
     return vld1q_u8(array);                                                       \
25617
   }())
25618
#endif
25619
#ifndef simdjson_make_int8x16_t
25620
#define simdjson_make_int8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
25621
                             x13, x14, x15, x16)                                  \
25622
   ([=]() {                                                                       \
25623
     int8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,                    \
25624
                                 x9, x10, x11, x12, x13, x14, x15, x16};          \
25625
     return vld1q_s8(array);                                                      \
25626
   }())
25627
#endif
25628
25629
#ifndef simdjson_make_uint8x8_t
25630
#define simdjson_make_uint8x8_t(x1, x2, x3, x4, x5, x6, x7, x8)                \
25631
   ([=]() {                                                                    \
25632
     uint8_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};                \
25633
     return vld1_u8(array);                                                    \
25634
   }())
25635
#endif
25636
#ifndef simdjson_make_int8x8_t
25637
#define simdjson_make_int8x8_t(x1, x2, x3, x4, x5, x6, x7, x8)                 \
25638
   ([=]() {                                                                    \
25639
     int8_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};                 \
25640
     return vld1_s8(array);                                                    \
25641
   }())
25642
#endif
25643
#ifndef simdjson_make_uint16x8_t
25644
#define simdjson_make_uint16x8_t(x1, x2, x3, x4, x5, x6, x7, x8)               \
25645
   ([=]() {                                                                    \
25646
     uint16_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};               \
25647
     return vld1q_u16(array);                                                  \
25648
   }())
25649
#endif
25650
#ifndef simdjson_make_int16x8_t
25651
#define simdjson_make_int16x8_t(x1, x2, x3, x4, x5, x6, x7, x8)                \
25652
   ([=]() {                                                                    \
25653
     int16_t array[8] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8};                \
25654
     return vld1q_s16(array);                                                  \
25655
   }())
25656
#endif
25657
25658
// End of private section with Visual Studio workaround
25659
} // namespace
25660
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
25661
25662
25663
  template<typename T>
25664
  struct simd8;
25665
25666
  //
25667
  // Base class of simd8<uint8_t> and simd8<bool>, both of which use uint8x16_t internally.
25668
  //
25669
  template<typename T, typename Mask=simd8<bool>>
25670
  struct base_u8 {
25671
    uint8x16_t value;
25672
    static const int SIZE = sizeof(value);
25673
25674
    // Conversion from/to SIMD register
25675
    simdjson_inline base_u8(const uint8x16_t _value) : value(_value) {}
25676
    simdjson_inline operator const uint8x16_t&() const { return this->value; }
25677
    simdjson_inline operator uint8x16_t&() { return this->value; }
25678
25679
    // Bit operations
25680
    simdjson_inline simd8<T> operator|(const simd8<T> other) const { return vorrq_u8(*this, other); }
25681
    simdjson_inline simd8<T> operator&(const simd8<T> other) const { return vandq_u8(*this, other); }
25682
    simdjson_inline simd8<T> operator^(const simd8<T> other) const { return veorq_u8(*this, other); }
25683
    simdjson_inline simd8<T> bit_andnot(const simd8<T> other) const { return vbicq_u8(*this, other); }
25684
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
25685
    simdjson_inline simd8<T>& operator|=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast | other; return *this_cast; }
25686
    simdjson_inline simd8<T>& operator&=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast & other; return *this_cast; }
25687
    simdjson_inline simd8<T>& operator^=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
25688
25689
    friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return vceqq_u8(lhs, rhs); }
25690
25691
    template<int N=1>
25692
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
25693
      return vextq_u8(prev_chunk, *this, 16 - N);
25694
    }
25695
  };
25696
25697
  // SIMD byte mask type (returned by things like eq and gt)
25698
  template<>
25699
  struct simd8<bool>: base_u8<bool> {
25700
    typedef uint16_t bitmask_t;
25701
    typedef uint32_t bitmask2_t;
25702
25703
    static simdjson_inline simd8<bool> splat(bool _value) { return vmovq_n_u8(uint8_t(-(!!_value))); }
25704
25705
    simdjson_inline simd8(const uint8x16_t _value) : base_u8<bool>(_value) {}
25706
    // False constructor
25707
    simdjson_inline simd8() : simd8(vdupq_n_u8(0)) {}
25708
    // Splat constructor
25709
    simdjson_inline simd8(bool _value) : simd8(splat(_value)) {}
25710
25711
    // We return uint32_t instead of uint16_t because that seems to be more efficient for most
25712
    // purposes (cutting it down to uint16_t costs performance in some compilers).
25713
    simdjson_inline uint32_t to_bitmask() const {
25714
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25715
      const uint8x16_t bit_mask =  simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
25716
                                                   0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
25717
#else
25718
      const uint8x16_t bit_mask =  {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
25719
                                    0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
25720
#endif
25721
      auto minput = *this & bit_mask;
25722
      uint8x16_t tmp = vpaddq_u8(minput, minput);
25723
      tmp = vpaddq_u8(tmp, tmp);
25724
      tmp = vpaddq_u8(tmp, tmp);
25725
      return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
25726
    }
25727
    simdjson_inline bool any() const { return vmaxvq_u8(*this) != 0; }
25728
  };
25729
25730
  // Unsigned bytes
25731
  template<>
25732
  struct simd8<uint8_t>: base_u8<uint8_t> {
25733
    static simdjson_inline uint8x16_t splat(uint8_t _value) { return vmovq_n_u8(_value); }
25734
    static simdjson_inline uint8x16_t zero() { return vdupq_n_u8(0); }
25735
    static simdjson_inline uint8x16_t load(const uint8_t* values) { return vld1q_u8(values); }
25736
25737
    simdjson_inline simd8(const uint8x16_t _value) : base_u8<uint8_t>(_value) {}
25738
    // Zero constructor
25739
    simdjson_inline simd8() : simd8(zero()) {}
25740
    // Array constructor
25741
    simdjson_inline simd8(const uint8_t values[16]) : simd8(load(values)) {}
25742
    // Splat constructor
25743
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
25744
    // Member-by-member initialization
25745
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25746
    simdjson_inline simd8(
25747
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
25748
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
25749
    ) : simd8(simdjson_make_uint8x16_t(
25750
      v0, v1, v2, v3, v4, v5, v6, v7,
25751
      v8, v9, v10,v11,v12,v13,v14,v15
25752
    )) {}
25753
#else
25754
    simdjson_inline simd8(
25755
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
25756
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
25757
    ) : simd8(uint8x16_t{
25758
      v0, v1, v2, v3, v4, v5, v6, v7,
25759
      v8, v9, v10,v11,v12,v13,v14,v15
25760
    }) {}
25761
#endif
25762
25763
    // Repeat 16 values as many times as necessary (usually for lookup tables)
25764
    simdjson_inline static simd8<uint8_t> repeat_16(
25765
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
25766
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
25767
    ) {
25768
      return simd8<uint8_t>(
25769
        v0, v1, v2, v3, v4, v5, v6, v7,
25770
        v8, v9, v10,v11,v12,v13,v14,v15
25771
      );
25772
    }
25773
25774
    // Store to array
25775
    simdjson_inline void store(uint8_t dst[16]) const { return vst1q_u8(dst, *this); }
25776
25777
    // Saturated math
25778
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return vqaddq_u8(*this, other); }
25779
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return vqsubq_u8(*this, other); }
25780
25781
    // Addition/subtraction are the same for signed and unsigned
25782
    simdjson_inline simd8<uint8_t> operator+(const simd8<uint8_t> other) const { return vaddq_u8(*this, other); }
25783
    simdjson_inline simd8<uint8_t> operator-(const simd8<uint8_t> other) const { return vsubq_u8(*this, other); }
25784
    simdjson_inline simd8<uint8_t>& operator+=(const simd8<uint8_t> other) { *this = *this + other; return *this; }
25785
    simdjson_inline simd8<uint8_t>& operator-=(const simd8<uint8_t> other) { *this = *this - other; return *this; }
25786
25787
    // Order-specific operations
25788
    simdjson_inline uint8_t max_val() const { return vmaxvq_u8(*this); }
25789
    simdjson_inline uint8_t min_val() const { return vminvq_u8(*this); }
25790
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return vmaxq_u8(*this, other); }
25791
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return vminq_u8(*this, other); }
25792
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return vcleq_u8(*this, other); }
25793
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return vcgeq_u8(*this, other); }
25794
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return vcltq_u8(*this, other); }
25795
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return vcgtq_u8(*this, other); }
25796
    // Same as >, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero. For ARM, returns all 1's.
25797
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return simd8<uint8_t>(*this > other); }
25798
    // Same as <, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero. For ARM, returns all 1's.
25799
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return simd8<uint8_t>(*this < other); }
25800
25801
    // Bit-specific operations
25802
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return vtstq_u8(*this, bits); }
25803
    simdjson_inline bool any_bits_set_anywhere() const { return this->max_val() != 0; }
25804
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return (*this & bits).any_bits_set_anywhere(); }
25805
    template<int N>
25806
    simdjson_inline simd8<uint8_t> shr() const { return vshrq_n_u8(*this, N); }
25807
    template<int N>
25808
    simdjson_inline simd8<uint8_t> shl() const { return vshlq_n_u8(*this, N); }
25809
25810
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
25811
    template<typename L>
25812
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
25813
      return lookup_table.apply_lookup_16_to(*this);
25814
    }
25815
25816
25817
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
25818
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
25819
    // Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
25820
    // get written.
25821
    // Design consideration: it seems like a function with the
25822
    // signature simd8<L> compress(uint16_t mask) would be
25823
    // sensible, but the AVX ISA makes this kind of approach difficult.
25824
    template<typename L>
25825
    simdjson_inline void compress(uint16_t mask, L * output) const {
25826
      using internal::thintable_epi8;
25827
      using internal::BitsSetTable256mul2;
25828
      using internal::pshufb_combine_table;
25829
      // this particular implementation was inspired by work done by @animetosho
25830
      // we do it in two steps, first 8 bytes and then second 8 bytes
25831
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
25832
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
25833
      // next line just loads the 64-bit values thintable_epi8[mask1] and
25834
      // thintable_epi8[mask2] into a 128-bit register, using only
25835
      // two instructions on most compilers.
25836
      uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]};
25837
      uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64);
25838
      // we increment by 0x08 the second half of the mask
25839
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25840
      uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
25841
#else
25842
      uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
25843
#endif
25844
      shufmask = vaddq_u8(shufmask, inc);
25845
      // this is the version "nearly pruned"
25846
      uint8x16_t pruned = vqtbl1q_u8(*this, shufmask);
25847
      // we still need to put the two halves together.
25848
      // we compute the popcount of the first half:
25849
      int pop1 = BitsSetTable256mul2[mask1];
25850
      // then load the corresponding mask, what it does is to write
25851
      // only the first pop1 bytes from the first 8 bytes, and then
25852
      // it fills in with the bytes from the second 8 bytes + some filling
25853
      // at the end.
25854
      uint8x16_t compactmask = vld1q_u8(reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
25855
      uint8x16_t answer = vqtbl1q_u8(pruned, compactmask);
25856
      vst1q_u8(reinterpret_cast<uint8_t*>(output), answer);
25857
    }
25858
25859
    // Copies all bytes corresponding to a 0 in the low half of the mask (interpreted as a
25860
    // bitset) to output1, then those corresponding to a 0 in the high half to output2.
25861
    template<typename L>
25862
    simdjson_inline void compress_halves(uint16_t mask, L *output1, L *output2) const {
25863
      using internal::thintable_epi8;
25864
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
25865
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
25866
      uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]);
25867
      uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]);
25868
      // we increment by 0x08 the second half of the mask
25869
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25870
      uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
25871
#else
25872
      uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
25873
#endif
25874
      compactmask2 = vadd_u8(compactmask2, inc);
25875
      // store each result (with the second store possibly overlapping the first)
25876
      vst1_u8((uint8_t*)output1, vqtbl1_u8(*this, compactmask1));
25877
      vst1_u8((uint8_t*)output2, vqtbl1_u8(*this, compactmask2));
25878
    }
25879
25880
    template<typename L>
25881
    simdjson_inline simd8<L> lookup_16(
25882
        L replace0,  L replace1,  L replace2,  L replace3,
25883
        L replace4,  L replace5,  L replace6,  L replace7,
25884
        L replace8,  L replace9,  L replace10, L replace11,
25885
        L replace12, L replace13, L replace14, L replace15) const {
25886
      return lookup_16(simd8<L>::repeat_16(
25887
        replace0,  replace1,  replace2,  replace3,
25888
        replace4,  replace5,  replace6,  replace7,
25889
        replace8,  replace9,  replace10, replace11,
25890
        replace12, replace13, replace14, replace15
25891
      ));
25892
    }
25893
25894
    template<typename T>
25895
    simdjson_inline simd8<uint8_t> apply_lookup_16_to(const simd8<T> original) {
25896
      return vqtbl1q_u8(*this, simd8<uint8_t>(original));
25897
    }
25898
  };
25899
25900
  // Signed bytes
25901
  template<>
25902
  struct simd8<int8_t> {
25903
    int8x16_t value;
25904
25905
    static simdjson_inline simd8<int8_t> splat(int8_t _value) { return vmovq_n_s8(_value); }
25906
    static simdjson_inline simd8<int8_t> zero() { return vdupq_n_s8(0); }
25907
    static simdjson_inline simd8<int8_t> load(const int8_t values[16]) { return vld1q_s8(values); }
25908
25909
    // Conversion from/to SIMD register
25910
    simdjson_inline simd8(const int8x16_t _value) : value{_value} {}
25911
    simdjson_inline operator const int8x16_t&() const { return this->value; }
25912
    simdjson_inline operator int8x16_t&() { return this->value; }
25913
25914
    // Zero constructor
25915
    simdjson_inline simd8() : simd8(zero()) {}
25916
    // Splat constructor
25917
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
25918
    // Array constructor
25919
    simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {}
25920
    // Member-by-member initialization
25921
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
25922
    simdjson_inline simd8(
25923
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3, int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
25924
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
25925
    ) : simd8(simdjson_make_int8x16_t(
25926
      v0, v1, v2, v3, v4, v5, v6, v7,
25927
      v8, v9, v10,v11,v12,v13,v14,v15
25928
    )) {}
25929
#else
25930
    simdjson_inline simd8(
25931
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3, int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
25932
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
25933
    ) : simd8(int8x16_t{
25934
      v0, v1, v2, v3, v4, v5, v6, v7,
25935
      v8, v9, v10,v11,v12,v13,v14,v15
25936
    }) {}
25937
#endif
25938
    // Repeat 16 values as many times as necessary (usually for lookup tables)
25939
    simdjson_inline static simd8<int8_t> repeat_16(
25940
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
25941
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
25942
    ) {
25943
      return simd8<int8_t>(
25944
        v0, v1, v2, v3, v4, v5, v6, v7,
25945
        v8, v9, v10,v11,v12,v13,v14,v15
25946
      );
25947
    }
25948
25949
    // Store to array
25950
    simdjson_inline void store(int8_t dst[16]) const { return vst1q_s8(dst, *this); }
25951
25952
    // Explicit conversion to/from unsigned
25953
    //
25954
    // Under Visual Studio/ARM64 uint8x16_t and int8x16_t are apparently the same type.
25955
    // In theory, we could check this occurrence with std::same_as and std::enabled_if but it is C++14
25956
    // and relatively ugly and hard to read.
25957
#ifndef SIMDJSON_REGULAR_VISUAL_STUDIO
25958
    simdjson_inline explicit simd8(const uint8x16_t other): simd8(vreinterpretq_s8_u8(other)) {}
25959
#endif
25960
    simdjson_inline explicit operator simd8<uint8_t>() const { return vreinterpretq_u8_s8(this->value); }
25961
25962
    // Math
25963
    simdjson_inline simd8<int8_t> operator+(const simd8<int8_t> other) const { return vaddq_s8(*this, other); }
25964
    simdjson_inline simd8<int8_t> operator-(const simd8<int8_t> other) const { return vsubq_s8(*this, other); }
25965
    simdjson_inline simd8<int8_t>& operator+=(const simd8<int8_t> other) { *this = *this + other; return *this; }
25966
    simdjson_inline simd8<int8_t>& operator-=(const simd8<int8_t> other) { *this = *this - other; return *this; }
25967
25968
    // Order-sensitive comparisons
25969
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return vmaxq_s8(*this, other); }
25970
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return vminq_s8(*this, other); }
25971
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return vcgtq_s8(*this, other); }
25972
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return vcltq_s8(*this, other); }
25973
    simdjson_inline simd8<bool> operator==(const simd8<int8_t> other) const { return vceqq_s8(*this, other); }
25974
25975
    template<int N=1>
25976
    simdjson_inline simd8<int8_t> prev(const simd8<int8_t> prev_chunk) const {
25977
      return vextq_s8(prev_chunk, *this, 16 - N);
25978
    }
25979
25980
    // Perform a lookup assuming no value is larger than 16
25981
    template<typename L>
25982
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
25983
      return lookup_table.apply_lookup_16_to(*this);
25984
    }
25985
    template<typename L>
25986
    simdjson_inline simd8<L> lookup_16(
25987
        L replace0,  L replace1,  L replace2,  L replace3,
25988
        L replace4,  L replace5,  L replace6,  L replace7,
25989
        L replace8,  L replace9,  L replace10, L replace11,
25990
        L replace12, L replace13, L replace14, L replace15) const {
25991
      return lookup_16(simd8<L>::repeat_16(
25992
        replace0,  replace1,  replace2,  replace3,
25993
        replace4,  replace5,  replace6,  replace7,
25994
        replace8,  replace9,  replace10, replace11,
25995
        replace12, replace13, replace14, replace15
25996
      ));
25997
    }
25998
25999
    template<typename T>
26000
    simdjson_inline simd8<int8_t> apply_lookup_16_to(const simd8<T> original) {
26001
      return vqtbl1q_s8(*this, simd8<uint8_t>(original));
26002
    }
26003
  };
26004
26005
  template<typename T>
26006
  struct simd8x64 {
26007
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
26008
    static_assert(NUM_CHUNKS == 4, "ARM kernel should use four registers per 64-byte block.");
26009
    const simd8<T> chunks[NUM_CHUNKS];
26010
26011
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
26012
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
26013
    simd8x64() = delete; // no default constructor allowed
26014
26015
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
26016
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
26017
26018
    simdjson_inline void store(T ptr[64]) const {
26019
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
26020
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
26021
      this->chunks[2].store(ptr+sizeof(simd8<T>)*2);
26022
      this->chunks[3].store(ptr+sizeof(simd8<T>)*3);
26023
    }
26024
26025
    simdjson_inline simd8<T> reduce_or() const {
26026
      return (this->chunks[0] | this->chunks[1]) | (this->chunks[2] | this->chunks[3]);
26027
    }
26028
26029
26030
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
26031
      uint64_t popcounts = vget_lane_u64(vreinterpret_u64_u8(vcnt_u8(vcreate_u8(~mask))), 0);
26032
      // compute the prefix sum of the popcounts of each byte
26033
      uint64_t offsets = popcounts * 0x0101010101010101;
26034
      this->chunks[0].compress_halves(uint16_t(mask), output, &output[popcounts & 0xFF]);
26035
      this->chunks[1].compress_halves(uint16_t(mask >> 16), &output[(offsets >> 8) & 0xFF], &output[(offsets >> 16) & 0xFF]);
26036
      this->chunks[2].compress_halves(uint16_t(mask >> 32), &output[(offsets >> 24) & 0xFF], &output[(offsets >> 32) & 0xFF]);
26037
      this->chunks[3].compress_halves(uint16_t(mask >> 48), &output[(offsets >> 40) & 0xFF], &output[(offsets >> 48) & 0xFF]);
26038
      return offsets >> 56;
26039
    }
26040
26041
    simdjson_inline uint64_t to_bitmask() const {
26042
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
26043
      const uint8x16_t bit_mask = simdjson_make_uint8x16_t(
26044
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
26045
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
26046
      );
26047
#else
26048
      const uint8x16_t bit_mask = {
26049
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
26050
        0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
26051
      };
26052
#endif
26053
      // Add each of the elements next to each other, successively, to stuff each 8 byte mask into one.
26054
      uint8x16_t sum0 = vpaddq_u8(this->chunks[0] & bit_mask, this->chunks[1] & bit_mask);
26055
      uint8x16_t sum1 = vpaddq_u8(this->chunks[2] & bit_mask, this->chunks[3] & bit_mask);
26056
      sum0 = vpaddq_u8(sum0, sum1);
26057
      sum0 = vpaddq_u8(sum0, sum0);
26058
      return vgetq_lane_u64(vreinterpretq_u64_u8(sum0), 0);
26059
    }
26060
26061
    simdjson_inline uint64_t eq(const T m) const {
26062
      const simd8<T> mask = simd8<T>::splat(m);
26063
      return  simd8x64<bool>(
26064
        this->chunks[0] == mask,
26065
        this->chunks[1] == mask,
26066
        this->chunks[2] == mask,
26067
        this->chunks[3] == mask
26068
      ).to_bitmask();
26069
    }
26070
26071
    simdjson_inline uint64_t lteq(const T m) const {
26072
      const simd8<T> mask = simd8<T>::splat(m);
26073
      return  simd8x64<bool>(
26074
        this->chunks[0] <= mask,
26075
        this->chunks[1] <= mask,
26076
        this->chunks[2] <= mask,
26077
        this->chunks[3] <= mask
26078
      ).to_bitmask();
26079
    }
26080
  }; // struct simd8x64<T>
26081
26082
} // namespace simd
26083
} // unnamed namespace
26084
} // namespace arm64
26085
} // namespace simdjson
26086
26087
#endif // SIMDJSON_ARM64_SIMD_H
26088
/* end file simdjson/arm64/simd.h */
26089
/* including simdjson/arm64/stringparsing_defs.h: #include "simdjson/arm64/stringparsing_defs.h" */
26090
/* begin file simdjson/arm64/stringparsing_defs.h */
26091
#ifndef SIMDJSON_ARM64_STRINGPARSING_DEFS_H
26092
#define SIMDJSON_ARM64_STRINGPARSING_DEFS_H
26093
26094
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
26095
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
26096
/* amalgamation skipped (editor-only): #include "simdjson/arm64/simd.h" */
26097
/* amalgamation skipped (editor-only): #include "simdjson/arm64/bitmanipulation.h" */
26098
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
26099
26100
namespace simdjson {
26101
namespace arm64 {
26102
namespace {
26103
26104
using namespace simd;
26105
26106
// Holds backslashes and quotes locations.
26107
struct backslash_and_quote {
26108
public:
26109
  static constexpr uint32_t BYTES_PROCESSED = 32;
26110
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
26111
26112
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
26113
  simdjson_inline bool has_backslash() { return bs_bits != 0; }
26114
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
26115
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
26116
26117
  uint32_t bs_bits;
26118
  uint32_t quote_bits;
26119
}; // struct backslash_and_quote
26120
26121
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
26122
  // this can read up to 31 bytes beyond the buffer size, but we require
26123
  // SIMDJSON_PADDING of padding
26124
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
26125
  simd8<uint8_t> v0(src);
26126
  simd8<uint8_t> v1(src + sizeof(v0));
26127
  v0.store(dst);
26128
  v1.store(dst + sizeof(v0));
26129
26130
  // Getting a 64-bit bitmask is much cheaper than multiple 16-bit bitmasks on ARM; therefore, we
26131
  // smash them together into a 64-byte mask and get the bitmask from there.
26132
  uint64_t bs_and_quote = simd8x64<bool>(v0 == '\\', v1 == '\\', v0 == '"', v1 == '"').to_bitmask();
26133
  return {
26134
    uint32_t(bs_and_quote),      // bs_bits
26135
    uint32_t(bs_and_quote >> 32) // quote_bits
26136
  };
26137
}
26138
26139
} // unnamed namespace
26140
} // namespace arm64
26141
} // namespace simdjson
26142
26143
#endif // SIMDJSON_ARM64_STRINGPARSING_DEFS_H
26144
/* end file simdjson/arm64/stringparsing_defs.h */
26145
26146
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
26147
/* end file simdjson/arm64/begin.h */
26148
/* including simdjson/generic/ondemand/amalgamated.h for arm64: #include "simdjson/generic/ondemand/amalgamated.h" */
26149
/* begin file simdjson/generic/ondemand/amalgamated.h for arm64 */
26150
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
26151
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
26152
#endif
26153
26154
// Stuff other things depend on
26155
/* including simdjson/generic/ondemand/base.h for arm64: #include "simdjson/generic/ondemand/base.h" */
26156
/* begin file simdjson/generic/ondemand/base.h for arm64 */
26157
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
26158
26159
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
26160
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_BASE_H */
26161
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
26162
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
26163
26164
namespace simdjson {
26165
namespace arm64 {
26166
/**
26167
 * A fast, simple, DOM-like interface that parses JSON as you use it.
26168
 *
26169
 * Designed for maximum speed and a lower memory profile.
26170
 */
26171
namespace ondemand {
26172
26173
/** Represents the depth of a JSON value (number of nested arrays/objects). */
26174
using depth_t = int32_t;
26175
26176
/** @copydoc simdjson::arm64::number_type */
26177
using number_type = simdjson::arm64::number_type;
26178
26179
/** @private Position in the JSON buffer indexes */
26180
using token_position = const uint32_t *;
26181
26182
class array;
26183
class array_iterator;
26184
class document;
26185
class document_reference;
26186
class document_stream;
26187
class field;
26188
class json_iterator;
26189
enum class json_type;
26190
struct number;
26191
class object;
26192
class object_iterator;
26193
class parser;
26194
class raw_json_string;
26195
class token_iterator;
26196
class value;
26197
class value_iterator;
26198
26199
} // namespace ondemand
26200
} // namespace arm64
26201
} // namespace simdjson
26202
26203
#endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H
26204
/* end file simdjson/generic/ondemand/base.h for arm64 */
26205
/* including simdjson/generic/ondemand/value_iterator.h for arm64: #include "simdjson/generic/ondemand/value_iterator.h" */
26206
/* begin file simdjson/generic/ondemand/value_iterator.h for arm64 */
26207
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
26208
26209
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
26210
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H */
26211
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
26212
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
26213
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
26214
26215
namespace simdjson {
26216
namespace arm64 {
26217
namespace ondemand {
26218
26219
/**
26220
 * Iterates through a single JSON value at a particular depth.
26221
 *
26222
 * Does not keep track of the type of value: provides methods for objects, arrays and scalars and expects
26223
 * the caller to call the right ones.
26224
 *
26225
 * @private This is not intended for external use.
26226
 */
26227
class value_iterator {
26228
protected:
26229
  /** The underlying JSON iterator */
26230
  json_iterator *_json_iter{};
26231
  /** The depth of this value */
26232
  depth_t _depth{};
26233
  /**
26234
   * The starting token index for this value
26235
   */
26236
  token_position _start_position{};
26237
26238
public:
26239
  simdjson_inline value_iterator() noexcept = default;
26240
26241
  /**
26242
   * Denote that we're starting a document.
26243
   */
26244
  simdjson_inline void start_document() noexcept;
26245
26246
  /**
26247
   * Skips a non-iterated or partially-iterated JSON value, whether it is a scalar, array or object.
26248
   *
26249
   * Optimized for scalars.
26250
   */
26251
  simdjson_warn_unused simdjson_inline error_code skip_child() noexcept;
26252
26253
  /**
26254
   * Tell whether the iterator is at the EOF mark
26255
   */
26256
  simdjson_inline bool at_end() const noexcept;
26257
26258
  /**
26259
   * Tell whether the iterator is at the start of the value
26260
   */
26261
  simdjson_inline bool at_start() const noexcept;
26262
26263
  /**
26264
   * Tell whether the value is open--if the value has not been used, or the array/object is still open.
26265
   */
26266
  simdjson_inline bool is_open() const noexcept;
26267
26268
  /**
26269
   * Tell whether the value is at an object's first field (just after the {).
26270
   */
26271
  simdjson_inline bool at_first_field() const noexcept;
26272
26273
  /**
26274
   * Abandon all iteration.
26275
   */
26276
  simdjson_inline void abandon() noexcept;
26277
26278
  /**
26279
   * Get the child value as a value_iterator.
26280
   */
26281
  simdjson_inline value_iterator child_value() const noexcept;
26282
26283
  /**
26284
   * Get the depth of this value.
26285
   */
26286
  simdjson_inline int32_t depth() const noexcept;
26287
26288
  /**
26289
   * Get the JSON type of this value.
26290
   *
26291
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
26292
   */
26293
  simdjson_inline simdjson_result<json_type> type() const noexcept;
26294
26295
  /**
26296
   * @addtogroup object Object iteration
26297
   *
26298
   * Methods to iterate and find object fields. These methods generally *assume* the value is
26299
   * actually an object; the caller is responsible for keeping track of that fact.
26300
   *
26301
   * @{
26302
   */
26303
26304
  /**
26305
   * Start an object iteration.
26306
   *
26307
   * @returns Whether the object had any fields (returns false for empty).
26308
   * @error INCORRECT_TYPE if there is no opening {
26309
   */
26310
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_object() noexcept;
26311
  /**
26312
   * Start an object iteration from the root.
26313
   *
26314
   * @returns Whether the object had any fields (returns false for empty).
26315
   * @error INCORRECT_TYPE if there is no opening {
26316
   * @error TAPE_ERROR if there is no matching } at end of document
26317
   */
26318
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_object() noexcept;
26319
  /**
26320
   * Checks whether an object could be started from the root. May be called by start_root_object.
26321
   *
26322
   * @returns SUCCESS if it is possible to safely start an object from the root (document level).
26323
   * @error INCORRECT_TYPE if there is no opening {
26324
   * @error TAPE_ERROR if there is no matching } at end of document
26325
   */
26326
  simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept;
26327
  /**
26328
   * Start an object iteration after the user has already checked and moved past the {.
26329
   *
26330
   * Does not move the iterator unless the object is empty ({}).
26331
   *
26332
   * @returns Whether the object had any fields (returns false for empty).
26333
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
26334
   *        array or object is incomplete).
26335
   */
26336
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_object() noexcept;
26337
  /**
26338
   * Start an object iteration from the root, after the user has already checked and moved past the {.
26339
   *
26340
   * Does not move the iterator unless the object is empty ({}).
26341
   *
26342
   * @returns Whether the object had any fields (returns false for empty).
26343
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
26344
   *        array or object is incomplete).
26345
   */
26346
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_object() noexcept;
26347
26348
  /**
26349
   * Moves to the next field in an object.
26350
   *
26351
   * Looks for , and }. If } is found, the object is finished and the iterator advances past it.
26352
   * Otherwise, it advances to the next value.
26353
   *
26354
   * @return whether there is another field in the object.
26355
   * @error TAPE_ERROR If there is a comma missing between fields.
26356
   * @error TAPE_ERROR If there is a comma, but not enough tokens remaining to have a key, :, and value.
26357
   */
26358
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_field() noexcept;
26359
26360
  /**
26361
   * Get the current field's key.
26362
   */
26363
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> field_key() noexcept;
26364
26365
  /**
26366
   * Pass the : in the field and move to its value.
26367
   */
26368
  simdjson_warn_unused simdjson_inline error_code field_value() noexcept;
26369
26370
  /**
26371
   * Find the next field with the given key.
26372
   *
26373
   * Assumes you have called next_field() or otherwise matched the previous value.
26374
   *
26375
   * This means the iterator must be sitting at the next key:
26376
   *
26377
   * ```
26378
   * { "a": 1, "b": 2 }
26379
   *           ^
26380
   * ```
26381
   *
26382
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
26383
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
26384
   * fail to match some keys with escapes (\u, \n, etc.).
26385
   */
26386
  simdjson_warn_unused simdjson_inline error_code find_field(const std::string_view key) noexcept;
26387
26388
  /**
26389
   * Find the next field with the given key, *without* unescaping. This assumes object order: it
26390
   * will not find the field if it was already passed when looking for some *other* field.
26391
   *
26392
   * Assumes you have called next_field() or otherwise matched the previous value.
26393
   *
26394
   * This means the iterator must be sitting at the next key:
26395
   *
26396
   * ```
26397
   * { "a": 1, "b": 2 }
26398
   *           ^
26399
   * ```
26400
   *
26401
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
26402
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
26403
   * fail to match some keys with escapes (\u, \n, etc.).
26404
   */
26405
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
26406
26407
  /**
26408
   * Find the field with the given key without regard to order, and *without* unescaping.
26409
   *
26410
   * This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
26411
   *
26412
   * Assumes you have called next_field() or otherwise matched the previous value.
26413
   *
26414
   * This means the iterator must be sitting at the next key:
26415
   *
26416
   * ```
26417
   * { "a": 1, "b": 2 }
26418
   *           ^
26419
   * ```
26420
   *
26421
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
26422
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
26423
   * fail to match some keys with escapes (\u, \n, etc.).
26424
   */
26425
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
26426
26427
  /** @} */
26428
26429
  /**
26430
   * @addtogroup array Array iteration
26431
   * Methods to iterate over array elements. These methods generally *assume* the value is actually
26432
   * an object; the caller is responsible for keeping track of that fact.
26433
   * @{
26434
   */
26435
26436
  /**
26437
   * Check for an opening [ and start an array iteration.
26438
   *
26439
   * @returns Whether the array had any elements (returns false for empty).
26440
   * @error INCORRECT_TYPE If there is no [.
26441
   */
26442
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_array() noexcept;
26443
  /**
26444
   * Check for an opening [ and start an array iteration while at the root.
26445
   *
26446
   * @returns Whether the array had any elements (returns false for empty).
26447
   * @error INCORRECT_TYPE If there is no [.
26448
   * @error TAPE_ERROR if there is no matching ] at end of document
26449
   */
26450
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_array() noexcept;
26451
  /**
26452
   * Checks whether an array could be started from the root. May be called by start_root_array.
26453
   *
26454
   * @returns SUCCESS if it is possible to safely start an array from the root (document level).
26455
   * @error INCORRECT_TYPE If there is no [.
26456
   * @error TAPE_ERROR if there is no matching ] at end of document
26457
   */
26458
  simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept;
26459
  /**
26460
   * Start an array iteration, after the user has already checked and moved past the [.
26461
   *
26462
   * Does not move the iterator unless the array is empty ([]).
26463
   *
26464
   * @returns Whether the array had any elements (returns false for empty).
26465
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
26466
   *        array or object is incomplete).
26467
   */
26468
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_array() noexcept;
26469
  /**
26470
   * Start an array iteration from the root, after the user has already checked and moved past the [.
26471
   *
26472
   * Does not move the iterator unless the array is empty ([]).
26473
   *
26474
   * @returns Whether the array had any elements (returns false for empty).
26475
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
26476
   *        array or object is incomplete).
26477
   */
26478
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_array() noexcept;
26479
26480
  /**
26481
   * Moves to the next element in an array.
26482
   *
26483
   * Looks for , and ]. If ] is found, the array is finished and the iterator advances past it.
26484
   * Otherwise, it advances to the next value.
26485
   *
26486
   * @return Whether there is another element in the array.
26487
   * @error TAPE_ERROR If there is a comma missing between elements.
26488
   */
26489
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_element() noexcept;
26490
26491
  /**
26492
   * Get a child value iterator.
26493
   */
26494
  simdjson_warn_unused simdjson_inline value_iterator child() const noexcept;
26495
26496
  /** @} */
26497
26498
  /**
26499
   * @defgroup scalar Scalar values
26500
   * @addtogroup scalar
26501
   * @{
26502
   */
26503
26504
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
26505
  template <typename string_type>
26506
  simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
26507
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
26508
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
26509
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
26510
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
26511
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
26512
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
26513
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
26514
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
26515
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
26516
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
26517
  simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
26518
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
26519
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
26520
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
26521
26522
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
26523
  template <typename string_type>
26524
  simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
26525
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
26526
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
26527
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
26528
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
26529
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
26530
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
26531
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
26532
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
26533
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
26534
  simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
26535
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
26536
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
26537
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
26538
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
26539
26540
  simdjson_inline error_code error() const noexcept;
26541
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
26542
  simdjson_inline const json_iterator &json_iter() const noexcept;
26543
  simdjson_inline json_iterator &json_iter() noexcept;
26544
26545
  simdjson_inline void assert_is_valid() const noexcept;
26546
  simdjson_inline bool is_valid() const noexcept;
26547
26548
  /** @} */
26549
protected:
26550
  /**
26551
   * Restarts an array iteration.
26552
   * @returns Whether the array has any elements (returns false for empty).
26553
   */
26554
  simdjson_inline simdjson_result<bool> reset_array() noexcept;
26555
  /**
26556
   * Restarts an object iteration.
26557
   * @returns Whether the object has any fields (returns false for empty).
26558
   */
26559
  simdjson_inline simdjson_result<bool> reset_object() noexcept;
26560
  /**
26561
   * move_at_start(): moves us so that we are pointing at the beginning of
26562
   * the container. It updates the index so that at_start() is true and it
26563
   * syncs the depth. The user can then create a new container instance.
26564
   *
26565
   * Usage: used with value::count_elements().
26566
   **/
26567
  simdjson_inline void move_at_start() noexcept;
26568
26569
  /**
26570
   * move_at_container_start(): moves us so that we are pointing at the beginning of
26571
   * the container so that assert_at_container_start() passes.
26572
   *
26573
   * Usage: used with reset_array() and reset_object().
26574
   **/
26575
   simdjson_inline void move_at_container_start() noexcept;
26576
  /* Useful for debugging and logging purposes. */
26577
  inline std::string to_string() const noexcept;
26578
  simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
26579
26580
  simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
26581
  simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
26582
  simdjson_inline const uint8_t *peek_start() const noexcept;
26583
  simdjson_inline uint32_t peek_start_length() const noexcept;
26584
  simdjson_inline uint32_t peek_root_length() const noexcept;
26585
26586
  /**
26587
   * The general idea of the advance_... methods and the peek_* methods
26588
   * is that you first peek and check that you have desired type. If you do,
26589
   * and only if you do, then you advance.
26590
   *
26591
   * We used to unconditionally advance. But this made reasoning about our
26592
   * current state difficult.
26593
   * Suppose you always advance. Look at the 'value' matching the key
26594
   * "shadowable" in the following example...
26595
   *
26596
   * ({"globals":{"a":{"shadowable":[}}}})
26597
   *
26598
   * If the user thinks it is a Boolean and asks for it, then we check the '[',
26599
   * decide it is not a Boolean, but still move into the next character ('}'). Now
26600
   * we are left pointing at '}' right after a '['. And we have not yet reported
26601
   * an error, only that we do not have a Boolean.
26602
   *
26603
   * If, instead, you just stand your ground until it is content that you know, then
26604
   * you will only even move beyond the '[' if the user tells you that you have an
26605
   * array. So you will be at the '}' character inside the array and, hopefully, you
26606
   * will then catch the error because an array cannot start with '}', but the code
26607
   * processing Boolean values does not know this.
26608
   *
26609
   * So the contract is: first call 'peek_...' and then call 'advance_...' only
26610
   * if you have determined that it is a type you can handle.
26611
   *
26612
   * Unfortunately, it makes the code more verbose, longer and maybe more error prone.
26613
   */
26614
26615
  simdjson_inline void advance_scalar(const char *type) noexcept;
26616
  simdjson_inline void advance_root_scalar(const char *type) noexcept;
26617
  simdjson_inline void advance_non_root_scalar(const char *type) noexcept;
26618
26619
  simdjson_inline const uint8_t *peek_scalar(const char *type) noexcept;
26620
  simdjson_inline const uint8_t *peek_root_scalar(const char *type) noexcept;
26621
  simdjson_inline const uint8_t *peek_non_root_scalar(const char *type) noexcept;
26622
26623
26624
  simdjson_inline error_code start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept;
26625
  simdjson_inline error_code end_container() noexcept;
26626
26627
  /**
26628
   * Advance to a place expecting a value (increasing depth).
26629
   *
26630
   * @return The current token (the one left behind).
26631
   * @error TAPE_ERROR If the document ended early.
26632
   */
26633
  simdjson_inline simdjson_result<const uint8_t *> advance_to_value() noexcept;
26634
26635
  simdjson_inline error_code incorrect_type_error(const char *message) const noexcept;
26636
  simdjson_inline error_code error_unless_more_tokens(uint32_t tokens=1) const noexcept;
26637
26638
  simdjson_inline bool is_at_start() const noexcept;
26639
  /**
26640
   * is_at_iterator_start() returns true on an array or object after it has just been
26641
   * created, whether the instance is empty or not.
26642
   *
26643
   * Usage: used by array::begin() in debug mode (SIMDJSON_DEVELOPMENT_CHECKS)
26644
   */
26645
  simdjson_inline bool is_at_iterator_start() const noexcept;
26646
26647
  /**
26648
   * Assuming that we are within an object, this returns true if we
26649
   * are pointing at a key.
26650
   *
26651
   * Usage: the skip_child() method should never be used while we are pointing
26652
   * at a key inside an object.
26653
   */
26654
  simdjson_inline bool is_at_key() const noexcept;
26655
26656
  inline void assert_at_start() const noexcept;
26657
  inline void assert_at_container_start() const noexcept;
26658
  inline void assert_at_root() const noexcept;
26659
  inline void assert_at_child() const noexcept;
26660
  inline void assert_at_next() const noexcept;
26661
  inline void assert_at_non_root_start() const noexcept;
26662
26663
  /** Get the starting position of this value */
26664
  simdjson_inline token_position start_position() const noexcept;
26665
26666
  /** @copydoc error_code json_iterator::position() const noexcept; */
26667
  simdjson_inline token_position position() const noexcept;
26668
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
26669
  simdjson_inline token_position last_position() const noexcept;
26670
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
26671
  simdjson_inline token_position end_position() const noexcept;
26672
  /** @copydoc error_code json_iterator::report_error(error_code error, const char *message) noexcept; */
26673
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
26674
26675
  friend class document;
26676
  friend class object;
26677
  friend class array;
26678
  friend class value;
26679
  friend class field;
26680
}; // value_iterator
26681
26682
} // namespace ondemand
26683
} // namespace arm64
26684
} // namespace simdjson
26685
26686
namespace simdjson {
26687
26688
template<>
26689
struct simdjson_result<arm64::ondemand::value_iterator> : public arm64::implementation_simdjson_result_base<arm64::ondemand::value_iterator> {
26690
public:
26691
  simdjson_inline simdjson_result(arm64::ondemand::value_iterator &&value) noexcept; ///< @private
26692
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
26693
  simdjson_inline simdjson_result() noexcept = default;
26694
};
26695
26696
} // namespace simdjson
26697
26698
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
26699
/* end file simdjson/generic/ondemand/value_iterator.h for arm64 */
26700
/* including simdjson/generic/ondemand/value.h for arm64: #include "simdjson/generic/ondemand/value.h" */
26701
/* begin file simdjson/generic/ondemand/value.h for arm64 */
26702
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H
26703
26704
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
26705
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_H */
26706
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
26707
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
26708
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
26709
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
26710
26711
namespace simdjson {
26712
namespace arm64 {
26713
namespace ondemand {
26714
26715
/**
26716
 * An ephemeral JSON value returned during iteration. It is only valid for as long as you do
26717
 * not access more data in the JSON document.
26718
 */
26719
class value {
26720
public:
26721
  /**
26722
   * Create a new invalid value.
26723
   *
26724
   * Exists so you can declare a variable and later assign to it before use.
26725
   */
26726
  simdjson_inline value() noexcept = default;
26727
26728
  /**
26729
   * Get this value as the given type.
26730
   *
26731
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
26732
   *
26733
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
26734
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
26735
   *
26736
   * @returns A value of the given type, parsed from the JSON.
26737
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
26738
   */
26739
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
26740
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
26741
    // immediately fail.
26742
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
26743
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
26744
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
26745
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
26746
      " You may also add support for custom types, see our documentation.");
26747
  }
26748
26749
  /**
26750
   * Get this value as the given type.
26751
   *
26752
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
26753
   *
26754
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
26755
   * @returns INCORRECT_TYPE If the JSON value is not an object.
26756
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
26757
   */
26758
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
26759
26760
  /**
26761
   * Cast this JSON value to an array.
26762
   *
26763
   * @returns An object that can be used to iterate the array.
26764
   * @returns INCORRECT_TYPE If the JSON value is not an array.
26765
   */
26766
  simdjson_inline simdjson_result<array> get_array() noexcept;
26767
26768
  /**
26769
   * Cast this JSON value to an object.
26770
   *
26771
   * @returns An object that can be used to look up or iterate fields.
26772
   * @returns INCORRECT_TYPE If the JSON value is not an object.
26773
   */
26774
  simdjson_inline simdjson_result<object> get_object() noexcept;
26775
26776
  /**
26777
   * Cast this JSON value to an unsigned integer.
26778
   *
26779
   * @returns A unsigned 64-bit integer.
26780
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
26781
   */
26782
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
26783
26784
  /**
26785
   * Cast this JSON value (inside string) to a unsigned integer.
26786
   *
26787
   * @returns A unsigned 64-bit integer.
26788
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
26789
   */
26790
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
26791
26792
  /**
26793
   * Cast this JSON value to a signed integer.
26794
   *
26795
   * @returns A signed 64-bit integer.
26796
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
26797
   */
26798
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
26799
26800
  /**
26801
   * Cast this JSON value (inside string) to a signed integer.
26802
   *
26803
   * @returns A signed 64-bit integer.
26804
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
26805
   */
26806
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
26807
26808
  /**
26809
   * Cast this JSON value to a double.
26810
   *
26811
   * @returns A double.
26812
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
26813
   */
26814
  simdjson_inline simdjson_result<double> get_double() noexcept;
26815
26816
  /**
26817
   * Cast this JSON value (inside string) to a double
26818
   *
26819
   * @returns A double.
26820
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
26821
   */
26822
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
26823
26824
  /**
26825
   * Cast this JSON value to a string.
26826
   *
26827
   * The string is guaranteed to be valid UTF-8.
26828
   *
26829
   * Equivalent to get<std::string_view>().
26830
   *
26831
   * Important: a value should be consumed once. Calling get_string() twice on the same value
26832
   * is an error.
26833
   *
26834
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
26835
   *          time it parses a document or when it is destroyed.
26836
   * @returns INCORRECT_TYPE if the JSON value is not a string.
26837
   */
26838
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
26839
26840
  /**
26841
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
26842
   *
26843
   * The string is guaranteed to be valid UTF-8.
26844
   *
26845
   * Important: a value should be consumed once. Calling get_string() twice on the same value
26846
   * is an error.
26847
   *
26848
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
26849
   * We recommend you avoid allocating an std::string unless you need to.
26850
   *
26851
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
26852
   */
26853
  template <typename string_type>
26854
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
26855
26856
  /**
26857
   * Cast this JSON value to a "wobbly" string.
26858
   *
26859
   * The string is may not be a valid UTF-8 string.
26860
   * See https://simonsapin.github.io/wtf-8/
26861
   *
26862
   * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value
26863
   * is an error.
26864
   *
26865
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
26866
   *          time it parses a document or when it is destroyed.
26867
   * @returns INCORRECT_TYPE if the JSON value is not a string.
26868
   */
26869
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
26870
  /**
26871
   * Cast this JSON value to a raw_json_string.
26872
   *
26873
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
26874
   *
26875
   * @returns A pointer to the raw JSON for the given string.
26876
   * @returns INCORRECT_TYPE if the JSON value is not a string.
26877
   */
26878
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
26879
26880
  /**
26881
   * Cast this JSON value to a bool.
26882
   *
26883
   * @returns A bool value.
26884
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
26885
   */
26886
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
26887
26888
  /**
26889
   * Checks if this JSON value is null. If and only if the value is
26890
   * null, then it is consumed (we advance). If we find a token that
26891
   * begins with 'n' but is not 'null', then an error is returned.
26892
   *
26893
   * @returns Whether the value is null.
26894
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
26895
   */
26896
  simdjson_inline simdjson_result<bool> is_null() noexcept;
26897
26898
#if SIMDJSON_EXCEPTIONS
26899
  /**
26900
   * Cast this JSON value to an instance of type T. The programmer is responsible for
26901
   * providing an implementation of get<T> for the type T, if T is not one of the types
26902
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.).
26903
   *
26904
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
26905
   *
26906
   * @returns An instance of type T
26907
   */
26908
  template <class T>
26909
  explicit simdjson_inline operator T() noexcept(false);
26910
  /**
26911
   * Cast this JSON value to an array.
26912
   *
26913
   * @returns An object that can be used to iterate the array.
26914
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
26915
   */
26916
  simdjson_inline operator array() noexcept(false);
26917
  /**
26918
   * Cast this JSON value to an object.
26919
   *
26920
   * @returns An object that can be used to look up or iterate fields.
26921
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
26922
   */
26923
  simdjson_inline operator object() noexcept(false);
26924
  /**
26925
   * Cast this JSON value to an unsigned integer.
26926
   *
26927
   * @returns A signed 64-bit integer.
26928
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
26929
   */
26930
  simdjson_inline operator uint64_t() noexcept(false);
26931
  /**
26932
   * Cast this JSON value to a signed integer.
26933
   *
26934
   * @returns A signed 64-bit integer.
26935
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
26936
   */
26937
  simdjson_inline operator int64_t() noexcept(false);
26938
  /**
26939
   * Cast this JSON value to a double.
26940
   *
26941
   * @returns A double.
26942
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
26943
   */
26944
  simdjson_inline operator double() noexcept(false);
26945
  /**
26946
   * Cast this JSON value to a string.
26947
   *
26948
   * The string is guaranteed to be valid UTF-8.
26949
   *
26950
   * Equivalent to get<std::string_view>().
26951
   *
26952
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
26953
   *          time it parses a document or when it is destroyed.
26954
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
26955
   */
26956
  simdjson_inline operator std::string_view() noexcept(false);
26957
  /**
26958
   * Cast this JSON value to a raw_json_string.
26959
   *
26960
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
26961
   *
26962
   * @returns A pointer to the raw JSON for the given string.
26963
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
26964
   */
26965
  simdjson_inline operator raw_json_string() noexcept(false);
26966
  /**
26967
   * Cast this JSON value to a bool.
26968
   *
26969
   * @returns A bool value.
26970
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
26971
   */
26972
  simdjson_inline operator bool() noexcept(false);
26973
#endif
26974
26975
  /**
26976
   * Begin array iteration.
26977
   *
26978
   * Part of the std::iterable interface.
26979
   *
26980
   * @returns INCORRECT_TYPE If the JSON value is not an array.
26981
   */
26982
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
26983
  /**
26984
   * Sentinel representing the end of the array.
26985
   *
26986
   * Part of the std::iterable interface.
26987
   */
26988
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
26989
  /**
26990
   * This method scans the array and counts the number of elements.
26991
   * The count_elements method should always be called before you have begun
26992
   * iterating through the array: it is expected that you are pointing at
26993
   * the beginning of the array.
26994
   * The runtime complexity is linear in the size of the array. After
26995
   * calling this function, if successful, the array is 'rewinded' at its
26996
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
26997
   * there is a missing comma), then an error is returned and it is no longer
26998
   * safe to continue.
26999
   *
27000
   * Performance hint: You should only call count_elements() as a last
27001
   * resort as it may require scanning the document twice or more.
27002
   */
27003
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
27004
  /**
27005
   * This method scans the object and counts the number of key-value pairs.
27006
   * The count_fields method should always be called before you have begun
27007
   * iterating through the object: it is expected that you are pointing at
27008
   * the beginning of the object.
27009
   * The runtime complexity is linear in the size of the object. After
27010
   * calling this function, if successful, the object is 'rewinded' at its
27011
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
27012
   * there is a missing comma), then an error is returned and it is no longer
27013
   * safe to continue.
27014
   *
27015
   * To check that an object is empty, it is more performant to use
27016
   * the is_empty() method on the object instance.
27017
   *
27018
   * Performance hint: You should only call count_fields() as a last
27019
   * resort as it may require scanning the document twice or more.
27020
   */
27021
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
27022
  /**
27023
   * Get the value at the given index in the array. This function has linear-time complexity.
27024
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
27025
   *
27026
   * @return The value at the given index, or:
27027
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
27028
   */
27029
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
27030
  /**
27031
   * Look up a field by name on an object (order-sensitive).
27032
   *
27033
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
27034
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
27035
   *
27036
   * ```c++
27037
   * simdjson::ondemand::parser parser;
27038
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
27039
   * double z = obj.find_field("z");
27040
   * double y = obj.find_field("y");
27041
   * double x = obj.find_field("x");
27042
   * ```
27043
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
27044
   * that only one field is returned.
27045
27046
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
27047
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
27048
   *
27049
   * @param key The key to look up.
27050
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
27051
   */
27052
  simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept;
27053
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
27054
  simdjson_inline simdjson_result<value> find_field(const char *key) noexcept;
27055
27056
  /**
27057
   * Look up a field by name on an object, without regard to key order.
27058
   *
27059
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
27060
   * and often appears negligible. It starts out normally, starting out at the last field; but if
27061
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
27062
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
27063
   * in question is large. The fact that the extra code is there also bumps the executable size.
27064
   *
27065
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
27066
   * default behavior failed to look up a field just because it was in the wrong order--and many
27067
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
27068
   *
27069
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
27070
   * that only one field is returned.
27071
   *
27072
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
27073
   * field as not there when they are not in order).
27074
   *
27075
   * @param key The key to look up.
27076
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
27077
   */
27078
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
27079
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
27080
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
27081
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
27082
  simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept;
27083
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
27084
  simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
27085
27086
  /**
27087
   * Get the type of this JSON value. It does not validate or consume the value.
27088
   * E.g., you must still call "is_null()" to check that a value is null even if
27089
   * "type()" returns json_type::null.
27090
   *
27091
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
27092
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
27093
   * let it throw an exception).
27094
   *
27095
   * @return The type of JSON value (json_type::array, json_type::object, json_type::string,
27096
   *     json_type::number, json_type::boolean, or json_type::null).
27097
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
27098
   */
27099
  simdjson_inline simdjson_result<json_type> type() noexcept;
27100
27101
  /**
27102
   * Checks whether the value is a scalar (string, number, null, Boolean).
27103
   * Returns false when there it is an array or object.
27104
   *
27105
   * @returns true if the type is string, number, null, Boolean
27106
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
27107
   */
27108
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
27109
  /**
27110
   * Checks whether the value is a string.
27111
   *
27112
   * @returns true if the type is string
27113
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
27114
   */
27115
  simdjson_inline simdjson_result<bool> is_string() noexcept;
27116
27117
  /**
27118
   * Checks whether the value is a negative number.
27119
   *
27120
   * @returns true if the number if negative.
27121
   */
27122
  simdjson_inline bool is_negative() noexcept;
27123
  /**
27124
   * Checks whether the value is an integer number. Note that
27125
   * this requires to partially parse the number string. If
27126
   * the value is determined to be an integer, it may still
27127
   * not parse properly as an integer in subsequent steps
27128
   * (e.g., it might overflow).
27129
   *
27130
   * Performance note: if you call this function systematically
27131
   * before parsing a number, you may have fallen for a performance
27132
   * anti-pattern.
27133
   *
27134
   * @returns true if the number if negative.
27135
   */
27136
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
27137
  /**
27138
   * Determine the number type (integer or floating-point number) as quickly
27139
   * as possible. This function does not fully validate the input. It is
27140
   * useful when you only need to classify the numbers, without parsing them.
27141
   *
27142
   * If you are planning to retrieve the value or you need full validation,
27143
   * consider using the get_number() method instead: it will fully parse
27144
   * and validate the input, and give you access to the type:
27145
   * get_number().get_number_type().
27146
   *
27147
   * get_number_type() is number_type::unsigned_integer if we have
27148
   * an integer greater or equal to 9223372036854775808.
27149
   * get_number_type() is number_type::signed_integer if we have an
27150
   * integer that is less than 9223372036854775808.
27151
   * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits,
27152
   * in which case the digit_count is set to the length of the big integer string.
27153
   * Otherwise, get_number_type() has value number_type::floating_point_number.
27154
   *
27155
   * This function requires processing the number string, but it is expected
27156
   * to be faster than get_number().get_number_type() because it is does not
27157
   * parse the number value.
27158
   *
27159
   * @returns the type of the number
27160
   */
27161
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
27162
27163
  /**
27164
   * Attempt to parse an ondemand::number. An ondemand::number may
27165
   * contain an integer value or a floating-point value, the simdjson
27166
   * library will autodetect the type. Thus it is a dynamically typed
27167
   * number. Before accessing the value, you must determine the detected
27168
   * type.
27169
   *
27170
   * number.get_number_type() is number_type::signed_integer if we have
27171
   * an integer in [-9223372036854775808,9223372036854775808)
27172
   * You can recover the value by calling number.get_int64() and you
27173
   * have that number.is_int64() is true.
27174
   *
27175
   * number.get_number_type() is number_type::unsigned_integer if we have
27176
   * an integer in [9223372036854775808,18446744073709551616)
27177
   * You can recover the value by calling number.get_uint64() and you
27178
   * have that number.is_uint64() is true.
27179
   *
27180
   * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code.
27181
   *
27182
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
27183
   * and we have a binary64 number.
27184
   * You can recover the value by calling number.get_double() and you
27185
   * have that number.is_double() is true.
27186
   *
27187
   * You must check the type before accessing the value: it is an error
27188
   * to call "get_int64()" when number.get_number_type() is not
27189
   * number_type::signed_integer and when number.is_int64() is false.
27190
   *
27191
   * Performance note: this is designed with performance in mind. When
27192
   * calling 'get_number()', you scan the number string only once, determining
27193
   * efficiently the type and storing it in an efficient manner.
27194
   */
27195
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
27196
27197
  /**
27198
   * Get the raw JSON for this token.
27199
   *
27200
   * The string_view will always point into the input buffer.
27201
   *
27202
   * The string_view will start at the beginning of the token, and include the entire token
27203
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
27204
   * string token always begins with a " and is always terminated by the final ", possibly
27205
   * followed by a number of spaces.
27206
   *
27207
   * The string_view is *not* null-terminated. However, if this is a scalar (string, number,
27208
   * boolean, or null), the character after the end of the string_view is guaranteed to be
27209
   * a non-space token.
27210
   *
27211
   * Tokens include:
27212
   * - {
27213
   * - [
27214
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
27215
   * - -1.2e-100
27216
   * - true
27217
   * - false
27218
   * - null
27219
   *
27220
   * See also value::raw_json().
27221
   */
27222
  simdjson_inline std::string_view raw_json_token() noexcept;
27223
27224
  /**
27225
   * Get a string_view pointing at this value in the JSON document.
27226
   * If this element is an array or an object, it consumes the array or the object
27227
   * and returns a string_view instance corresponding to the
27228
   * array as represented in JSON. It points inside the original document.
27229
   * If this element is a scalar (string, number, Boolean, null), it returns what
27230
   * raw_json_token() would return.
27231
   */
27232
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
27233
27234
  /**
27235
   * Returns the current location in the document if in bounds.
27236
   */
27237
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
27238
27239
  /**
27240
   * Returns the current depth in the document if in bounds.
27241
   *
27242
   * E.g.,
27243
   *  0 = finished with document
27244
   *  1 = document root value (could be [ or {, not yet known)
27245
   *  2 = , or } inside root array/object
27246
   *  3 = key or value inside root array/object.
27247
   */
27248
  simdjson_inline int32_t current_depth() const noexcept;
27249
27250
  /**
27251
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
27252
   * https://tools.ietf.org/html/rfc6901 standard.
27253
   *
27254
   *   ondemand::parser parser;
27255
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
27256
   *   auto doc = parser.iterate(json);
27257
   *   doc.at_pointer("/foo/a/1") == 20
27258
   *
27259
   * It is allowed for a key to be the empty string:
27260
   *
27261
   *   ondemand::parser parser;
27262
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
27263
   *   auto doc = parser.iterate(json);
27264
   *   doc.at_pointer("//a/1") == 20
27265
   *
27266
   * Note that at_pointer() called on the document automatically calls the document's rewind
27267
   * method between each call. It invalidates all previously accessed arrays, objects and values
27268
   * that have not been consumed.
27269
   *
27270
   * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not
27271
   * standardized (by RFC 6901). We provide some experimental support for JSON pointers
27272
   * on non-document instances.  Yet it is not the case when calling at_pointer on an array
27273
   * or an object instance: there is no rewind and no invalidation.
27274
   *
27275
   * You may only call at_pointer on an array after it has been created, but before it has
27276
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
27277
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
27278
   * to call at_pointer on the same array.
27279
   *
27280
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
27281
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
27282
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
27283
   *
27284
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
27285
   *
27286
   * @return The value associated with the given JSON pointer, or:
27287
   *         - NO_SUCH_FIELD if a field does not exist in an object
27288
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
27289
   *         - INCORRECT_TYPE if a non-integer is used to access an array
27290
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
27291
   */
27292
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
27293
27294
  /**
27295
   * Get the value associated with the given JSONPath expression. We only support
27296
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
27297
   * names and array indices.
27298
   *
27299
   * @return The value associated with the given JSONPath expression, or:
27300
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
27301
   *         - NO_SUCH_FIELD if a field does not exist in an object
27302
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
27303
   *         - INCORRECT_TYPE if a non-integer is used to access an array
27304
   */
27305
  simdjson_inline simdjson_result<value> at_path(std::string_view at_path) noexcept;
27306
27307
27308
protected:
27309
  /**
27310
   * Create a value.
27311
   */
27312
  simdjson_inline value(const value_iterator &iter) noexcept;
27313
27314
  /**
27315
   * Skip this value, allowing iteration to continue.
27316
   */
27317
  simdjson_inline void skip() noexcept;
27318
27319
  /**
27320
   * Start a value at the current position.
27321
   *
27322
   * (It should already be started; this is just a self-documentation method.)
27323
   */
27324
  static simdjson_inline value start(const value_iterator &iter) noexcept;
27325
27326
  /**
27327
   * Resume a value.
27328
   */
27329
  static simdjson_inline value resume(const value_iterator &iter) noexcept;
27330
27331
  /**
27332
   * Get the object, starting or resuming it as necessary
27333
   */
27334
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
27335
27336
  // simdjson_inline void log_value(const char *type) const noexcept;
27337
  // simdjson_inline void log_error(const char *message) const noexcept;
27338
27339
  value_iterator iter{};
27340
27341
  friend class document;
27342
  friend class array_iterator;
27343
  friend class field;
27344
  friend class object;
27345
  friend struct simdjson_result<value>;
27346
  friend struct simdjson_result<field>;
27347
  friend class field;
27348
};
27349
27350
} // namespace ondemand
27351
} // namespace arm64
27352
} // namespace simdjson
27353
27354
namespace simdjson {
27355
27356
template<>
27357
struct simdjson_result<arm64::ondemand::value> : public arm64::implementation_simdjson_result_base<arm64::ondemand::value> {
27358
public:
27359
  simdjson_inline simdjson_result(arm64::ondemand::value &&value) noexcept; ///< @private
27360
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
27361
  simdjson_inline simdjson_result() noexcept = default;
27362
27363
  simdjson_inline simdjson_result<arm64::ondemand::array> get_array() noexcept;
27364
  simdjson_inline simdjson_result<arm64::ondemand::object> get_object() noexcept;
27365
27366
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
27367
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
27368
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
27369
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
27370
  simdjson_inline simdjson_result<double> get_double() noexcept;
27371
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
27372
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
27373
  template <typename string_type>
27374
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
27375
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
27376
  simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> get_raw_json_string() noexcept;
27377
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
27378
  simdjson_inline simdjson_result<bool> is_null() noexcept;
27379
27380
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
27381
27382
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
27383
27384
#if SIMDJSON_EXCEPTIONS
27385
  template <class T>
27386
  explicit simdjson_inline operator T() noexcept(false);
27387
  simdjson_inline operator arm64::ondemand::array() noexcept(false);
27388
  simdjson_inline operator arm64::ondemand::object() noexcept(false);
27389
  simdjson_inline operator uint64_t() noexcept(false);
27390
  simdjson_inline operator int64_t() noexcept(false);
27391
  simdjson_inline operator double() noexcept(false);
27392
  simdjson_inline operator std::string_view() noexcept(false);
27393
  simdjson_inline operator arm64::ondemand::raw_json_string() noexcept(false);
27394
  simdjson_inline operator bool() noexcept(false);
27395
#endif
27396
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
27397
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
27398
  simdjson_inline simdjson_result<arm64::ondemand::value> at(size_t index) noexcept;
27399
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> begin() & noexcept;
27400
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> end() & noexcept;
27401
27402
  /**
27403
   * Look up a field by name on an object (order-sensitive).
27404
   *
27405
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
27406
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
27407
   *
27408
   * ```c++
27409
   * simdjson::ondemand::parser parser;
27410
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
27411
   * double z = obj.find_field("z");
27412
   * double y = obj.find_field("y");
27413
   * double x = obj.find_field("x");
27414
   * ```
27415
   *
27416
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
27417
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
27418
   *
27419
   * @param key The key to look up.
27420
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
27421
   */
27422
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(std::string_view key) noexcept;
27423
  /** @overload simdjson_inline simdjson_result<arm64::ondemand::value> find_field(std::string_view key) noexcept; */
27424
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(const char *key) noexcept;
27425
27426
  /**
27427
   * Look up a field by name on an object, without regard to key order.
27428
   *
27429
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
27430
   * and often appears negligible. It starts out normally, starting out at the last field; but if
27431
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
27432
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
27433
   * in question is large. The fact that the extra code is there also bumps the executable size.
27434
   *
27435
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
27436
   * default behavior failed to look up a field just because it was in the wrong order--and many
27437
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
27438
   *
27439
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
27440
   * field as not there when they are not in order).
27441
   *
27442
   * @param key The key to look up.
27443
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
27444
   */
27445
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) noexcept;
27446
  /** @overload simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
27447
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(const char *key) noexcept;
27448
  /** @overload simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
27449
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](std::string_view key) noexcept;
27450
  /** @overload simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
27451
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](const char *key) noexcept;
27452
27453
  /**
27454
   * Get the type of this JSON value.
27455
   *
27456
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
27457
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
27458
   * let it throw an exception).
27459
   */
27460
  simdjson_inline simdjson_result<arm64::ondemand::json_type> type() noexcept;
27461
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
27462
  simdjson_inline simdjson_result<bool> is_string() noexcept;
27463
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
27464
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
27465
  simdjson_inline simdjson_result<arm64::number_type> get_number_type() noexcept;
27466
  simdjson_inline simdjson_result<arm64::ondemand::number> get_number() noexcept;
27467
27468
  /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
27469
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
27470
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
27471
27472
  /** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
27473
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
27474
  /** @copydoc simdjson_inline int32_t current_depth() const noexcept */
27475
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
27476
  simdjson_inline simdjson_result<arm64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
27477
  simdjson_inline simdjson_result<arm64::ondemand::value> at_path(std::string_view json_path) noexcept;
27478
};
27479
27480
} // namespace simdjson
27481
27482
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H
27483
/* end file simdjson/generic/ondemand/value.h for arm64 */
27484
/* including simdjson/generic/ondemand/logger.h for arm64: #include "simdjson/generic/ondemand/logger.h" */
27485
/* begin file simdjson/generic/ondemand/logger.h for arm64 */
27486
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
27487
27488
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
27489
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_H */
27490
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
27491
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
27492
27493
namespace simdjson {
27494
namespace arm64 {
27495
namespace ondemand {
27496
27497
// Logging should be free unless SIMDJSON_VERBOSE_LOGGING is set. Importantly, it is critical
27498
// that the call to the log functions be side-effect free. Thus, for example, you should not
27499
// create temporary std::string instances.
27500
namespace logger {
27501
27502
enum class log_level : int32_t {
27503
  info = 0,
27504
  error = 1
27505
};
27506
27507
#if SIMDJSON_VERBOSE_LOGGING
27508
  static constexpr const bool LOG_ENABLED = true;
27509
#else
27510
  static constexpr const bool LOG_ENABLED = false;
27511
#endif
27512
27513
// We do not want these functions to be 'really inlined' since real inlining is
27514
// for performance purposes and if you are using the loggers, you do not care about
27515
// performance (or should not).
27516
static inline void log_headers() noexcept;
27517
// If args are provided, title will be treated as format string
27518
template <typename... Args>
27519
static inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
27520
template <typename... Args>
27521
static inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
27522
static inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
27523
static inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
27524
static inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
27525
static inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
27526
static inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
27527
static inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
27528
27529
static inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail="") noexcept;
27530
static inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
27531
27532
static inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
27533
static inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
27534
static inline void log_start_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
27535
static inline void log_end_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
27536
static inline void log_error(const value_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
27537
27538
} // namespace logger
27539
} // namespace ondemand
27540
} // namespace arm64
27541
} // namespace simdjson
27542
27543
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
27544
/* end file simdjson/generic/ondemand/logger.h for arm64 */
27545
/* including simdjson/generic/ondemand/token_iterator.h for arm64: #include "simdjson/generic/ondemand/token_iterator.h" */
27546
/* begin file simdjson/generic/ondemand/token_iterator.h for arm64 */
27547
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
27548
27549
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
27550
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H */
27551
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
27552
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
27553
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
27554
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
27555
27556
namespace simdjson {
27557
namespace arm64 {
27558
namespace ondemand {
27559
27560
/**
27561
 * Iterates through JSON tokens (`{` `}` `[` `]` `,` `:` `"<string>"` `123` `true` `false` `null`)
27562
 * detected by stage 1.
27563
 *
27564
 * @private This is not intended for external use.
27565
 */
27566
class token_iterator {
27567
public:
27568
  /**
27569
   * Create a new invalid token_iterator.
27570
   *
27571
   * Exists so you can declare a variable and later assign to it before use.
27572
   */
27573
  simdjson_inline token_iterator() noexcept = default;
27574
  simdjson_inline token_iterator(token_iterator &&other) noexcept = default;
27575
  simdjson_inline token_iterator &operator=(token_iterator &&other) noexcept = default;
27576
  simdjson_inline token_iterator(const token_iterator &other) noexcept = default;
27577
  simdjson_inline token_iterator &operator=(const token_iterator &other) noexcept = default;
27578
27579
  /**
27580
   * Advance to the next token (returning the current one).
27581
   */
27582
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
27583
  /**
27584
   * Reports the current offset in bytes from the start of the underlying buffer.
27585
   */
27586
  simdjson_inline uint32_t current_offset() const noexcept;
27587
  /**
27588
   * Get the JSON text for a given token (relative).
27589
   *
27590
   * This is not null-terminated; it is a view into the JSON.
27591
   *
27592
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
27593
   *              1 = next token, -1 = prev token.
27594
   *
27595
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
27596
   * it is not used...
27597
   */
27598
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
27599
  /**
27600
   * Get the maximum length of the JSON text for a given token.
27601
   *
27602
   * The length will include any whitespace at the end of the token.
27603
   *
27604
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
27605
   *              1 = next token, -1 = prev token.
27606
   */
27607
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
27608
27609
  /**
27610
   * Get the JSON text for a given token.
27611
   *
27612
   * This is not null-terminated; it is a view into the JSON.
27613
   *
27614
   * @param position The position of the token.
27615
   *
27616
   */
27617
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
27618
  /**
27619
   * Get the maximum length of the JSON text for a given token.
27620
   *
27621
   * The length will include any whitespace at the end of the token.
27622
   *
27623
   * @param position The position of the token.
27624
   */
27625
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
27626
  /**
27627
   * Get the maximum length of the JSON text for a root token.
27628
   *
27629
   * The length will include any whitespace at the end of the token.
27630
   *
27631
   * @param position The position of the token (start of the document).
27632
   */
27633
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
27634
  /**
27635
   * Return the current index.
27636
   */
27637
  simdjson_inline token_position position() const noexcept;
27638
  /**
27639
   * Reset to a previously saved index.
27640
   */
27641
  simdjson_inline void set_position(token_position target_position) noexcept;
27642
27643
  // NOTE: we don't support a full C++ iterator interface, because we expect people to make
27644
  // different calls to advance the iterator based on *their own* state.
27645
27646
  simdjson_inline bool operator==(const token_iterator &other) const noexcept;
27647
  simdjson_inline bool operator!=(const token_iterator &other) const noexcept;
27648
  simdjson_inline bool operator>(const token_iterator &other) const noexcept;
27649
  simdjson_inline bool operator>=(const token_iterator &other) const noexcept;
27650
  simdjson_inline bool operator<(const token_iterator &other) const noexcept;
27651
  simdjson_inline bool operator<=(const token_iterator &other) const noexcept;
27652
27653
protected:
27654
  simdjson_inline token_iterator(const uint8_t *buf, token_position position) noexcept;
27655
27656
  /**
27657
   * Get the index of the JSON text for a given token (relative).
27658
   *
27659
   * This is not null-terminated; it is a view into the JSON.
27660
   *
27661
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
27662
   *              1 = next token, -1 = prev token.
27663
   */
27664
  simdjson_inline uint32_t peek_index(int32_t delta=0) const noexcept;
27665
  /**
27666
   * Get the index of the JSON text for a given token.
27667
   *
27668
   * This is not null-terminated; it is a view into the JSON.
27669
   *
27670
   * @param position The position of the token.
27671
   *
27672
   */
27673
  simdjson_inline uint32_t peek_index(token_position position) const noexcept;
27674
27675
  const uint8_t *buf{};
27676
  token_position _position{};
27677
27678
  friend class json_iterator;
27679
  friend class value_iterator;
27680
  friend class object;
27681
  template <typename... Args>
27682
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
27683
  template <typename... Args>
27684
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
27685
};
27686
27687
} // namespace ondemand
27688
} // namespace arm64
27689
} // namespace simdjson
27690
27691
namespace simdjson {
27692
27693
template<>
27694
struct simdjson_result<arm64::ondemand::token_iterator> : public arm64::implementation_simdjson_result_base<arm64::ondemand::token_iterator> {
27695
public:
27696
  simdjson_inline simdjson_result(arm64::ondemand::token_iterator &&value) noexcept; ///< @private
27697
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
27698
  simdjson_inline simdjson_result() noexcept = default;
27699
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
27700
};
27701
27702
} // namespace simdjson
27703
27704
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
27705
/* end file simdjson/generic/ondemand/token_iterator.h for arm64 */
27706
/* including simdjson/generic/ondemand/json_iterator.h for arm64: #include "simdjson/generic/ondemand/json_iterator.h" */
27707
/* begin file simdjson/generic/ondemand/json_iterator.h for arm64 */
27708
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
27709
27710
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
27711
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H */
27712
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
27713
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
27714
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
27715
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
27716
27717
namespace simdjson {
27718
namespace arm64 {
27719
namespace ondemand {
27720
27721
/**
27722
 * Iterates through JSON tokens, keeping track of depth and string buffer.
27723
 *
27724
 * @private This is not intended for external use.
27725
 */
27726
class json_iterator {
27727
protected:
27728
  token_iterator token{};
27729
  ondemand::parser *parser{};
27730
  /**
27731
   * Next free location in the string buffer.
27732
   *
27733
   * Used by raw_json_string::unescape() to have a place to unescape strings to.
27734
   */
27735
  uint8_t *_string_buf_loc{};
27736
  /**
27737
   * JSON error, if there is one.
27738
   *
27739
   * INCORRECT_TYPE and NO_SUCH_FIELD are *not* stored here, ever.
27740
   *
27741
   * PERF NOTE: we *hope* this will be elided into control flow, as it is only used (a) in the first
27742
   * iteration of the loop, or (b) for the final iteration after a missing comma is found in ++. If
27743
   * this is not elided, we should make sure it's at least not using up a register. Failing that,
27744
   * we should store it in document so there's only one of them.
27745
   */
27746
  error_code error{SUCCESS};
27747
  /**
27748
   * Depth of the current token in the JSON.
27749
   *
27750
   * - 0 = finished with document
27751
   * - 1 = document root value (could be [ or {, not yet known)
27752
   * - 2 = , or } inside root array/object
27753
   * - 3 = key or value inside root array/object.
27754
   */
27755
  depth_t _depth{};
27756
  /**
27757
   * Beginning of the document indexes.
27758
   * Normally we have root == parser->implementation->structural_indexes.get()
27759
   * but this may differ, especially in streaming mode (where we have several
27760
   * documents);
27761
   */
27762
  token_position _root{};
27763
  /**
27764
   * Normally, a json_iterator operates over a single document, but in
27765
   * some cases, we may have a stream of documents. This attribute is meant
27766
   * as meta-data: the json_iterator works the same irrespective of the
27767
   * value of this attribute.
27768
   */
27769
  bool _streaming{false};
27770
27771
public:
27772
  simdjson_inline json_iterator() noexcept = default;
27773
  simdjson_inline json_iterator(json_iterator &&other) noexcept;
27774
  simdjson_inline json_iterator &operator=(json_iterator &&other) noexcept;
27775
  simdjson_inline explicit json_iterator(const json_iterator &other) noexcept = default;
27776
  simdjson_inline json_iterator &operator=(const json_iterator &other) noexcept = default;
27777
  /**
27778
   * Skips a JSON value, whether it is a scalar, array or object.
27779
   */
27780
  simdjson_warn_unused simdjson_inline error_code skip_child(depth_t parent_depth) noexcept;
27781
27782
  /**
27783
   * Tell whether the iterator is still at the start
27784
   */
27785
  simdjson_inline bool at_root() const noexcept;
27786
27787
  /**
27788
   * Tell whether we should be expected to run in streaming
27789
   * mode (iterating over many documents). It is pure metadata
27790
   * that does not affect how the iterator works. It is used by
27791
   * start_root_array() and start_root_object().
27792
   */
27793
  simdjson_inline bool streaming() const noexcept;
27794
27795
  /**
27796
   * Get the root value iterator
27797
   */
27798
  simdjson_inline token_position root_position() const noexcept;
27799
  /**
27800
   * Assert that we are at the document depth (== 1)
27801
   */
27802
  simdjson_inline void assert_at_document_depth() const noexcept;
27803
  /**
27804
   * Assert that we are at the root of the document
27805
   */
27806
  simdjson_inline void assert_at_root() const noexcept;
27807
27808
  /**
27809
   * Tell whether the iterator is at the EOF mark
27810
   */
27811
  simdjson_inline bool at_end() const noexcept;
27812
27813
  /**
27814
   * Tell whether the iterator is live (has not been moved).
27815
   */
27816
  simdjson_inline bool is_alive() const noexcept;
27817
27818
  /**
27819
   * Abandon this iterator, setting depth to 0 (as if the document is finished).
27820
   */
27821
  simdjson_inline void abandon() noexcept;
27822
27823
  /**
27824
   * Advance the current token without modifying depth.
27825
   */
27826
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
27827
27828
  /**
27829
   * Returns true if there is a single token in the index (i.e., it is
27830
   * a JSON with a scalar value such as a single number).
27831
   *
27832
   * @return whether there is a single token
27833
   */
27834
  simdjson_inline bool is_single_token() const noexcept;
27835
27836
  /**
27837
   * Assert that there are at least the given number of tokens left.
27838
   *
27839
   * Has no effect in release builds.
27840
   */
27841
  simdjson_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
27842
  /**
27843
   * Assert that the given position addresses an actual token (is within bounds).
27844
   *
27845
   * Has no effect in release builds.
27846
   */
27847
  simdjson_inline void assert_valid_position(token_position position) const noexcept;
27848
  /**
27849
   * Get the JSON text for a given token (relative).
27850
   *
27851
   * This is not null-terminated; it is a view into the JSON.
27852
   *
27853
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
27854
   *
27855
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
27856
   * it is not used ...
27857
   */
27858
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
27859
  /**
27860
   * Get the maximum length of the JSON text for the current token (or relative).
27861
   *
27862
   * The length will include any whitespace at the end of the token.
27863
   *
27864
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
27865
   */
27866
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
27867
  /**
27868
   * Get a pointer to the current location in the input buffer.
27869
   *
27870
   * This is not null-terminated; it is a view into the JSON.
27871
   *
27872
   * You may be pointing outside of the input buffer: it is not generally
27873
   * safe to dereference this pointer.
27874
   */
27875
  simdjson_inline const uint8_t *unsafe_pointer() const noexcept;
27876
  /**
27877
   * Get the JSON text for a given token.
27878
   *
27879
   * This is not null-terminated; it is a view into the JSON.
27880
   *
27881
   * @param position The position of the token to retrieve.
27882
   *
27883
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
27884
   * it is not used ...
27885
   */
27886
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
27887
  /**
27888
   * Get the maximum length of the JSON text for the current token (or relative).
27889
   *
27890
   * The length will include any whitespace at the end of the token.
27891
   *
27892
   * @param position The position of the token to retrieve.
27893
   */
27894
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
27895
  /**
27896
   * Get the maximum length of the JSON text for the current root token.
27897
   *
27898
   * The length will include any whitespace at the end of the token.
27899
   *
27900
   * @param position The position of the token to retrieve.
27901
   */
27902
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
27903
  /**
27904
   * Get the JSON text for the last token in the document.
27905
   *
27906
   * This is not null-terminated; it is a view into the JSON.
27907
   *
27908
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
27909
   * it is not used ...
27910
   */
27911
  simdjson_inline const uint8_t *peek_last() const noexcept;
27912
27913
  /**
27914
   * Ascend one level.
27915
   *
27916
   * Validates that the depth - 1 == parent_depth.
27917
   *
27918
   * @param parent_depth the expected parent depth.
27919
   */
27920
  simdjson_inline void ascend_to(depth_t parent_depth) noexcept;
27921
27922
  /**
27923
   * Descend one level.
27924
   *
27925
   * Validates that the new depth == child_depth.
27926
   *
27927
   * @param child_depth the expected child depth.
27928
   */
27929
  simdjson_inline void descend_to(depth_t child_depth) noexcept;
27930
  simdjson_inline void descend_to(depth_t child_depth, int32_t delta) noexcept;
27931
27932
  /**
27933
   * Get current depth.
27934
   */
27935
  simdjson_inline depth_t depth() const noexcept;
27936
27937
  /**
27938
   * Get current (writeable) location in the string buffer.
27939
   */
27940
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
27941
27942
  /**
27943
   * Report an unrecoverable error, preventing further iteration.
27944
   *
27945
   * @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
27946
   * @param message An error message to report with the error.
27947
   */
27948
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
27949
27950
  /**
27951
   * Log error, but don't stop iteration.
27952
   * @param error The error to report. Must be INCORRECT_TYPE, or NO_SUCH_FIELD.
27953
   * @param message An error message to report with the error.
27954
   */
27955
  simdjson_inline error_code optional_error(error_code error, const char *message) noexcept;
27956
27957
  /**
27958
   * Take an input in json containing max_len characters and attempt to copy it over to tmpbuf, a buffer with
27959
   * N bytes of capacity. It will return false if N is too small (smaller than max_len) of if it is zero.
27960
   * The buffer (tmpbuf) is padded with space characters.
27961
   */
27962
  simdjson_warn_unused simdjson_inline bool copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept;
27963
27964
  simdjson_inline token_position position() const noexcept;
27965
  /**
27966
   * Write the raw_json_string to the string buffer and return a string_view.
27967
   * Each raw_json_string should be unescaped once, or else the string buffer might
27968
   * overflow.
27969
   */
27970
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
27971
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
27972
27973
  simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
27974
27975
  simdjson_inline error_code consume_character(char c) noexcept;
27976
#if SIMDJSON_DEVELOPMENT_CHECKS
27977
  simdjson_inline token_position start_position(depth_t depth) const noexcept;
27978
  simdjson_inline void set_start_position(depth_t depth, token_position position) noexcept;
27979
#endif
27980
27981
  /* Useful for debugging and logging purposes. */
27982
  inline std::string to_string() const noexcept;
27983
27984
  /**
27985
   * Returns the current location in the document if in bounds.
27986
   */
27987
  inline simdjson_result<const char *> current_location() const noexcept;
27988
27989
  /**
27990
   * Updates this json iterator so that it is back at the beginning of the document,
27991
   * as if it had just been created.
27992
   */
27993
  inline void rewind() noexcept;
27994
  /**
27995
   * This checks whether the {,},[,] are balanced so that the document
27996
   * ends with proper zero depth. This requires scanning the whole document
27997
   * and it may be expensive. It is expected that it will be rarely called.
27998
   * It does not attempt to match { with } and [ with ].
27999
   */
28000
  inline bool balanced() const noexcept;
28001
protected:
28002
  simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
28003
  /// The last token before the end
28004
  simdjson_inline token_position last_position() const noexcept;
28005
  /// The token *at* the end. This points at gibberish and should only be used for comparison.
28006
  simdjson_inline token_position end_position() const noexcept;
28007
  /// The end of the buffer.
28008
  simdjson_inline token_position end() const noexcept;
28009
28010
  friend class document;
28011
  friend class document_stream;
28012
  friend class object;
28013
  friend class array;
28014
  friend class value;
28015
  friend class raw_json_string;
28016
  friend class parser;
28017
  friend class value_iterator;
28018
  friend class field;
28019
  template <typename... Args>
28020
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
28021
  template <typename... Args>
28022
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
28023
}; // json_iterator
28024
28025
} // namespace ondemand
28026
} // namespace arm64
28027
} // namespace simdjson
28028
28029
namespace simdjson {
28030
28031
template<>
28032
struct simdjson_result<arm64::ondemand::json_iterator> : public arm64::implementation_simdjson_result_base<arm64::ondemand::json_iterator> {
28033
public:
28034
  simdjson_inline simdjson_result(arm64::ondemand::json_iterator &&value) noexcept; ///< @private
28035
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
28036
28037
  simdjson_inline simdjson_result() noexcept = default;
28038
};
28039
28040
} // namespace simdjson
28041
28042
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
28043
/* end file simdjson/generic/ondemand/json_iterator.h for arm64 */
28044
/* including simdjson/generic/ondemand/json_type.h for arm64: #include "simdjson/generic/ondemand/json_type.h" */
28045
/* begin file simdjson/generic/ondemand/json_type.h for arm64 */
28046
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
28047
28048
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
28049
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H */
28050
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
28051
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
28052
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
28053
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
28054
28055
namespace simdjson {
28056
namespace arm64 {
28057
namespace ondemand {
28058
28059
/**
28060
 * The type of a JSON value.
28061
 */
28062
enum class json_type {
28063
    // Start at 1 to catch uninitialized / default values more easily
28064
    array=1, ///< A JSON array   ( [ 1, 2, 3 ... ] )
28065
    object,  ///< A JSON object  ( { "a": 1, "b" 2, ... } )
28066
    number,  ///< A JSON number  ( 1 or -2.3 or 4.5e6 ...)
28067
    string,  ///< A JSON string  ( "a" or "hello world\n" ...)
28068
    boolean, ///< A JSON boolean (true or false)
28069
    null     ///< A JSON null    (null)
28070
};
28071
28072
/**
28073
 * A type representing a JSON number.
28074
 * The design of the struct is deliberately straight-forward. All
28075
 * functions return standard values with no error check.
28076
 */
28077
struct number {
28078
28079
  /**
28080
   * return the automatically determined type of
28081
   * the number: number_type::floating_point_number,
28082
   * number_type::signed_integer or number_type::unsigned_integer.
28083
   *
28084
   *    enum class number_type {
28085
   *        floating_point_number=1, /// a binary64 number
28086
   *        signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
28087
   *        unsigned_integer         /// a positive integer larger or equal to 1<<63
28088
   *    };
28089
   */
28090
  simdjson_inline ondemand::number_type get_number_type() const noexcept;
28091
  /**
28092
   * return true if the automatically determined type of
28093
   * the number is number_type::unsigned_integer.
28094
   */
28095
  simdjson_inline bool is_uint64() const noexcept;
28096
  /**
28097
   * return the value as a uint64_t, only valid if is_uint64() is true.
28098
   */
28099
  simdjson_inline uint64_t get_uint64() const noexcept;
28100
  simdjson_inline operator uint64_t() const noexcept;
28101
28102
  /**
28103
   * return true if the automatically determined type of
28104
   * the number is number_type::signed_integer.
28105
   */
28106
  simdjson_inline bool is_int64() const noexcept;
28107
  /**
28108
   * return the value as a int64_t, only valid if is_int64() is true.
28109
   */
28110
  simdjson_inline int64_t get_int64() const noexcept;
28111
  simdjson_inline operator int64_t() const noexcept;
28112
28113
28114
  /**
28115
   * return true if the automatically determined type of
28116
   * the number is number_type::floating_point_number.
28117
   */
28118
  simdjson_inline bool is_double() const noexcept;
28119
  /**
28120
   * return the value as a double, only valid if is_double() is true.
28121
   */
28122
  simdjson_inline double get_double() const noexcept;
28123
  simdjson_inline operator double() const noexcept;
28124
28125
  /**
28126
   * Convert the number to a double. Though it always succeed, the conversion
28127
   * may be lossy if the number cannot be represented exactly.
28128
   */
28129
  simdjson_inline double as_double() const noexcept;
28130
28131
28132
protected:
28133
  /**
28134
   * The next block of declaration is designed so that we can call the number parsing
28135
   * functions on a number type. They are protected and should never be used outside
28136
   * of the core simdjson library.
28137
   */
28138
  friend class value_iterator;
28139
  template<typename W>
28140
  friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
28141
  template<typename W>
28142
  friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
28143
  /** Store a signed 64-bit value to the number. */
28144
  simdjson_inline void append_s64(int64_t value) noexcept;
28145
  /** Store an unsigned 64-bit value to the number. */
28146
  simdjson_inline void append_u64(uint64_t value) noexcept;
28147
  /** Store a double value to the number. */
28148
  simdjson_inline void append_double(double value) noexcept;
28149
  /** Specifies that the value is a double, but leave it undefined. */
28150
  simdjson_inline void skip_double() noexcept;
28151
  /**
28152
   * End of friend declarations.
28153
   */
28154
28155
  /**
28156
   * Our attributes are a union type (size = 64 bits)
28157
   * followed by a type indicator.
28158
   */
28159
  union {
28160
    double floating_point_number;
28161
    int64_t signed_integer;
28162
    uint64_t unsigned_integer;
28163
  } payload{0};
28164
  number_type type{number_type::signed_integer};
28165
};
28166
28167
/**
28168
 * Write the JSON type to the output stream
28169
 *
28170
 * @param out The output stream.
28171
 * @param type The json_type.
28172
 */
28173
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
28174
28175
#if SIMDJSON_EXCEPTIONS
28176
/**
28177
 * Send JSON type to an output stream.
28178
 *
28179
 * @param out The output stream.
28180
 * @param type The json_type.
28181
 * @throw simdjson_error if the result being printed has an error. If there is an error with the
28182
 *        underlying output stream, that error will be propagated (simdjson_error will not be
28183
 *        thrown).
28184
 */
28185
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false);
28186
#endif
28187
28188
} // namespace ondemand
28189
} // namespace arm64
28190
} // namespace simdjson
28191
28192
namespace simdjson {
28193
28194
template<>
28195
struct simdjson_result<arm64::ondemand::json_type> : public arm64::implementation_simdjson_result_base<arm64::ondemand::json_type> {
28196
public:
28197
  simdjson_inline simdjson_result(arm64::ondemand::json_type &&value) noexcept; ///< @private
28198
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
28199
  simdjson_inline simdjson_result() noexcept = default;
28200
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
28201
};
28202
28203
} // namespace simdjson
28204
28205
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
28206
/* end file simdjson/generic/ondemand/json_type.h for arm64 */
28207
/* including simdjson/generic/ondemand/raw_json_string.h for arm64: #include "simdjson/generic/ondemand/raw_json_string.h" */
28208
/* begin file simdjson/generic/ondemand/raw_json_string.h for arm64 */
28209
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
28210
28211
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
28212
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H */
28213
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
28214
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
28215
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
28216
28217
namespace simdjson {
28218
namespace arm64 {
28219
namespace ondemand {
28220
28221
/**
28222
 * A string escaped per JSON rules, terminated with quote ("). They are used to represent
28223
 * unescaped keys inside JSON documents.
28224
 *
28225
 * (In other words, a pointer to the beginning of a string, just after the start quote, inside a
28226
 * JSON file.)
28227
 *
28228
 * This class is deliberately simplistic and has little functionality. You can
28229
 * compare a raw_json_string instance with an unescaped C string, but
28230
 * that is nearly all you can do.
28231
 *
28232
 * The raw_json_string is unescaped. If you wish to write an unescaped version of it to your own
28233
 * buffer, you may do so using the parser.unescape(string, buff) method, using an ondemand::parser
28234
 * instance. Doing so requires you to have a sufficiently large buffer.
28235
 *
28236
 * The raw_json_string instances originate typically from field instance which in turn represent
28237
 * key-value pairs from object instances. From a field instance, you get the raw_json_string
28238
 * instance by calling key(). You can, if you want a more usable string_view instance, call
28239
 * the unescaped_key() method on the field instance. You may also create a raw_json_string from
28240
 * any other string value, with the value.get_raw_json_string() method. Again, you can get
28241
 * a more usable string_view instance by calling get_string().
28242
 *
28243
 */
28244
class raw_json_string {
28245
public:
28246
  /**
28247
   * Create a new invalid raw_json_string.
28248
   *
28249
   * Exists so you can declare a variable and later assign to it before use.
28250
   */
28251
  simdjson_inline raw_json_string() noexcept = default;
28252
28253
  /**
28254
   * Create a new invalid raw_json_string pointed at the given location in the JSON.
28255
   *
28256
   * The given location must be just *after* the beginning quote (") in the JSON file.
28257
   *
28258
   * It *must* be terminated by a ", and be a valid JSON string.
28259
   */
28260
  simdjson_inline raw_json_string(const uint8_t * _buf) noexcept;
28261
  /**
28262
   * Get the raw pointer to the beginning of the string in the JSON (just after the ").
28263
   *
28264
   * It is possible for this function to return a null pointer if the instance
28265
   * has outlived its existence.
28266
   */
28267
  simdjson_inline const char * raw() const noexcept;
28268
28269
  /**
28270
   * This compares the current instance to the std::string_view target: returns true if
28271
   * they are byte-by-byte equal (no escaping is done) on target.size() characters,
28272
   * and if the raw_json_string instance has a quote character at byte index target.size().
28273
   * We never read more than length + 1 bytes in the raw_json_string instance.
28274
   * If length is smaller than target.size(), this will return false.
28275
   *
28276
   * The std::string_view instance may contain any characters. However, the caller
28277
   * is responsible for setting length so that length bytes may be read in the
28278
   * raw_json_string.
28279
   *
28280
   * Performance: the comparison may be done using memcmp which may be efficient
28281
   * for long strings.
28282
   */
28283
  simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept;
28284
28285
  /**
28286
   * This compares the current instance to the std::string_view target: returns true if
28287
   * they are byte-by-byte equal (no escaping is done).
28288
   * The std::string_view instance should not contain unescaped quote characters:
28289
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
28290
   *
28291
   * Performance: the comparison is done byte-by-byte which might be inefficient for
28292
   * long strings.
28293
   *
28294
   * If target is a compile-time constant, and your compiler likes you,
28295
   * you should be able to do the following without performance penalty...
28296
   *
28297
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
28298
   *   s.unsafe_is_equal(target);
28299
   */
28300
  simdjson_inline bool unsafe_is_equal(std::string_view target) const noexcept;
28301
28302
  /**
28303
   * This compares the current instance to the C string target: returns true if
28304
   * they are byte-by-byte equal (no escaping is done).
28305
   * The provided C string should not contain an unescaped quote character:
28306
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
28307
   *
28308
   * If target is a compile-time constant, and your compiler likes you,
28309
   * you should be able to do the following without performance penalty...
28310
   *
28311
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
28312
   *   s.unsafe_is_equal(target);
28313
   */
28314
  simdjson_inline bool unsafe_is_equal(const char* target) const noexcept;
28315
28316
  /**
28317
   * This compares the current instance to the std::string_view target: returns true if
28318
   * they are byte-by-byte equal (no escaping is done).
28319
   */
28320
  simdjson_inline bool is_equal(std::string_view target) const noexcept;
28321
28322
  /**
28323
   * This compares the current instance to the C string target: returns true if
28324
   * they are byte-by-byte equal (no escaping is done).
28325
   */
28326
  simdjson_inline bool is_equal(const char* target) const noexcept;
28327
28328
  /**
28329
   * Returns true if target is free from unescaped quote. If target is known at
28330
   * compile-time, we might expect the computation to happen at compile time with
28331
   * many compilers (not all!).
28332
   */
28333
  static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
28334
  static simdjson_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
28335
28336
private:
28337
28338
28339
  /**
28340
   * This will set the inner pointer to zero, effectively making
28341
   * this instance unusable.
28342
   */
28343
  simdjson_inline void consume() noexcept { buf = nullptr; }
28344
28345
  /**
28346
   * Checks whether the inner pointer is non-null and thus usable.
28347
   */
28348
  simdjson_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
28349
28350
  /**
28351
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
28352
   * The result will be a valid UTF-8.
28353
   *
28354
   * ## IMPORTANT: string_view lifetime
28355
   *
28356
   * The string_view is only valid until the next parse() call on the parser.
28357
   *
28358
   * @param iter A json_iterator, which contains a buffer where the string will be written.
28359
   * @param allow_replacement Whether we allow replacement of invalid surrogate pairs.
28360
   */
28361
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(json_iterator &iter, bool allow_replacement) const noexcept;
28362
28363
  /**
28364
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
28365
   * The result may not be a valid UTF-8. https://simonsapin.github.io/wtf-8/
28366
   *
28367
   * ## IMPORTANT: string_view lifetime
28368
   *
28369
   * The string_view is only valid until the next parse() call on the parser.
28370
   *
28371
   * @param iter A json_iterator, which contains a buffer where the string will be written.
28372
   */
28373
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(json_iterator &iter) const noexcept;
28374
  const uint8_t * buf{};
28375
  friend class object;
28376
  friend class field;
28377
  friend class parser;
28378
  friend struct simdjson_result<raw_json_string>;
28379
};
28380
28381
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &, const raw_json_string &) noexcept;
28382
28383
/**
28384
 * Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user is responsible
28385
 * for providing a string with no unescaped quote. Note that unescaped quotes cannot be present in valid JSON strings.
28386
 */
28387
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept;
28388
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept;
28389
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept;
28390
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept;
28391
28392
28393
} // namespace ondemand
28394
} // namespace arm64
28395
} // namespace simdjson
28396
28397
namespace simdjson {
28398
28399
template<>
28400
struct simdjson_result<arm64::ondemand::raw_json_string> : public arm64::implementation_simdjson_result_base<arm64::ondemand::raw_json_string> {
28401
public:
28402
  simdjson_inline simdjson_result(arm64::ondemand::raw_json_string &&value) noexcept; ///< @private
28403
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
28404
  simdjson_inline simdjson_result() noexcept = default;
28405
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
28406
28407
  simdjson_inline simdjson_result<const char *> raw() const noexcept;
28408
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(arm64::ondemand::json_iterator &iter, bool allow_replacement) const noexcept;
28409
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(arm64::ondemand::json_iterator &iter) const noexcept;
28410
};
28411
28412
} // namespace simdjson
28413
28414
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
28415
/* end file simdjson/generic/ondemand/raw_json_string.h for arm64 */
28416
/* including simdjson/generic/ondemand/parser.h for arm64: #include "simdjson/generic/ondemand/parser.h" */
28417
/* begin file simdjson/generic/ondemand/parser.h for arm64 */
28418
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_H
28419
28420
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
28421
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_H */
28422
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
28423
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
28424
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
28425
28426
#include <memory>
28427
28428
namespace simdjson {
28429
namespace arm64 {
28430
namespace ondemand {
28431
28432
/**
28433
 * The default batch size for document_stream instances for this On Demand kernel.
28434
 * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value
28435
 * in the future.
28436
 */
28437
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
28438
/**
28439
 * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
28440
 * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
28441
 * most users will want a much larger batch size.
28442
 *
28443
 * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
28444
 * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
28445
 */
28446
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
28447
28448
/**
28449
 * A JSON fragment iterator.
28450
 *
28451
 * This holds the actual iterator as well as the buffer for writing strings.
28452
 */
28453
class parser {
28454
public:
28455
  /**
28456
   * Create a JSON parser.
28457
   *
28458
   * The new parser will have zero capacity.
28459
   */
28460
  inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
28461
28462
  inline parser(parser &&other) noexcept = default;
28463
  simdjson_inline parser(const parser &other) = delete;
28464
  simdjson_inline parser &operator=(const parser &other) = delete;
28465
  simdjson_inline parser &operator=(parser &&other) noexcept = default;
28466
28467
  /** Deallocate the JSON parser. */
28468
  inline ~parser() noexcept = default;
28469
28470
  /**
28471
   * Start iterating an on-demand JSON document.
28472
   *
28473
   *   ondemand::parser parser;
28474
   *   document doc = parser.iterate(json);
28475
   *
28476
   * It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
28477
   * Otherwise the iterate method may return an error. In particular, the whole input should be
28478
   * valid: we do not attempt to tolerate incorrect content either before or after a JSON
28479
   * document. If there is a UTF-8 BOM, the parser skips it.
28480
   *
28481
   * ### IMPORTANT: Validate what you use
28482
   *
28483
   * Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
28484
   * iterate does not parse and validate the whole document.
28485
   *
28486
   * ### IMPORTANT: Buffer Lifetime
28487
   *
28488
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
28489
   * long as the document iteration.
28490
   *
28491
   * ### IMPORTANT: Document Lifetime
28492
   *
28493
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
28494
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
28495
   * you call parse() again or destroy the parser.
28496
   *
28497
   * ### REQUIRED: Buffer Padding
28498
   *
28499
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
28500
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
28501
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
28502
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
28503
   *
28504
   * @param json The JSON to parse.
28505
   * @param len The length of the JSON.
28506
   * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
28507
   *
28508
   * @return The document, or an error:
28509
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
28510
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
28511
   *           allocation fails.
28512
   *         - EMPTY if the document is all whitespace.
28513
   *         - UTF8_ERROR if the document is not valid UTF-8.
28514
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
28515
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
28516
   */
28517
  simdjson_warn_unused simdjson_result<document> iterate(padded_string_view json) & noexcept;
28518
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28519
  simdjson_warn_unused simdjson_result<document> iterate(const char *json, size_t len, size_t capacity) & noexcept;
28520
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28521
  simdjson_warn_unused simdjson_result<document> iterate(const uint8_t *json, size_t len, size_t capacity) & noexcept;
28522
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28523
  simdjson_warn_unused simdjson_result<document> iterate(std::string_view json, size_t capacity) & noexcept;
28524
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28525
  simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
28526
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28527
  simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
28528
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28529
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
28530
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28531
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
28532
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
28533
  simdjson_warn_unused simdjson_result<document> iterate(padded_string &&json) & noexcept = delete;
28534
28535
  /**
28536
   * @private
28537
   *
28538
   * Start iterating an on-demand JSON document.
28539
   *
28540
   *   ondemand::parser parser;
28541
   *   json_iterator doc = parser.iterate(json);
28542
   *
28543
   * ### IMPORTANT: Buffer Lifetime
28544
   *
28545
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
28546
   * long as the document iteration.
28547
   *
28548
   * ### IMPORTANT: Document Lifetime
28549
   *
28550
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
28551
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
28552
   * you call parse() again or destroy the parser.
28553
   *
28554
   * The ondemand::document instance holds the iterator. The document must remain in scope
28555
   * while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
28556
   *
28557
   * ### REQUIRED: Buffer Padding
28558
   *
28559
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
28560
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
28561
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
28562
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
28563
   *
28564
   * @param json The JSON to parse.
28565
   *
28566
   * @return The iterator, or an error:
28567
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
28568
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
28569
   *           allocation fails.
28570
   *         - EMPTY if the document is all whitespace.
28571
   *         - UTF8_ERROR if the document is not valid UTF-8.
28572
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
28573
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
28574
   */
28575
  simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
28576
28577
28578
  /**
28579
   * Parse a buffer containing many JSON documents.
28580
   *
28581
   *   auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
28582
   *   ondemand::parser parser;
28583
   *   ondemand::document_stream docs = parser.iterate_many(json);
28584
   *   for (auto & doc : docs) {
28585
   *     std::cout << doc["foo"] << std::endl;
28586
   *   }
28587
   *   // Prints 1 2 3
28588
   *
28589
   * No copy of the input buffer is made.
28590
   *
28591
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
28592
   *
28593
   * The caller is responsabile to ensure that the input string data remains unchanged and is
28594
   * not deleted during the loop.
28595
   *
28596
   * ### Format
28597
   *
28598
   * The buffer must contain a series of one or more JSON documents, concatenated into a single
28599
   * buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
28600
   * then starts parsing the next document at that point. (It does this with more parallelism and
28601
   * lookahead than you might think, though.)
28602
   *
28603
   * documents that consist of an object or array may omit the whitespace between them, concatenating
28604
   * with no separator. Documents that consist of a single primitive (i.e. documents that are not
28605
   * arrays or objects) MUST be separated with ASCII whitespace.
28606
   *
28607
   * The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
28608
   * If there is a UTF-8 BOM, the parser skips it.
28609
   *
28610
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
28611
   * Setting batch_size to excessively large or excessively small values may impact negatively the
28612
   * performance.
28613
   *
28614
   * ### REQUIRED: Buffer Padding
28615
   *
28616
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
28617
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
28618
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
28619
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
28620
   *
28621
   * ### Threads
28622
   *
28623
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
28624
   * hood to do some lookahead.
28625
   *
28626
   * ### Parser Capacity
28627
   *
28628
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
28629
   * to handle it (up to max_capacity).
28630
   *
28631
   * @param buf The concatenated JSON to parse.
28632
   * @param len The length of the concatenated JSON.
28633
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
28634
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
28635
   *                   parse as many documents as possible in one tight loop.
28636
   *                   Defaults to 10MB, which has been a reasonable sweet spot in our tests.
28637
   * @param allow_comma_separated (defaults on false) This allows a mode where the documents are
28638
   *                   separated by commas instead of whitespace. It comes with a performance
28639
   *                   penalty because the entire document is indexed at once (and the document must be
28640
   *                   less than 4 GB), and there is no multithreading. In this mode, the batch_size parameter
28641
   *                   is effectively ignored, as it is set to at least the document size.
28642
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
28643
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails
28644
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
28645
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
28646
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
28647
   */
28648
  inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
28649
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
28650
  inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
28651
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
28652
  inline simdjson_result<document_stream> iterate_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
28653
  inline simdjson_result<document_stream> iterate_many(const std::string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
28654
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
28655
  inline simdjson_result<document_stream> iterate_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
28656
  inline simdjson_result<document_stream> iterate_many(const padded_string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
28657
28658
  /** @private We do not want to allow implicit conversion from C string to std::string. */
28659
  simdjson_result<document_stream> iterate_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
28660
28661
  /** The capacity of this parser (the largest document it can process). */
28662
  simdjson_inline size_t capacity() const noexcept;
28663
  /** The maximum capacity of this parser (the largest document it is allowed to process). */
28664
  simdjson_inline size_t max_capacity() const noexcept;
28665
  simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
28666
  /**
28667
   * The maximum depth of this parser (the most deeply nested objects and arrays it can process).
28668
   * This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
28669
   * The document's instance current_depth() method should be used to monitor the parsing
28670
   * depth and limit it if desired.
28671
   */
28672
  simdjson_inline size_t max_depth() const noexcept;
28673
28674
  /**
28675
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
28676
   * and `max_depth` depth.
28677
   *
28678
   * The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
28679
   * The document's instance current_depth() method should be used to monitor the parsing
28680
   * depth and limit it if desired.
28681
   *
28682
   * @param capacity The new capacity.
28683
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
28684
   * @return The error, if there is one.
28685
   */
28686
  simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
28687
28688
  #ifdef SIMDJSON_THREADS_ENABLED
28689
  /**
28690
   * The parser instance can use threads when they are available to speed up some
28691
   * operations. It is enabled by default. Changing this attribute will change the
28692
   * behavior of the parser for future operations.
28693
   */
28694
  bool threaded{true};
28695
  #endif
28696
28697
  /**
28698
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
28699
   * The result must be valid UTF-8.
28700
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
28701
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
28702
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
28703
   *
28704
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
28705
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
28706
   * instead of get_raw_json_string()).
28707
   *
28708
   * ## IMPORTANT: string_view lifetime
28709
   *
28710
   * The string_view is only valid as long as the bytes in dst.
28711
   *
28712
   * @param raw_json_string input
28713
   * @param dst A pointer to a buffer at least large enough to write this string as well as
28714
   *            an additional SIMDJSON_PADDING bytes.
28715
   * @param allow_replacement Whether we allow a replacement if the input string contains unmatched surrogate pairs.
28716
   * @return A string_view pointing at the unescaped string in dst
28717
   * @error STRING_ERROR if escapes are incorrect.
28718
   */
28719
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement = false) const noexcept;
28720
28721
  /**
28722
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
28723
   * The result may not be valid UTF-8. See https://simonsapin.github.io/wtf-8/
28724
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
28725
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
28726
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
28727
   *
28728
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
28729
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
28730
   * instead of get_raw_json_string()).
28731
   *
28732
   * ## IMPORTANT: string_view lifetime
28733
   *
28734
   * The string_view is only valid as long as the bytes in dst.
28735
   *
28736
   * @param raw_json_string input
28737
   * @param dst A pointer to a buffer at least large enough to write this string as well as
28738
   *            an additional SIMDJSON_PADDING bytes.
28739
   * @return A string_view pointing at the unescaped string in dst
28740
   * @error STRING_ERROR if escapes are incorrect.
28741
   */
28742
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept;
28743
28744
private:
28745
  /** @private [for benchmarking access] The implementation to use */
28746
  std::unique_ptr<internal::dom_parser_implementation> implementation{};
28747
  size_t _capacity{0};
28748
  size_t _max_capacity;
28749
  size_t _max_depth{DEFAULT_MAX_DEPTH};
28750
  std::unique_ptr<uint8_t[]> string_buf{};
28751
#if SIMDJSON_DEVELOPMENT_CHECKS
28752
  std::unique_ptr<token_position[]> start_positions{};
28753
#endif
28754
28755
  friend class json_iterator;
28756
  friend class document_stream;
28757
};
28758
28759
} // namespace ondemand
28760
} // namespace arm64
28761
} // namespace simdjson
28762
28763
namespace simdjson {
28764
28765
template<>
28766
struct simdjson_result<arm64::ondemand::parser> : public arm64::implementation_simdjson_result_base<arm64::ondemand::parser> {
28767
public:
28768
  simdjson_inline simdjson_result(arm64::ondemand::parser &&value) noexcept; ///< @private
28769
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
28770
  simdjson_inline simdjson_result() noexcept = default;
28771
};
28772
28773
} // namespace simdjson
28774
28775
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_H
28776
/* end file simdjson/generic/ondemand/parser.h for arm64 */
28777
28778
// All other declarations
28779
/* including simdjson/generic/ondemand/array.h for arm64: #include "simdjson/generic/ondemand/array.h" */
28780
/* begin file simdjson/generic/ondemand/array.h for arm64 */
28781
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
28782
28783
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
28784
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H */
28785
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
28786
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
28787
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
28788
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
28789
28790
namespace simdjson {
28791
namespace arm64 {
28792
namespace ondemand {
28793
28794
/**
28795
 * A forward-only JSON array.
28796
 */
28797
class array {
28798
public:
28799
  /**
28800
   * Create a new invalid array.
28801
   *
28802
   * Exists so you can declare a variable and later assign to it before use.
28803
   */
28804
  simdjson_inline array() noexcept = default;
28805
28806
  /**
28807
   * Begin array iteration.
28808
   *
28809
   * Part of the std::iterable interface.
28810
   */
28811
  simdjson_inline simdjson_result<array_iterator> begin() noexcept;
28812
  /**
28813
   * Sentinel representing the end of the array.
28814
   *
28815
   * Part of the std::iterable interface.
28816
   */
28817
  simdjson_inline simdjson_result<array_iterator> end() noexcept;
28818
  /**
28819
   * This method scans the array and counts the number of elements.
28820
   * The count_elements method should always be called before you have begun
28821
   * iterating through the array: it is expected that you are pointing at
28822
   * the beginning of the array.
28823
   * The runtime complexity is linear in the size of the array. After
28824
   * calling this function, if successful, the array is 'rewinded' at its
28825
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
28826
   * there is a missing comma), then an error is returned and it is no longer
28827
   * safe to continue.
28828
   *
28829
   * To check that an array is empty, it is more performant to use
28830
   * the is_empty() method.
28831
   */
28832
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
28833
  /**
28834
   * This method scans the beginning of the array and checks whether the
28835
   * array is empty.
28836
   * The runtime complexity is constant time. After
28837
   * calling this function, if successful, the array is 'rewinded' at its
28838
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
28839
   * there is a missing comma), then an error is returned and it is no longer
28840
   * safe to continue.
28841
   */
28842
  simdjson_inline simdjson_result<bool> is_empty() & noexcept;
28843
  /**
28844
   * Reset the iterator so that we are pointing back at the
28845
   * beginning of the array. You should still consume values only once even if you
28846
   * can iterate through the array more than once. If you unescape a string
28847
   * within the array more than once, you have unsafe code. Note that rewinding
28848
   * an array means that you may need to reparse it anew: it is not a free
28849
   * operation.
28850
   *
28851
   * @returns true if the array contains some elements (not empty)
28852
   */
28853
  inline simdjson_result<bool> reset() & noexcept;
28854
  /**
28855
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
28856
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
28857
   * as the root of its own JSON document.
28858
   *
28859
   *   ondemand::parser parser;
28860
   *   auto json = R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded;
28861
   *   auto doc = parser.iterate(json);
28862
   *   doc.at_pointer("/0/foo/a/1") == 20
28863
   *
28864
   * Note that at_pointer() called on the document automatically calls the document's rewind
28865
   * method between each call. It invalidates all previously accessed arrays, objects and values
28866
   * that have not been consumed. Yet it is not the case when calling at_pointer on an array
28867
   * instance: there is no rewind and no invalidation.
28868
   *
28869
   * You may only call at_pointer on an array after it has been created, but before it has
28870
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
28871
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
28872
   * to call at_pointer on the same array.
28873
   *
28874
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
28875
   *
28876
   * @return The value associated with the given JSON pointer, or:
28877
   *         - NO_SUCH_FIELD if a field does not exist in an object
28878
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
28879
   *         - INCORRECT_TYPE if a non-integer is used to access an array
28880
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
28881
   */
28882
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
28883
28884
  /**
28885
   * Get the value associated with the given JSONPath expression. We only support
28886
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
28887
   * names and array indices.
28888
   *
28889
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
28890
   *
28891
   * @return The value associated with the given JSONPath expression, or:
28892
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
28893
   *         - NO_SUCH_FIELD if a field does not exist in an object
28894
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
28895
   *         - INCORRECT_TYPE if a non-integer is used to access an array
28896
  */
28897
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
28898
28899
  /**
28900
   * Consumes the array and returns a string_view instance corresponding to the
28901
   * array as represented in JSON. It points inside the original document.
28902
   */
28903
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
28904
28905
  /**
28906
   * Get the value at the given index. This function has linear-time complexity.
28907
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
28908
   *
28909
   * @return The value at the given index, or:
28910
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
28911
   */
28912
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
28913
protected:
28914
  /**
28915
   * Go to the end of the array, no matter where you are right now.
28916
   */
28917
  simdjson_inline error_code consume() noexcept;
28918
28919
  /**
28920
   * Begin array iteration.
28921
   *
28922
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
28923
   *        resulting array.
28924
   * @error INCORRECT_TYPE if the iterator is not at [.
28925
   */
28926
  static simdjson_inline simdjson_result<array> start(value_iterator &iter) noexcept;
28927
  /**
28928
   * Begin array iteration from the root.
28929
   *
28930
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
28931
   *        resulting array.
28932
   * @error INCORRECT_TYPE if the iterator is not at [.
28933
   * @error TAPE_ERROR if there is no closing ] at the end of the document.
28934
   */
28935
  static simdjson_inline simdjson_result<array> start_root(value_iterator &iter) noexcept;
28936
  /**
28937
   * Begin array iteration.
28938
   *
28939
   * This version of the method should be called after the initial [ has been verified, and is
28940
   * intended for use by switch statements that check the type of a value.
28941
   *
28942
   * @param iter The iterator. Must be after the initial [. Will be *moved* into the resulting array.
28943
   */
28944
  static simdjson_inline simdjson_result<array> started(value_iterator &iter) noexcept;
28945
28946
  /**
28947
   * Create an array at the given Internal array creation. Call array::start() or array::started() instead of this.
28948
   *
28949
   * @param iter The iterator. Must either be at the start of the first element with iter.is_alive()
28950
   *        == true, or past the [] with is_alive() == false if the array is empty. Will be *moved*
28951
   *        into the resulting array.
28952
   */
28953
  simdjson_inline array(const value_iterator &iter) noexcept;
28954
28955
  /**
28956
   * Iterator marking current position.
28957
   *
28958
   * iter.is_alive() == false indicates iteration is complete.
28959
   */
28960
  value_iterator iter{};
28961
28962
  friend class value;
28963
  friend class document;
28964
  friend struct simdjson_result<value>;
28965
  friend struct simdjson_result<array>;
28966
  friend class array_iterator;
28967
};
28968
28969
} // namespace ondemand
28970
} // namespace arm64
28971
} // namespace simdjson
28972
28973
namespace simdjson {
28974
28975
template<>
28976
struct simdjson_result<arm64::ondemand::array> : public arm64::implementation_simdjson_result_base<arm64::ondemand::array> {
28977
public:
28978
  simdjson_inline simdjson_result(arm64::ondemand::array &&value) noexcept; ///< @private
28979
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
28980
  simdjson_inline simdjson_result() noexcept = default;
28981
28982
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> begin() noexcept;
28983
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> end() noexcept;
28984
  inline simdjson_result<size_t> count_elements() & noexcept;
28985
  inline simdjson_result<bool> is_empty() & noexcept;
28986
  inline simdjson_result<bool> reset() & noexcept;
28987
  simdjson_inline simdjson_result<arm64::ondemand::value> at(size_t index) noexcept;
28988
  simdjson_inline simdjson_result<arm64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
28989
  simdjson_inline simdjson_result<arm64::ondemand::value> at_path(std::string_view json_path) noexcept;
28990
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
28991
28992
};
28993
28994
} // namespace simdjson
28995
28996
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
28997
/* end file simdjson/generic/ondemand/array.h for arm64 */
28998
/* including simdjson/generic/ondemand/array_iterator.h for arm64: #include "simdjson/generic/ondemand/array_iterator.h" */
28999
/* begin file simdjson/generic/ondemand/array_iterator.h for arm64 */
29000
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
29001
29002
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
29003
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H */
29004
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
29005
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
29006
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
29007
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
29008
29009
29010
namespace simdjson {
29011
namespace arm64 {
29012
namespace ondemand {
29013
29014
/**
29015
 * A forward-only JSON array.
29016
 *
29017
 * This is an input_iterator, meaning:
29018
 * - It is forward-only
29019
 * - * must be called exactly once per element.
29020
 * - ++ must be called exactly once in between each * (*, ++, *, ++, * ...)
29021
 */
29022
class array_iterator {
29023
public:
29024
  /** Create a new, invalid array iterator. */
29025
  simdjson_inline array_iterator() noexcept = default;
29026
29027
  //
29028
  // Iterator interface
29029
  //
29030
29031
  /**
29032
   * Get the current element.
29033
   *
29034
   * Part of the std::iterator interface.
29035
   */
29036
  simdjson_inline simdjson_result<value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
29037
  /**
29038
   * Check if we are at the end of the JSON.
29039
   *
29040
   * Part of the std::iterator interface.
29041
   *
29042
   * @return true if there are no more elements in the JSON array.
29043
   */
29044
  simdjson_inline bool operator==(const array_iterator &) const noexcept;
29045
  /**
29046
   * Check if there are more elements in the JSON array.
29047
   *
29048
   * Part of the std::iterator interface.
29049
   *
29050
   * @return true if there are more elements in the JSON array.
29051
   */
29052
  simdjson_inline bool operator!=(const array_iterator &) const noexcept;
29053
  /**
29054
   * Move to the next element.
29055
   *
29056
   * Part of the std::iterator interface.
29057
   */
29058
  simdjson_inline array_iterator &operator++() noexcept;
29059
29060
private:
29061
  value_iterator iter{};
29062
29063
  simdjson_inline array_iterator(const value_iterator &iter) noexcept;
29064
29065
  friend class array;
29066
  friend class value;
29067
  friend struct simdjson_result<array_iterator>;
29068
};
29069
29070
} // namespace ondemand
29071
} // namespace arm64
29072
} // namespace simdjson
29073
29074
namespace simdjson {
29075
29076
template<>
29077
struct simdjson_result<arm64::ondemand::array_iterator> : public arm64::implementation_simdjson_result_base<arm64::ondemand::array_iterator> {
29078
public:
29079
  simdjson_inline simdjson_result(arm64::ondemand::array_iterator &&value) noexcept; ///< @private
29080
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
29081
  simdjson_inline simdjson_result() noexcept = default;
29082
29083
  //
29084
  // Iterator interface
29085
  //
29086
29087
  simdjson_inline simdjson_result<arm64::ondemand::value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
29088
  simdjson_inline bool operator==(const simdjson_result<arm64::ondemand::array_iterator> &) const noexcept;
29089
  simdjson_inline bool operator!=(const simdjson_result<arm64::ondemand::array_iterator> &) const noexcept;
29090
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> &operator++() noexcept;
29091
};
29092
29093
} // namespace simdjson
29094
29095
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
29096
/* end file simdjson/generic/ondemand/array_iterator.h for arm64 */
29097
/* including simdjson/generic/ondemand/document.h for arm64: #include "simdjson/generic/ondemand/document.h" */
29098
/* begin file simdjson/generic/ondemand/document.h for arm64 */
29099
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
29100
29101
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
29102
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */
29103
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
29104
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
29105
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
29106
29107
namespace simdjson {
29108
namespace arm64 {
29109
namespace ondemand {
29110
29111
/**
29112
 * A JSON document. It holds a json_iterator instance.
29113
 *
29114
 * Used by tokens to get text, and string buffer location.
29115
 *
29116
 * You must keep the document around during iteration.
29117
 */
29118
class document {
29119
public:
29120
  /**
29121
   * Create a new invalid document.
29122
   *
29123
   * Exists so you can declare a variable and later assign to it before use.
29124
   */
29125
  simdjson_inline document() noexcept = default;
29126
  simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
29127
  simdjson_inline document(document &&other) noexcept = default;
29128
  simdjson_inline document &operator=(const document &other) noexcept = delete;
29129
  simdjson_inline document &operator=(document &&other) noexcept = default;
29130
29131
  /**
29132
   * Cast this JSON value to an array.
29133
   *
29134
   * @returns An object that can be used to iterate the array.
29135
   * @returns INCORRECT_TYPE If the JSON value is not an array.
29136
   */
29137
  simdjson_inline simdjson_result<array> get_array() & noexcept;
29138
  /**
29139
   * Cast this JSON value to an object.
29140
   *
29141
   * @returns An object that can be used to look up or iterate fields.
29142
   * @returns INCORRECT_TYPE If the JSON value is not an object.
29143
   */
29144
  simdjson_inline simdjson_result<object> get_object() & noexcept;
29145
  /**
29146
   * Cast this JSON value to an unsigned integer.
29147
   *
29148
   * @returns A signed 64-bit integer.
29149
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
29150
   */
29151
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
29152
  /**
29153
   * Cast this JSON value (inside string) to an unsigned integer.
29154
   *
29155
   * @returns A signed 64-bit integer.
29156
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
29157
   */
29158
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
29159
  /**
29160
   * Cast this JSON value to a signed integer.
29161
   *
29162
   * @returns A signed 64-bit integer.
29163
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
29164
   */
29165
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
29166
  /**
29167
   * Cast this JSON value (inside string) to a signed integer.
29168
   *
29169
   * @returns A signed 64-bit integer.
29170
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
29171
   */
29172
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
29173
  /**
29174
   * Cast this JSON value to a double.
29175
   *
29176
   * @returns A double.
29177
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
29178
   */
29179
  simdjson_inline simdjson_result<double> get_double() noexcept;
29180
29181
  /**
29182
   * Cast this JSON value (inside string) to a double.
29183
   *
29184
   * @returns A double.
29185
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
29186
   */
29187
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
29188
  /**
29189
   * Cast this JSON value to a string.
29190
   *
29191
   * The string is guaranteed to be valid UTF-8.
29192
   *
29193
   * Important: Calling get_string() twice on the same document is an error.
29194
   *
29195
   * @param Whether to allow a replacement character for unmatched surrogate pairs.
29196
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
29197
   *          time it parses a document or when it is destroyed.
29198
   * @returns INCORRECT_TYPE if the JSON value is not a string.
29199
   */
29200
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
29201
  /**
29202
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
29203
   *
29204
   * The string is guaranteed to be valid UTF-8.
29205
   *
29206
   * Important: a value should be consumed once. Calling get_string() twice on the same value
29207
   * is an error.
29208
   *
29209
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
29210
   * We recommend you avoid allocating an std::string unless you need to.
29211
   *
29212
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
29213
   */
29214
  template <typename string_type>
29215
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
29216
  /**
29217
   * Cast this JSON value to a string.
29218
   *
29219
   * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/
29220
   *
29221
   * Important: Calling get_wobbly_string() twice on the same document is an error.
29222
   *
29223
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
29224
   *          time it parses a document or when it is destroyed.
29225
   * @returns INCORRECT_TYPE if the JSON value is not a string.
29226
   */
29227
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
29228
  /**
29229
   * Cast this JSON value to a raw_json_string.
29230
   *
29231
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
29232
   *
29233
   * @returns A pointer to the raw JSON for the given string.
29234
   * @returns INCORRECT_TYPE if the JSON value is not a string.
29235
   */
29236
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
29237
  /**
29238
   * Cast this JSON value to a bool.
29239
   *
29240
   * @returns A bool value.
29241
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
29242
   */
29243
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
29244
  /**
29245
   * Cast this JSON value to a value when the document is an object or an array.
29246
   *
29247
   * You must not have begun iterating through the object or array. When
29248
   * SIMDJSON_DEVELOPMENT_CHECKS is set to 1 (which is the case when building in Debug mode
29249
   * by default), and you have already begun iterating,
29250
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
29251
   * rewind() to reset the document to its initial state before calling this method.
29252
   *
29253
   * @returns A value if a JSON array or object cannot be found.
29254
   * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
29255
   */
29256
  simdjson_inline simdjson_result<value> get_value() noexcept;
29257
29258
  /**
29259
   * Checks if this JSON value is null.  If and only if the value is
29260
   * null, then it is consumed (we advance). If we find a token that
29261
   * begins with 'n' but is not 'null', then an error is returned.
29262
   *
29263
   * @returns Whether the value is null.
29264
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
29265
   */
29266
  simdjson_inline simdjson_result<bool> is_null() noexcept;
29267
29268
  /**
29269
   * Get this value as the given type.
29270
   *
29271
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
29272
   *
29273
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
29274
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
29275
   *
29276
   * @returns A value of the given type, parsed from the JSON.
29277
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
29278
   */
29279
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
29280
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
29281
    // immediately fail.
29282
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
29283
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
29284
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
29285
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
29286
      " You may also add support for custom types, see our documentation.");
29287
  }
29288
  /** @overload template<typename T> simdjson_result<T> get() & noexcept */
29289
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
29290
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
29291
    // immediately fail.
29292
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
29293
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
29294
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
29295
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
29296
      " You may also add support for custom types, see our documentation.");
29297
  }
29298
29299
  /**
29300
   * Get this value as the given type.
29301
   *
29302
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
29303
   *
29304
   * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
29305
   *
29306
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
29307
   * @returns INCORRECT_TYPE If the JSON value is not an object.
29308
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
29309
   */
29310
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
29311
  /** @overload template<typename T> error_code get(T &out) & noexcept */
29312
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
29313
29314
#if SIMDJSON_EXCEPTIONS
29315
  /**
29316
   * Cast this JSON value to an instance of type T. The programmer is responsible for
29317
   * providing an implementation of get<T> for the type T, if T is not one of the types
29318
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.)
29319
   *
29320
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
29321
   *
29322
   * @returns An instance of type T
29323
   */
29324
  template <class T>
29325
  explicit simdjson_inline operator T() noexcept(false);
29326
  /**
29327
   * Cast this JSON value to an array.
29328
   *
29329
   * @returns An object that can be used to iterate the array.
29330
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
29331
   */
29332
  simdjson_inline operator array() & noexcept(false);
29333
  /**
29334
   * Cast this JSON value to an object.
29335
   *
29336
   * @returns An object that can be used to look up or iterate fields.
29337
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
29338
   */
29339
  simdjson_inline operator object() & noexcept(false);
29340
  /**
29341
   * Cast this JSON value to an unsigned integer.
29342
   *
29343
   * @returns A signed 64-bit integer.
29344
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
29345
   */
29346
  simdjson_inline operator uint64_t() noexcept(false);
29347
  /**
29348
   * Cast this JSON value to a signed integer.
29349
   *
29350
   * @returns A signed 64-bit integer.
29351
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
29352
   */
29353
  simdjson_inline operator int64_t() noexcept(false);
29354
  /**
29355
   * Cast this JSON value to a double.
29356
   *
29357
   * @returns A double.
29358
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
29359
   */
29360
  simdjson_inline operator double() noexcept(false);
29361
  /**
29362
   * Cast this JSON value to a string.
29363
   *
29364
   * The string is guaranteed to be valid UTF-8.
29365
   *
29366
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
29367
   *          time it parses a document or when it is destroyed.
29368
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
29369
   */
29370
  simdjson_inline operator std::string_view() noexcept(false);
29371
  /**
29372
   * Cast this JSON value to a raw_json_string.
29373
   *
29374
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
29375
   *
29376
   * @returns A pointer to the raw JSON for the given string.
29377
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
29378
   */
29379
  simdjson_inline operator raw_json_string() noexcept(false);
29380
  /**
29381
   * Cast this JSON value to a bool.
29382
   *
29383
   * @returns A bool value.
29384
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
29385
   */
29386
  simdjson_inline operator bool() noexcept(false);
29387
  /**
29388
   * Cast this JSON value to a value when the document is an object or an array.
29389
   *
29390
   * You must not have begun iterating through the object or array. When
29391
   * SIMDJSON_DEVELOPMENT_CHECKS is defined, and you have already begun iterating,
29392
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
29393
   * rewind() to reset the document to its initial state before calling this method.
29394
   *
29395
   * @returns A value value if a JSON array or object cannot be found.
29396
   * @exception SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
29397
   */
29398
  simdjson_inline operator value() noexcept(false);
29399
#endif
29400
  /**
29401
   * This method scans the array and counts the number of elements.
29402
   * The count_elements method should always be called before you have begun
29403
   * iterating through the array: it is expected that you are pointing at
29404
   * the beginning of the array.
29405
   * The runtime complexity is linear in the size of the array. After
29406
   * calling this function, if successful, the array is 'rewinded' at its
29407
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
29408
   * there is a missing comma), then an error is returned and it is no longer
29409
   * safe to continue.
29410
   */
29411
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
29412
   /**
29413
   * This method scans the object and counts the number of key-value pairs.
29414
   * The count_fields method should always be called before you have begun
29415
   * iterating through the object: it is expected that you are pointing at
29416
   * the beginning of the object.
29417
   * The runtime complexity is linear in the size of the object. After
29418
   * calling this function, if successful, the object is 'rewinded' at its
29419
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
29420
   * there is a missing comma), then an error is returned and it is no longer
29421
   * safe to continue.
29422
   *
29423
   * To check that an object is empty, it is more performant to use
29424
   * the is_empty() method.
29425
   */
29426
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
29427
  /**
29428
   * Get the value at the given index in the array. This function has linear-time complexity.
29429
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
29430
   *
29431
   * @return The value at the given index, or:
29432
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
29433
   */
29434
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
29435
  /**
29436
   * Begin array iteration.
29437
   *
29438
   * Part of the std::iterable interface.
29439
   */
29440
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
29441
  /**
29442
   * Sentinel representing the end of the array.
29443
   *
29444
   * Part of the std::iterable interface.
29445
   */
29446
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
29447
29448
  /**
29449
   * Look up a field by name on an object (order-sensitive).
29450
   *
29451
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
29452
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
29453
   *
29454
   * ```c++
29455
   * simdjson::ondemand::parser parser;
29456
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
29457
   * double z = obj.find_field("z");
29458
   * double y = obj.find_field("y");
29459
   * double x = obj.find_field("x");
29460
   * ```
29461
   *
29462
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
29463
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
29464
   *
29465
   *
29466
   * You must consume the fields on an object one at a time. A request for a new key
29467
   * invalidates previous field values: it makes them unsafe. E.g., the array
29468
   * given by content["bids"].get_array() should not be accessed after you have called
29469
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
29470
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
29471
   * OUT_OF_ORDER_ITERATION error is generated.
29472
   *
29473
   * You are expected to access keys only once. You should access the value corresponding to
29474
   * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
29475
   * is an error.
29476
   *
29477
   * @param key The key to look up.
29478
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
29479
   */
29480
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
29481
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
29482
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
29483
29484
  /**
29485
   * Look up a field by name on an object, without regard to key order.
29486
   *
29487
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
29488
   * and often appears negligible. It starts out normally, starting out at the last field; but if
29489
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
29490
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
29491
   * in question is large. The fact that the extra code is there also bumps the executable size.
29492
   *
29493
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
29494
   * default behavior failed to look up a field just because it was in the wrong order--and many
29495
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
29496
   *
29497
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
29498
   * field was not there when they are not in order).
29499
   *
29500
   * You must consume the fields on an object one at a time. A request for a new key
29501
   * invalidates previous field values: it makes them unsafe. E.g., the array
29502
   * given by content["bids"].get_array() should not be accessed after you have called
29503
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
29504
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
29505
   * OUT_OF_ORDER_ITERATION error is generated.
29506
   *
29507
   * You are expected to access keys only once. You should access the value corresponding to a key
29508
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
29509
   * is an error.
29510
   *
29511
   * @param key The key to look up.
29512
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
29513
   */
29514
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
29515
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
29516
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
29517
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
29518
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
29519
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
29520
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
29521
29522
  /**
29523
   * Get the type of this JSON value. It does not validate or consume the value.
29524
   * E.g., you must still call "is_null()" to check that a value is null even if
29525
   * "type()" returns json_type::null.
29526
   *
29527
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
29528
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
29529
   * let it throw an exception).
29530
   *
29531
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
29532
   */
29533
  simdjson_inline simdjson_result<json_type> type() noexcept;
29534
29535
  /**
29536
   * Checks whether the document is a scalar (string, number, null, Boolean).
29537
   * Returns false when there it is an array or object.
29538
   *
29539
   * @returns true if the type is string, number, null, Boolean
29540
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
29541
   */
29542
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
29543
29544
  /**
29545
   * Checks whether the document is a string.
29546
   *
29547
   * @returns true if the type is string
29548
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
29549
   */
29550
  simdjson_inline simdjson_result<bool> is_string() noexcept;
29551
29552
  /**
29553
   * Checks whether the document is a negative number.
29554
   *
29555
   * @returns true if the number if negative.
29556
   */
29557
  simdjson_inline bool is_negative() noexcept;
29558
  /**
29559
   * Checks whether the document is an integer number. Note that
29560
   * this requires to partially parse the number string. If
29561
   * the value is determined to be an integer, it may still
29562
   * not parse properly as an integer in subsequent steps
29563
   * (e.g., it might overflow).
29564
   *
29565
   * @returns true if the number if negative.
29566
   */
29567
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
29568
  /**
29569
   * Determine the number type (integer or floating-point number) as quickly
29570
   * as possible. This function does not fully validate the input. It is
29571
   * useful when you only need to classify the numbers, without parsing them.
29572
   *
29573
   * If you are planning to retrieve the value or you need full validation,
29574
   * consider using the get_number() method instead: it will fully parse
29575
   * and validate the input, and give you access to the type:
29576
   * get_number().get_number_type().
29577
   *
29578
   * get_number_type() is number_type::unsigned_integer if we have
29579
   * an integer greater or equal to 9223372036854775808 and no larger than 18446744073709551615.
29580
   * get_number_type() is number_type::signed_integer if we have an
29581
   * integer that is less than 9223372036854775808 and greater or equal to -9223372036854775808.
29582
   * get_number_type() is number_type::big_integer if we have an integer outside
29583
   * of those ranges (either larger than 18446744073709551615 or smaller than -9223372036854775808).
29584
   * Otherwise, get_number_type() has value number_type::floating_point_number
29585
   *
29586
   * This function requires processing the number string, but it is expected
29587
   * to be faster than get_number().get_number_type() because it is does not
29588
   * parse the number value.
29589
   *
29590
   * @returns the type of the number
29591
   */
29592
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
29593
29594
  /**
29595
   * Attempt to parse an ondemand::number. An ondemand::number may
29596
   * contain an integer value or a floating-point value, the simdjson
29597
   * library will autodetect the type. Thus it is a dynamically typed
29598
   * number. Before accessing the value, you must determine the detected
29599
   * type.
29600
   *
29601
   * number.get_number_type() is number_type::signed_integer if we have
29602
   * an integer in [-9223372036854775808,9223372036854775808)
29603
   * You can recover the value by calling number.get_int64() and you
29604
   * have that number.is_int64() is true.
29605
   *
29606
   * number.get_number_type() is number_type::unsigned_integer if we have
29607
   * an integer in [9223372036854775808,18446744073709551616)
29608
   * You can recover the value by calling number.get_uint64() and you
29609
   * have that number.is_uint64() is true.
29610
   *
29611
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
29612
   * and we have a binary64 number.
29613
   * You can recover the value by calling number.get_double() and you
29614
   * have that number.is_double() is true.
29615
   *
29616
   * You must check the type before accessing the value: it is an error
29617
   * to call "get_int64()" when number.get_number_type() is not
29618
   * number_type::signed_integer and when number.is_int64() is false.
29619
   */
29620
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
29621
29622
  /**
29623
   * Get the raw JSON for this token.
29624
   *
29625
   * The string_view will always point into the input buffer.
29626
   *
29627
   * The string_view will start at the beginning of the token, and include the entire token
29628
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
29629
   * string token always begins with a " and is always terminated by the final ", possibly
29630
   * followed by a number of spaces.
29631
   *
29632
   * The string_view is *not* null-terminated. If this is a scalar (string, number,
29633
   * boolean, or null), the character after the end of the string_view may be the padded buffer.
29634
   *
29635
   * Tokens include:
29636
   * - {
29637
   * - [
29638
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
29639
   * - -1.2e-100
29640
   * - true
29641
   * - false
29642
   * - null
29643
   */
29644
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
29645
29646
  /**
29647
   * Reset the iterator inside the document instance so we are pointing back at the
29648
   * beginning of the document, as if it had just been created. It invalidates all
29649
   * values, objects and arrays that you have created so far (including unescaped strings).
29650
   */
29651
  inline void rewind() noexcept;
29652
  /**
29653
   * Returns debugging information.
29654
   */
29655
  inline std::string to_debug_string() noexcept;
29656
  /**
29657
   * Some unrecoverable error conditions may render the document instance unusable.
29658
   * The is_alive() method returns true when the document is still suitable.
29659
   */
29660
  inline bool is_alive() noexcept;
29661
29662
  /**
29663
   * Returns the current location in the document if in bounds.
29664
   */
29665
  inline simdjson_result<const char *> current_location() const noexcept;
29666
29667
  /**
29668
   * Returns true if this document has been fully parsed.
29669
   * If you have consumed the whole document and at_end() returns
29670
   * false, then there may be trailing content.
29671
   */
29672
  inline bool at_end() const noexcept;
29673
29674
  /**
29675
   * Returns the current depth in the document if in bounds.
29676
   *
29677
   * E.g.,
29678
   *  0 = finished with document
29679
   *  1 = document root value (could be [ or {, not yet known)
29680
   *  2 = , or } inside root array/object
29681
   *  3 = key or value inside root array/object.
29682
   */
29683
  simdjson_inline int32_t current_depth() const noexcept;
29684
29685
  /**
29686
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
29687
   * https://tools.ietf.org/html/rfc6901 standard.
29688
   *
29689
   *   ondemand::parser parser;
29690
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
29691
   *   auto doc = parser.iterate(json);
29692
   *   doc.at_pointer("/foo/a/1") == 20
29693
   *
29694
   * It is allowed for a key to be the empty string:
29695
   *
29696
   *   ondemand::parser parser;
29697
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
29698
   *   auto doc = parser.iterate(json);
29699
   *   doc.at_pointer("//a/1") == 20
29700
   *
29701
   * Key values are matched exactly, without unescaping or Unicode normalization.
29702
   * We do a byte-by-byte comparison. E.g.
29703
   *
29704
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
29705
   *   auto doc = parser.iterate(json);
29706
   *   doc.at_pointer("/\\u00E9") == 123
29707
   *   doc.at_pointer((const char*)u8"/\u00E9") returns an error (NO_SUCH_FIELD)
29708
   *
29709
   * Note that at_pointer() automatically calls rewind between each call. Thus
29710
   * all values, objects and arrays that you have created so far (including unescaped strings)
29711
   * are invalidated. After calling at_pointer, you need to consume the result: string values
29712
   * should be stored in your own variables, arrays should be decoded and stored in your own array-like
29713
   * structures and so forth.
29714
   *
29715
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
29716
   *
29717
   * @return The value associated with the given JSON pointer, or:
29718
   *         - NO_SUCH_FIELD if a field does not exist in an object
29719
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
29720
   *         - INCORRECT_TYPE if a non-integer is used to access an array
29721
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
29722
   *         - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
29723
   */
29724
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
29725
29726
  /**
29727
   * Get the value associated with the given JSONPath expression. We only support
29728
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
29729
   * names and array indices.
29730
   *
29731
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
29732
   *
29733
   * Key values are matched exactly, without unescaping or Unicode normalization.
29734
   * We do a byte-by-byte comparison. E.g.
29735
   *
29736
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
29737
   *   auto doc = parser.iterate(json);
29738
   *   doc.at_path(".\\u00E9") == 123
29739
   *   doc.at_path((const char*)u8".\u00E9") returns an error (NO_SUCH_FIELD)
29740
   *
29741
   * @return The value associated with the given JSONPath expression, or:
29742
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
29743
   *         - NO_SUCH_FIELD if a field does not exist in an object
29744
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
29745
   *         - INCORRECT_TYPE if a non-integer is used to access an array
29746
   */
29747
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
29748
29749
  /**
29750
   * Consumes the document and returns a string_view instance corresponding to the
29751
   * document as represented in JSON. It points inside the original byte array containing
29752
   * the JSON document.
29753
   */
29754
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
29755
protected:
29756
  /**
29757
   * Consumes the document.
29758
   */
29759
  simdjson_inline error_code consume() noexcept;
29760
29761
  simdjson_inline document(ondemand::json_iterator &&iter) noexcept;
29762
  simdjson_inline const uint8_t *text(uint32_t idx) const noexcept;
29763
29764
  simdjson_inline value_iterator resume_value_iterator() noexcept;
29765
  simdjson_inline value_iterator get_root_value_iterator() noexcept;
29766
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
29767
  static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept;
29768
29769
  //
29770
  // Fields
29771
  //
29772
  json_iterator iter{}; ///< Current position in the document
29773
  static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0
29774
29775
  friend class array_iterator;
29776
  friend class value;
29777
  friend class ondemand::parser;
29778
  friend class object;
29779
  friend class array;
29780
  friend class field;
29781
  friend class token;
29782
  friend class document_stream;
29783
  friend class document_reference;
29784
};
29785
29786
29787
/**
29788
 * A document_reference is a thin wrapper around a document reference instance.
29789
 */
29790
class document_reference {
29791
public:
29792
  simdjson_inline document_reference() noexcept;
29793
  simdjson_inline document_reference(document &d) noexcept;
29794
  simdjson_inline document_reference(const document_reference &other) noexcept = default;
29795
  simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default;
29796
  simdjson_inline void rewind() noexcept;
29797
  simdjson_inline simdjson_result<array> get_array() & noexcept;
29798
  simdjson_inline simdjson_result<object> get_object() & noexcept;
29799
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
29800
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
29801
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
29802
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
29803
  simdjson_inline simdjson_result<double> get_double() noexcept;
29804
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
29805
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
29806
  template <typename string_type>
29807
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
29808
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
29809
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
29810
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
29811
  simdjson_inline simdjson_result<value> get_value() noexcept;
29812
29813
  simdjson_inline simdjson_result<bool> is_null() noexcept;
29814
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
29815
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
29816
  simdjson_inline operator document&() const noexcept;
29817
#if SIMDJSON_EXCEPTIONS
29818
  template <class T>
29819
  explicit simdjson_inline operator T() noexcept(false);
29820
  simdjson_inline operator array() & noexcept(false);
29821
  simdjson_inline operator object() & noexcept(false);
29822
  simdjson_inline operator uint64_t() noexcept(false);
29823
  simdjson_inline operator int64_t() noexcept(false);
29824
  simdjson_inline operator double() noexcept(false);
29825
  simdjson_inline operator std::string_view() noexcept(false);
29826
  simdjson_inline operator raw_json_string() noexcept(false);
29827
  simdjson_inline operator bool() noexcept(false);
29828
  simdjson_inline operator value() noexcept(false);
29829
#endif
29830
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
29831
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
29832
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
29833
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
29834
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
29835
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
29836
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
29837
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
29838
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
29839
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
29840
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
29841
29842
  simdjson_inline simdjson_result<json_type> type() noexcept;
29843
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
29844
  simdjson_inline simdjson_result<bool> is_string() noexcept;
29845
29846
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
29847
  simdjson_inline int32_t current_depth() const noexcept;
29848
  simdjson_inline bool is_negative() noexcept;
29849
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
29850
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
29851
  simdjson_inline simdjson_result<number> get_number() noexcept;
29852
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
29853
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
29854
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
29855
29856
private:
29857
  document *doc{nullptr};
29858
};
29859
} // namespace ondemand
29860
} // namespace arm64
29861
} // namespace simdjson
29862
29863
namespace simdjson {
29864
29865
template<>
29866
struct simdjson_result<arm64::ondemand::document> : public arm64::implementation_simdjson_result_base<arm64::ondemand::document> {
29867
public:
29868
  simdjson_inline simdjson_result(arm64::ondemand::document &&value) noexcept; ///< @private
29869
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
29870
  simdjson_inline simdjson_result() noexcept = default;
29871
  simdjson_inline error_code rewind() noexcept;
29872
29873
  simdjson_inline simdjson_result<arm64::ondemand::array> get_array() & noexcept;
29874
  simdjson_inline simdjson_result<arm64::ondemand::object> get_object() & noexcept;
29875
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
29876
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
29877
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
29878
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
29879
  simdjson_inline simdjson_result<double> get_double() noexcept;
29880
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
29881
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
29882
  template <typename string_type>
29883
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
29884
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
29885
  simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> get_raw_json_string() noexcept;
29886
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
29887
  simdjson_inline simdjson_result<arm64::ondemand::value> get_value() noexcept;
29888
  simdjson_inline simdjson_result<bool> is_null() noexcept;
29889
29890
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
29891
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept;
29892
29893
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
29894
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
29895
#if SIMDJSON_EXCEPTIONS
29896
  template <class T, typename std::enable_if<std::is_same<T, arm64::ondemand::document>::value == false>::type>
29897
  explicit simdjson_inline operator T() noexcept(false);
29898
  simdjson_inline operator arm64::ondemand::array() & noexcept(false);
29899
  simdjson_inline operator arm64::ondemand::object() & noexcept(false);
29900
  simdjson_inline operator uint64_t() noexcept(false);
29901
  simdjson_inline operator int64_t() noexcept(false);
29902
  simdjson_inline operator double() noexcept(false);
29903
  simdjson_inline operator std::string_view() noexcept(false);
29904
  simdjson_inline operator arm64::ondemand::raw_json_string() noexcept(false);
29905
  simdjson_inline operator bool() noexcept(false);
29906
  simdjson_inline operator arm64::ondemand::value() noexcept(false);
29907
#endif
29908
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
29909
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
29910
  simdjson_inline simdjson_result<arm64::ondemand::value> at(size_t index) & noexcept;
29911
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> begin() & noexcept;
29912
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> end() & noexcept;
29913
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(std::string_view key) & noexcept;
29914
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(const char *key) & noexcept;
29915
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](std::string_view key) & noexcept;
29916
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](const char *key) & noexcept;
29917
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
29918
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(const char *key) & noexcept;
29919
  simdjson_inline simdjson_result<arm64::ondemand::json_type> type() noexcept;
29920
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
29921
  simdjson_inline simdjson_result<bool> is_string() noexcept;
29922
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
29923
  simdjson_inline int32_t current_depth() const noexcept;
29924
  simdjson_inline bool at_end() const noexcept;
29925
  simdjson_inline bool is_negative() noexcept;
29926
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
29927
  simdjson_inline simdjson_result<arm64::number_type> get_number_type() noexcept;
29928
  simdjson_inline simdjson_result<arm64::ondemand::number> get_number() noexcept;
29929
  /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */
29930
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
29931
29932
  simdjson_inline simdjson_result<arm64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
29933
  simdjson_inline simdjson_result<arm64::ondemand::value> at_path(std::string_view json_path) noexcept;
29934
};
29935
29936
29937
} // namespace simdjson
29938
29939
29940
29941
namespace simdjson {
29942
29943
template<>
29944
struct simdjson_result<arm64::ondemand::document_reference> : public arm64::implementation_simdjson_result_base<arm64::ondemand::document_reference> {
29945
public:
29946
  simdjson_inline simdjson_result(arm64::ondemand::document_reference value, error_code error) noexcept;
29947
  simdjson_inline simdjson_result() noexcept = default;
29948
  simdjson_inline error_code rewind() noexcept;
29949
29950
  simdjson_inline simdjson_result<arm64::ondemand::array> get_array() & noexcept;
29951
  simdjson_inline simdjson_result<arm64::ondemand::object> get_object() & noexcept;
29952
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
29953
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
29954
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
29955
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
29956
  simdjson_inline simdjson_result<double> get_double() noexcept;
29957
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
29958
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
29959
  template <typename string_type>
29960
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
29961
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
29962
  simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> get_raw_json_string() noexcept;
29963
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
29964
  simdjson_inline simdjson_result<arm64::ondemand::value> get_value() noexcept;
29965
  simdjson_inline simdjson_result<bool> is_null() noexcept;
29966
#if SIMDJSON_EXCEPTIONS
29967
  template <class T, typename std::enable_if<std::is_same<T, arm64::ondemand::document_reference>::value == false>::type>
29968
  explicit simdjson_inline operator T() noexcept(false);
29969
  simdjson_inline operator arm64::ondemand::array() & noexcept(false);
29970
  simdjson_inline operator arm64::ondemand::object() & noexcept(false);
29971
  simdjson_inline operator uint64_t() noexcept(false);
29972
  simdjson_inline operator int64_t() noexcept(false);
29973
  simdjson_inline operator double() noexcept(false);
29974
  simdjson_inline operator std::string_view() noexcept(false);
29975
  simdjson_inline operator arm64::ondemand::raw_json_string() noexcept(false);
29976
  simdjson_inline operator bool() noexcept(false);
29977
  simdjson_inline operator arm64::ondemand::value() noexcept(false);
29978
#endif
29979
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
29980
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
29981
  simdjson_inline simdjson_result<arm64::ondemand::value> at(size_t index) & noexcept;
29982
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> begin() & noexcept;
29983
  simdjson_inline simdjson_result<arm64::ondemand::array_iterator> end() & noexcept;
29984
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(std::string_view key) & noexcept;
29985
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(const char *key) & noexcept;
29986
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](std::string_view key) & noexcept;
29987
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](const char *key) & noexcept;
29988
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
29989
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(const char *key) & noexcept;
29990
  simdjson_inline simdjson_result<arm64::ondemand::json_type> type() noexcept;
29991
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
29992
  simdjson_inline simdjson_result<bool> is_string() noexcept;
29993
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
29994
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
29995
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
29996
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
29997
  simdjson_inline simdjson_result<arm64::number_type> get_number_type() noexcept;
29998
  simdjson_inline simdjson_result<arm64::ondemand::number> get_number() noexcept;
29999
  /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */
30000
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
30001
30002
  simdjson_inline simdjson_result<arm64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
30003
  simdjson_inline simdjson_result<arm64::ondemand::value> at_path(std::string_view json_path) noexcept;
30004
};
30005
30006
30007
} // namespace simdjson
30008
30009
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
30010
/* end file simdjson/generic/ondemand/document.h for arm64 */
30011
/* including simdjson/generic/ondemand/document_stream.h for arm64: #include "simdjson/generic/ondemand/document_stream.h" */
30012
/* begin file simdjson/generic/ondemand/document_stream.h for arm64 */
30013
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
30014
30015
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
30016
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H */
30017
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
30018
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
30019
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
30020
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
30021
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
30022
30023
#ifdef SIMDJSON_THREADS_ENABLED
30024
#include <thread>
30025
#include <mutex>
30026
#include <condition_variable>
30027
#endif
30028
30029
namespace simdjson {
30030
namespace arm64 {
30031
namespace ondemand {
30032
30033
#ifdef SIMDJSON_THREADS_ENABLED
30034
/** @private Custom worker class **/
30035
struct stage1_worker {
30036
  stage1_worker() noexcept = default;
30037
  stage1_worker(const stage1_worker&) = delete;
30038
  stage1_worker(stage1_worker&&) = delete;
30039
  stage1_worker operator=(const stage1_worker&) = delete;
30040
  ~stage1_worker();
30041
  /**
30042
   * We only start the thread when it is needed, not at object construction, this may throw.
30043
   * You should only call this once.
30044
   **/
30045
  void start_thread();
30046
  /**
30047
   * Start a stage 1 job. You should first call 'run', then 'finish'.
30048
   * You must call start_thread once before.
30049
   */
30050
  void run(document_stream * ds, parser * stage1, size_t next_batch_start);
30051
  /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
30052
  void finish();
30053
30054
private:
30055
30056
  /**
30057
   * Normally, we would never stop the thread. But we do in the destructor.
30058
   * This function is only safe assuming that you are not waiting for results. You
30059
   * should have called run, then finish, and be done.
30060
   **/
30061
  void stop_thread();
30062
30063
  std::thread thread{};
30064
  /** These three variables define the work done by the thread. **/
30065
  ondemand::parser * stage1_thread_parser{};
30066
  size_t _next_batch_start{};
30067
  document_stream * owner{};
30068
  /**
30069
   * We have two state variables. This could be streamlined to one variable in the future but
30070
   * we use two for clarity.
30071
   */
30072
  bool has_work{false};
30073
  bool can_work{true};
30074
30075
  /**
30076
   * We lock using a mutex.
30077
   */
30078
  std::mutex locking_mutex{};
30079
  std::condition_variable cond_var{};
30080
30081
  friend class document_stream;
30082
};
30083
#endif  // SIMDJSON_THREADS_ENABLED
30084
30085
/**
30086
 * A forward-only stream of documents.
30087
 *
30088
 * Produced by parser::iterate_many.
30089
 *
30090
 */
30091
class document_stream {
30092
public:
30093
  /**
30094
   * Construct an uninitialized document_stream.
30095
   *
30096
   *  ```c++
30097
   *  document_stream docs;
30098
   *  auto error = parser.iterate_many(json).get(docs);
30099
   *  ```
30100
   */
30101
  simdjson_inline document_stream() noexcept;
30102
  /** Move one document_stream to another. */
30103
  simdjson_inline document_stream(document_stream &&other) noexcept = default;
30104
  /** Move one document_stream to another. */
30105
  simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
30106
30107
  simdjson_inline ~document_stream() noexcept;
30108
30109
  /**
30110
   * Returns the input size in bytes.
30111
   */
30112
  inline size_t size_in_bytes() const noexcept;
30113
30114
  /**
30115
   * After iterating through the stream, this method
30116
   * returns the number of bytes that were not parsed at the end
30117
   * of the stream. If truncated_bytes() differs from zero,
30118
   * then the input was truncated maybe because incomplete JSON
30119
   * documents were found at the end of the stream. You
30120
   * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
30121
   *
30122
   * You should only call truncated_bytes() after streaming through all
30123
   * documents, like so:
30124
   *
30125
   *   document_stream stream = parser.iterate_many(json,window);
30126
   *   for(auto & doc : stream) {
30127
   *      // do something with doc
30128
   *   }
30129
   *   size_t truncated = stream.truncated_bytes();
30130
   *
30131
   */
30132
  inline size_t truncated_bytes() const noexcept;
30133
30134
  class iterator {
30135
  public:
30136
    using value_type = simdjson_result<document>;
30137
    using reference  = simdjson_result<ondemand::document_reference>;
30138
    using pointer    = void;
30139
    using difference_type   = std::ptrdiff_t;
30140
    using iterator_category = std::input_iterator_tag;
30141
30142
    /**
30143
     * Default constructor.
30144
     */
30145
    simdjson_inline iterator() noexcept;
30146
    /**
30147
     * Get the current document (or error).
30148
     */
30149
    simdjson_inline reference operator*() noexcept;
30150
    /**
30151
     * Advance to the next document (prefix).
30152
     */
30153
    inline iterator& operator++() noexcept;
30154
    /**
30155
     * Check if we're at the end yet.
30156
     * @param other the end iterator to compare to.
30157
     */
30158
    simdjson_inline bool operator!=(const iterator &other) const noexcept;
30159
    /**
30160
     * @private
30161
     *
30162
     * Gives the current index in the input document in bytes.
30163
     *
30164
     *   document_stream stream = parser.parse_many(json,window);
30165
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
30166
     *      auto doc = *i;
30167
     *      size_t index = i.current_index();
30168
     *   }
30169
     *
30170
     * This function (current_index()) is experimental and the usage
30171
     * may change in future versions of simdjson: we find the API somewhat
30172
     * awkward and we would like to offer something friendlier.
30173
     */
30174
     simdjson_inline size_t current_index() const noexcept;
30175
30176
     /**
30177
     * @private
30178
     *
30179
     * Gives a view of the current document at the current position.
30180
     *
30181
     *   document_stream stream = parser.iterate_many(json,window);
30182
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
30183
     *      std::string_view v = i.source();
30184
     *   }
30185
     *
30186
     * The returned string_view instance is simply a map to the (unparsed)
30187
     * source string: it may thus include white-space characters and all manner
30188
     * of padding.
30189
     *
30190
     * This function (source()) is experimental and the usage
30191
     * may change in future versions of simdjson: we find the API somewhat
30192
     * awkward and we would like to offer something friendlier.
30193
     *
30194
     */
30195
     simdjson_inline std::string_view source() const noexcept;
30196
30197
    /**
30198
     * Returns error of the stream (if any).
30199
     */
30200
     inline error_code error() const noexcept;
30201
30202
  private:
30203
    simdjson_inline iterator(document_stream *s, bool finished) noexcept;
30204
    /** The document_stream we're iterating through. */
30205
    document_stream* stream;
30206
    /** Whether we're finished or not. */
30207
    bool finished;
30208
30209
    friend class document;
30210
    friend class document_stream;
30211
    friend class json_iterator;
30212
  };
30213
30214
  /**
30215
   * Start iterating the documents in the stream.
30216
   */
30217
  simdjson_inline iterator begin() noexcept;
30218
  /**
30219
   * The end of the stream, for iterator comparison purposes.
30220
   */
30221
  simdjson_inline iterator end() noexcept;
30222
30223
private:
30224
30225
  document_stream &operator=(const document_stream &) = delete; // Disallow copying
30226
  document_stream(const document_stream &other) = delete; // Disallow copying
30227
30228
  /**
30229
   * Construct a document_stream. Does not allocate or parse anything until the iterator is
30230
   * used.
30231
   *
30232
   * @param parser is a reference to the parser instance used to generate this document_stream
30233
   * @param buf is the raw byte buffer we need to process
30234
   * @param len is the length of the raw byte buffer in bytes
30235
   * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
30236
   */
30237
  simdjson_inline document_stream(
30238
    ondemand::parser &parser,
30239
    const uint8_t *buf,
30240
    size_t len,
30241
    size_t batch_size,
30242
    bool allow_comma_separated
30243
  ) noexcept;
30244
30245
  /**
30246
   * Parse the first document in the buffer. Used by begin(), to handle allocation and
30247
   * initialization.
30248
   */
30249
  inline void start() noexcept;
30250
30251
  /**
30252
   * Parse the next document found in the buffer previously given to document_stream.
30253
   *
30254
   * The content should be a valid JSON document encoded as UTF-8. If there is a
30255
   * UTF-8 BOM, the parser skips it.
30256
   *
30257
   * You do NOT need to pre-allocate a parser.  This function takes care of
30258
   * pre-allocating a capacity defined by the batch_size defined when creating the
30259
   * document_stream object.
30260
   *
30261
   * The function returns simdjson::EMPTY if there is no more data to be parsed.
30262
   *
30263
   * The function returns simdjson::SUCCESS (as integer = 0) in case of success
30264
   * and indicates that the buffer has successfully been parsed to the end.
30265
   * Every document it contained has been parsed without error.
30266
   *
30267
   * The function returns an error code from simdjson/simdjson.h in case of failure
30268
   * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
30269
   * the simdjson::error_message function converts these error codes into a string).
30270
   *
30271
   * You can also check validity by calling parser.is_valid(). The same parser can
30272
   * and should be reused for the other documents in the buffer.
30273
   */
30274
  inline void next() noexcept;
30275
30276
  /** Move the json_iterator of the document to the location of the next document in the stream. */
30277
  inline void next_document() noexcept;
30278
30279
  /** Get the next document index. */
30280
  inline size_t next_batch_start() const noexcept;
30281
30282
  /** Pass the next batch through stage 1 with the given parser. */
30283
  inline error_code run_stage1(ondemand::parser &p, size_t batch_start) noexcept;
30284
30285
  // Fields
30286
  ondemand::parser *parser;
30287
  const uint8_t *buf;
30288
  size_t len;
30289
  size_t batch_size;
30290
  bool allow_comma_separated;
30291
  /**
30292
   * We are going to use just one document instance. The document owns
30293
   * the json_iterator. It implies that we only ever pass a reference
30294
   * to the document to the users.
30295
   */
30296
  document doc{};
30297
  /** The error (or lack thereof) from the current document. */
30298
  error_code error;
30299
  size_t batch_start{0};
30300
  size_t doc_index{};
30301
30302
  #ifdef SIMDJSON_THREADS_ENABLED
30303
  /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
30304
  bool use_thread;
30305
30306
  inline void load_from_stage1_thread() noexcept;
30307
30308
  /** Start a thread to run stage 1 on the next batch. */
30309
  inline void start_stage1_thread() noexcept;
30310
30311
  /** Wait for the stage 1 thread to finish and capture the results. */
30312
  inline void finish_stage1_thread() noexcept;
30313
30314
  /** The error returned from the stage 1 thread. */
30315
  error_code stage1_thread_error{UNINITIALIZED};
30316
  /** The thread used to run stage 1 against the next batch in the background. */
30317
  std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
30318
  /**
30319
   * The parser used to run stage 1 in the background. Will be swapped
30320
   * with the regular parser when finished.
30321
   */
30322
  ondemand::parser stage1_thread_parser{};
30323
30324
  friend struct stage1_worker;
30325
  #endif // SIMDJSON_THREADS_ENABLED
30326
30327
  friend class parser;
30328
  friend class document;
30329
  friend class json_iterator;
30330
  friend struct simdjson_result<ondemand::document_stream>;
30331
  friend struct internal::simdjson_result_base<ondemand::document_stream>;
30332
};  // document_stream
30333
30334
} // namespace ondemand
30335
} // namespace arm64
30336
} // namespace simdjson
30337
30338
namespace simdjson {
30339
template<>
30340
struct simdjson_result<arm64::ondemand::document_stream> : public arm64::implementation_simdjson_result_base<arm64::ondemand::document_stream> {
30341
public:
30342
  simdjson_inline simdjson_result(arm64::ondemand::document_stream &&value) noexcept; ///< @private
30343
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
30344
  simdjson_inline simdjson_result() noexcept = default;
30345
};
30346
30347
} // namespace simdjson
30348
30349
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
30350
/* end file simdjson/generic/ondemand/document_stream.h for arm64 */
30351
/* including simdjson/generic/ondemand/field.h for arm64: #include "simdjson/generic/ondemand/field.h" */
30352
/* begin file simdjson/generic/ondemand/field.h for arm64 */
30353
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
30354
30355
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
30356
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_H */
30357
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
30358
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
30359
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
30360
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
30361
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
30362
30363
namespace simdjson {
30364
namespace arm64 {
30365
namespace ondemand {
30366
30367
/**
30368
 * A JSON field (key/value pair) in an object.
30369
 *
30370
 * Returned from object iteration.
30371
 *
30372
 * Extends from std::pair<raw_json_string, value> so you can use C++ algorithms that rely on pairs.
30373
 */
30374
class field : public std::pair<raw_json_string, value> {
30375
public:
30376
  /**
30377
   * Create a new invalid field.
30378
   *
30379
   * Exists so you can declare a variable and later assign to it before use.
30380
   */
30381
  simdjson_inline field() noexcept;
30382
30383
  /**
30384
   * Get the key as a string_view (for higher speed, consider raw_key).
30385
   * We deliberately use a more cumbersome name (unescaped_key) to force users
30386
   * to think twice about using it.
30387
   *
30388
   * This consumes the key: once you have called unescaped_key(), you cannot
30389
   * call it again nor can you call key().
30390
   */
30391
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescaped_key(bool allow_replacement) noexcept;
30392
  /**
30393
   * Get the key as a raw_json_string. Can be used for direct comparison with
30394
   * an unescaped C string: e.g., key() == "test".
30395
   */
30396
  simdjson_inline raw_json_string key() const noexcept;
30397
  /**
30398
   * Get the unprocessed key as a string_view. This includes the quotes and may include
30399
   * some spaces after the last quote.
30400
   */
30401
  simdjson_inline std::string_view key_raw_json_token() const noexcept;
30402
  /**
30403
   * Get the field value.
30404
   */
30405
  simdjson_inline ondemand::value &value() & noexcept;
30406
  /**
30407
   * @overload ondemand::value &ondemand::value() & noexcept
30408
   */
30409
  simdjson_inline ondemand::value value() && noexcept;
30410
30411
protected:
30412
  simdjson_inline field(raw_json_string key, ondemand::value &&value) noexcept;
30413
  static simdjson_inline simdjson_result<field> start(value_iterator &parent_iter) noexcept;
30414
  static simdjson_inline simdjson_result<field> start(const value_iterator &parent_iter, raw_json_string key) noexcept;
30415
  friend struct simdjson_result<field>;
30416
  friend class object_iterator;
30417
};
30418
30419
} // namespace ondemand
30420
} // namespace arm64
30421
} // namespace simdjson
30422
30423
namespace simdjson {
30424
30425
template<>
30426
struct simdjson_result<arm64::ondemand::field> : public arm64::implementation_simdjson_result_base<arm64::ondemand::field> {
30427
public:
30428
  simdjson_inline simdjson_result(arm64::ondemand::field &&value) noexcept; ///< @private
30429
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
30430
  simdjson_inline simdjson_result() noexcept = default;
30431
30432
  simdjson_inline simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
30433
  simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> key() noexcept;
30434
  simdjson_inline simdjson_result<std::string_view> key_raw_json_token() noexcept;
30435
  simdjson_inline simdjson_result<arm64::ondemand::value> value() noexcept;
30436
};
30437
30438
} // namespace simdjson
30439
30440
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_H
30441
/* end file simdjson/generic/ondemand/field.h for arm64 */
30442
/* including simdjson/generic/ondemand/object.h for arm64: #include "simdjson/generic/ondemand/object.h" */
30443
/* begin file simdjson/generic/ondemand/object.h for arm64 */
30444
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
30445
30446
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
30447
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_H */
30448
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
30449
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
30450
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
30451
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
30452
30453
namespace simdjson {
30454
namespace arm64 {
30455
namespace ondemand {
30456
30457
/**
30458
 * A forward-only JSON object field iterator.
30459
 */
30460
class object {
30461
public:
30462
  /**
30463
   * Create a new invalid object.
30464
   *
30465
   * Exists so you can declare a variable and later assign to it before use.
30466
   */
30467
  simdjson_inline object() noexcept = default;
30468
30469
  simdjson_inline simdjson_result<object_iterator> begin() noexcept;
30470
  simdjson_inline simdjson_result<object_iterator> end() noexcept;
30471
  /**
30472
   * Look up a field by name on an object (order-sensitive).
30473
   *
30474
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
30475
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
30476
   *
30477
   * ```c++
30478
   * simdjson::ondemand::parser parser;
30479
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
30480
   * double z = obj.find_field("z");
30481
   * double y = obj.find_field("y");
30482
   * double x = obj.find_field("x");
30483
   * ```
30484
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
30485
   * that only one field is returned.
30486
   *
30487
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
30488
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
30489
   *
30490
   * You must consume the fields on an object one at a time. A request for a new key
30491
   * invalidates previous field values: it makes them unsafe. The value instance you get
30492
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
30493
   * given by content["bids"].get_array() should not be accessed after you have called
30494
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
30495
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
30496
   * OUT_OF_ORDER_ITERATION error is generated.
30497
   *
30498
   * You are expected to access keys only once. You should access the value corresponding to a
30499
   * key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
30500
   * is an error.
30501
   *
30502
   * @param key The key to look up.
30503
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
30504
   */
30505
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
30506
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
30507
  simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
30508
30509
  /**
30510
   * Look up a field by name on an object, without regard to key order.
30511
   *
30512
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
30513
   * and often appears negligible. It starts out normally, starting out at the last field; but if
30514
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
30515
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
30516
   * in question is large. The fact that the extra code is there also bumps the executable size.
30517
   *
30518
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
30519
   * default behavior failed to look up a field just because it was in the wrong order--and many
30520
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
30521
   *
30522
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
30523
   * field was not there when they are not in order).
30524
   *
30525
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
30526
   * that only one field is returned.
30527
   *
30528
   * You must consume the fields on an object one at a time. A request for a new key
30529
   * invalidates previous field values: it makes them unsafe. The value instance you get
30530
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
30531
   * given by content["bids"].get_array() should not be accessed after you have called
30532
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
30533
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
30534
   * OUT_OF_ORDER_ITERATION error is generated.
30535
   *
30536
   * You are expected to access keys only once. You should access the value corresponding to a key
30537
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
30538
   *
30539
   * @param key The key to look up.
30540
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
30541
   */
30542
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
30543
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
30544
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
30545
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
30546
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
30547
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
30548
  simdjson_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
30549
30550
  /**
30551
   * Get the value associated with the given JSON pointer. We use the RFC 6901
30552
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
30553
   * as the root of its own JSON document.
30554
   *
30555
   *   ondemand::parser parser;
30556
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
30557
   *   auto doc = parser.iterate(json);
30558
   *   doc.at_pointer("/foo/a/1") == 20
30559
   *
30560
   * It is allowed for a key to be the empty string:
30561
   *
30562
   *   ondemand::parser parser;
30563
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
30564
   *   auto doc = parser.iterate(json);
30565
   *   doc.at_pointer("//a/1") == 20
30566
   *
30567
   * Note that at_pointer() called on the document automatically calls the document's rewind
30568
   * method between each call. It invalidates all previously accessed arrays, objects and values
30569
   * that have not been consumed. Yet it is not the case when calling at_pointer on an object
30570
   * instance: there is no rewind and no invalidation.
30571
   *
30572
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
30573
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
30574
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
30575
   *
30576
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
30577
   *
30578
   * @return The value associated with the given JSON pointer, or:
30579
   *         - NO_SUCH_FIELD if a field does not exist in an object
30580
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
30581
   *         - INCORRECT_TYPE if a non-integer is used to access an array
30582
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
30583
   */
30584
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
30585
30586
  /**
30587
   * Get the value associated with the given JSONPath expression. We only support
30588
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
30589
   * names and array indices.
30590
   *
30591
   * @return The value associated with the given JSONPath expression, or:
30592
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
30593
   *         - NO_SUCH_FIELD if a field does not exist in an object
30594
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
30595
   *         - INCORRECT_TYPE if a non-integer is used to access an array
30596
   */
30597
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
30598
30599
  /**
30600
   * Reset the iterator so that we are pointing back at the
30601
   * beginning of the object. You should still consume values only once even if you
30602
   * can iterate through the object more than once. If you unescape a string within
30603
   * the object more than once, you have unsafe code. Note that rewinding an object
30604
   * means that you may need to reparse it anew: it is not a free operation.
30605
   *
30606
   * @returns true if the object contains some elements (not empty)
30607
   */
30608
  inline simdjson_result<bool> reset() & noexcept;
30609
  /**
30610
   * This method scans the beginning of the object and checks whether the
30611
   * object is empty.
30612
   * The runtime complexity is constant time. After
30613
   * calling this function, if successful, the object is 'rewinded' at its
30614
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
30615
   * there is a missing comma), then an error is returned and it is no longer
30616
   * safe to continue.
30617
   */
30618
  inline simdjson_result<bool> is_empty() & noexcept;
30619
  /**
30620
   * This method scans the object and counts the number of key-value pairs.
30621
   * The count_fields method should always be called before you have begun
30622
   * iterating through the object: it is expected that you are pointing at
30623
   * the beginning of the object.
30624
   * The runtime complexity is linear in the size of the object. After
30625
   * calling this function, if successful, the object is 'rewinded' at its
30626
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
30627
   * there is a missing comma), then an error is returned and it is no longer
30628
   * safe to continue.
30629
   *
30630
   * To check that an object is empty, it is more performant to use
30631
   * the is_empty() method.
30632
   *
30633
   * Performance hint: You should only call count_fields() as a last
30634
   * resort as it may require scanning the document twice or more.
30635
   */
30636
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
30637
  /**
30638
   * Consumes the object and returns a string_view instance corresponding to the
30639
   * object as represented in JSON. It points inside the original byte array containing
30640
   * the JSON document.
30641
   */
30642
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
30643
30644
protected:
30645
  /**
30646
   * Go to the end of the object, no matter where you are right now.
30647
   */
30648
  simdjson_inline error_code consume() noexcept;
30649
  static simdjson_inline simdjson_result<object> start(value_iterator &iter) noexcept;
30650
  static simdjson_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
30651
  static simdjson_inline simdjson_result<object> started(value_iterator &iter) noexcept;
30652
  static simdjson_inline object resume(const value_iterator &iter) noexcept;
30653
  simdjson_inline object(const value_iterator &iter) noexcept;
30654
30655
  simdjson_warn_unused simdjson_inline error_code find_field_raw(const std::string_view key) noexcept;
30656
30657
  value_iterator iter{};
30658
30659
  friend class value;
30660
  friend class document;
30661
  friend struct simdjson_result<object>;
30662
};
30663
30664
} // namespace ondemand
30665
} // namespace arm64
30666
} // namespace simdjson
30667
30668
namespace simdjson {
30669
30670
template<>
30671
struct simdjson_result<arm64::ondemand::object> : public arm64::implementation_simdjson_result_base<arm64::ondemand::object> {
30672
public:
30673
  simdjson_inline simdjson_result(arm64::ondemand::object &&value) noexcept; ///< @private
30674
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
30675
  simdjson_inline simdjson_result() noexcept = default;
30676
30677
  simdjson_inline simdjson_result<arm64::ondemand::object_iterator> begin() noexcept;
30678
  simdjson_inline simdjson_result<arm64::ondemand::object_iterator> end() noexcept;
30679
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(std::string_view key) & noexcept;
30680
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field(std::string_view key) && noexcept;
30681
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
30682
  simdjson_inline simdjson_result<arm64::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
30683
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](std::string_view key) & noexcept;
30684
  simdjson_inline simdjson_result<arm64::ondemand::value> operator[](std::string_view key) && noexcept;
30685
  simdjson_inline simdjson_result<arm64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
30686
  simdjson_inline simdjson_result<arm64::ondemand::value> at_path(std::string_view json_path) noexcept;
30687
30688
  inline simdjson_result<bool> reset() noexcept;
30689
  inline simdjson_result<bool> is_empty() noexcept;
30690
  inline simdjson_result<size_t> count_fields() & noexcept;
30691
  inline simdjson_result<std::string_view> raw_json() noexcept;
30692
30693
};
30694
30695
} // namespace simdjson
30696
30697
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
30698
/* end file simdjson/generic/ondemand/object.h for arm64 */
30699
/* including simdjson/generic/ondemand/object_iterator.h for arm64: #include "simdjson/generic/ondemand/object_iterator.h" */
30700
/* begin file simdjson/generic/ondemand/object_iterator.h for arm64 */
30701
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
30702
30703
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
30704
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H */
30705
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
30706
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
30707
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
30708
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
30709
30710
namespace simdjson {
30711
namespace arm64 {
30712
namespace ondemand {
30713
30714
class object_iterator {
30715
public:
30716
  /**
30717
   * Create a new invalid object_iterator.
30718
   *
30719
   * Exists so you can declare a variable and later assign to it before use.
30720
   */
30721
  simdjson_inline object_iterator() noexcept = default;
30722
30723
  //
30724
  // Iterator interface
30725
  //
30726
30727
  // Reads key and value, yielding them to the user.
30728
  // MUST ONLY BE CALLED ONCE PER ITERATION.
30729
  simdjson_inline simdjson_result<field> operator*() noexcept;
30730
  // Assumes it's being compared with the end. true if depth < iter->depth.
30731
  simdjson_inline bool operator==(const object_iterator &) const noexcept;
30732
  // Assumes it's being compared with the end. true if depth >= iter->depth.
30733
  simdjson_inline bool operator!=(const object_iterator &) const noexcept;
30734
  // Checks for ']' and ','
30735
  simdjson_inline object_iterator &operator++() noexcept;
30736
30737
private:
30738
  /**
30739
   * The underlying JSON iterator.
30740
   *
30741
   * PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
30742
   * is first used, and never changes afterwards.
30743
   */
30744
  value_iterator iter{};
30745
30746
  simdjson_inline object_iterator(const value_iterator &iter) noexcept;
30747
  friend struct simdjson_result<object_iterator>;
30748
  friend class object;
30749
};
30750
30751
} // namespace ondemand
30752
} // namespace arm64
30753
} // namespace simdjson
30754
30755
namespace simdjson {
30756
30757
template<>
30758
struct simdjson_result<arm64::ondemand::object_iterator> : public arm64::implementation_simdjson_result_base<arm64::ondemand::object_iterator> {
30759
public:
30760
  simdjson_inline simdjson_result(arm64::ondemand::object_iterator &&value) noexcept; ///< @private
30761
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
30762
  simdjson_inline simdjson_result() noexcept = default;
30763
30764
  //
30765
  // Iterator interface
30766
  //
30767
30768
  // Reads key and value, yielding them to the user.
30769
  simdjson_inline simdjson_result<arm64::ondemand::field> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
30770
  // Assumes it's being compared with the end. true if depth < iter->depth.
30771
  simdjson_inline bool operator==(const simdjson_result<arm64::ondemand::object_iterator> &) const noexcept;
30772
  // Assumes it's being compared with the end. true if depth >= iter->depth.
30773
  simdjson_inline bool operator!=(const simdjson_result<arm64::ondemand::object_iterator> &) const noexcept;
30774
  // Checks for ']' and ','
30775
  simdjson_inline simdjson_result<arm64::ondemand::object_iterator> &operator++() noexcept;
30776
};
30777
30778
} // namespace simdjson
30779
30780
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
30781
/* end file simdjson/generic/ondemand/object_iterator.h for arm64 */
30782
/* including simdjson/generic/ondemand/serialization.h for arm64: #include "simdjson/generic/ondemand/serialization.h" */
30783
/* begin file simdjson/generic/ondemand/serialization.h for arm64 */
30784
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
30785
30786
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
30787
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H */
30788
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
30789
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
30790
30791
namespace simdjson {
30792
/**
30793
 * Create a string-view instance out of a document instance. The string-view instance
30794
 * contains JSON text that is suitable to be parsed as JSON again. It does not
30795
 * validate the content.
30796
 */
30797
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::document& x) noexcept;
30798
/**
30799
 * Create a string-view instance out of a value instance. The string-view instance
30800
 * contains JSON text that is suitable to be parsed as JSON again. The value must
30801
 * not have been accessed previously. It does not
30802
 * validate the content.
30803
 */
30804
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::value& x) noexcept;
30805
/**
30806
 * Create a string-view instance out of an object instance. The string-view instance
30807
 * contains JSON text that is suitable to be parsed as JSON again. It does not
30808
 * validate the content.
30809
 */
30810
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::object& x) noexcept;
30811
/**
30812
 * Create a string-view instance out of an array instance. The string-view instance
30813
 * contains JSON text that is suitable to be parsed as JSON again. It does not
30814
 * validate the content.
30815
 */
30816
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::array& x) noexcept;
30817
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::document> x);
30818
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::value> x);
30819
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::object> x);
30820
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::array> x);
30821
} // namespace simdjson
30822
30823
/**
30824
 * We want to support argument-dependent lookup (ADL).
30825
 * Hence we should define operator<< in the namespace
30826
 * where the argument (here value, object, etc.) resides.
30827
 * Credit: @madhur4127
30828
 * See https://github.com/simdjson/simdjson/issues/1768
30829
 */
30830
namespace simdjson { namespace arm64 { namespace ondemand {
30831
30832
/**
30833
 * Print JSON to an output stream.  It does not
30834
 * validate the content.
30835
 *
30836
 * @param out The output stream.
30837
 * @param value The element.
30838
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
30839
 */
30840
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::value x);
30841
#if SIMDJSON_EXCEPTIONS
30842
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::value> x);
30843
#endif
30844
/**
30845
 * Print JSON to an output stream. It does not
30846
 * validate the content.
30847
 *
30848
 * @param out The output stream.
30849
 * @param value The array.
30850
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
30851
 */
30852
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::array value);
30853
#if SIMDJSON_EXCEPTIONS
30854
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::array> x);
30855
#endif
30856
/**
30857
 * Print JSON to an output stream. It does not
30858
 * validate the content.
30859
 *
30860
 * @param out The output stream.
30861
 * @param value The array.
30862
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
30863
 */
30864
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::document& value);
30865
#if SIMDJSON_EXCEPTIONS
30866
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::document>&& x);
30867
#endif
30868
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::document_reference& value);
30869
#if SIMDJSON_EXCEPTIONS
30870
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::document_reference>&& x);
30871
#endif
30872
/**
30873
 * Print JSON to an output stream. It does not
30874
 * validate the content.
30875
 *
30876
 * @param out The output stream.
30877
 * @param value The object.
30878
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
30879
 */
30880
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::object value);
30881
#if SIMDJSON_EXCEPTIONS
30882
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::object> x);
30883
#endif
30884
}}} // namespace simdjson::arm64::ondemand
30885
30886
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
30887
/* end file simdjson/generic/ondemand/serialization.h for arm64 */
30888
30889
// Inline definitions
30890
/* including simdjson/generic/ondemand/array-inl.h for arm64: #include "simdjson/generic/ondemand/array-inl.h" */
30891
/* begin file simdjson/generic/ondemand/array-inl.h for arm64 */
30892
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
30893
30894
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
30895
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H */
30896
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
30897
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
30898
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator-inl.h" */
30899
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
30900
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
30901
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
30902
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
30903
30904
namespace simdjson {
30905
namespace arm64 {
30906
namespace ondemand {
30907
30908
//
30909
// ### Live States
30910
//
30911
// While iterating or looking up values, depth >= iter->depth. at_start may vary. Error is
30912
// always SUCCESS:
30913
//
30914
// - Start: This is the state when the array is first found and the iterator is just past the `{`.
30915
//   In this state, at_start == true.
30916
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
30917
//   iterate over, the iterator is at the `,` before the next value (or `]`). In this state,
30918
//   depth == iter->depth, at_start == false, and error == SUCCESS.
30919
// - Unfinished Business: When we hand an array/object to the user which they do not fully
30920
//   iterate over, we need to finish that iteration by skipping child values until we reach the
30921
//   Next state. In this state, depth > iter->depth, at_start == false, and error == SUCCESS.
30922
//
30923
// ## Error States
30924
//
30925
// In error states, we will yield exactly one more value before stopping. iter->depth == depth
30926
// and at_start is always false. We decrement after yielding the error, moving to the Finished
30927
// state.
30928
//
30929
// - Chained Error: When the array iterator is part of an error chain--for example, in
30930
//   `for (auto tweet : doc["tweets"])`, where the tweet element may be missing or not be an
30931
//   array--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
30932
//   iter->depth == depth, and at_start == false. We decrement depth when we yield the error.
30933
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between elements,
30934
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
30935
//   error == TAPE_ERROR, iter->depth == depth, and at_start == false.
30936
//
30937
// ## Terminal State
30938
//
30939
// The terminal state has iter->depth < depth. at_start is always false.
30940
//
30941
// - Finished: When we have reached a `]` or have reported an error, we are finished. We signal this
30942
//   by decrementing depth. In this state, iter->depth < depth, at_start == false, and
30943
//   error == SUCCESS.
30944
//
30945
30946
simdjson_inline array::array(const value_iterator &_iter) noexcept
30947
  : iter{_iter}
30948
{
30949
}
30950
30951
simdjson_inline simdjson_result<array> array::start(value_iterator &iter) noexcept {
30952
  // We don't need to know if the array is empty to start iteration, but we do want to know if there
30953
  // is an error--thus `simdjson_unused`.
30954
  simdjson_unused bool has_value;
30955
  SIMDJSON_TRY( iter.start_array().get(has_value) );
30956
  return array(iter);
30957
}
30958
simdjson_inline simdjson_result<array> array::start_root(value_iterator &iter) noexcept {
30959
  simdjson_unused bool has_value;
30960
  SIMDJSON_TRY( iter.start_root_array().get(has_value) );
30961
  return array(iter);
30962
}
30963
simdjson_inline simdjson_result<array> array::started(value_iterator &iter) noexcept {
30964
  bool has_value;
30965
  SIMDJSON_TRY(iter.started_array().get(has_value));
30966
  return array(iter);
30967
}
30968
30969
simdjson_inline simdjson_result<array_iterator> array::begin() noexcept {
30970
#if SIMDJSON_DEVELOPMENT_CHECKS
30971
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
30972
#endif
30973
  return array_iterator(iter);
30974
}
30975
simdjson_inline simdjson_result<array_iterator> array::end() noexcept {
30976
  return array_iterator(iter);
30977
}
30978
simdjson_inline error_code array::consume() noexcept {
30979
  auto error = iter.json_iter().skip_child(iter.depth()-1);
30980
  if(error) { iter.abandon(); }
30981
  return error;
30982
}
30983
30984
simdjson_inline simdjson_result<std::string_view> array::raw_json() noexcept {
30985
  const uint8_t * starting_point{iter.peek_start()};
30986
  auto error = consume();
30987
  if(error) { return error; }
30988
  // After 'consume()', we could be left pointing just beyond the document, but that
30989
  // is ok because we are not going to dereference the final pointer position, we just
30990
  // use it to compute the length in bytes.
30991
  const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
30992
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
30993
}
30994
30995
SIMDJSON_PUSH_DISABLE_WARNINGS
30996
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
30997
simdjson_inline simdjson_result<size_t> array::count_elements() & noexcept {
30998
  size_t count{0};
30999
  // Important: we do not consume any of the values.
31000
  for(simdjson_unused auto v : *this) { count++; }
31001
  // The above loop will always succeed, but we want to report errors.
31002
  if(iter.error()) { return iter.error(); }
31003
  // We need to move back at the start because we expect users to iterate through
31004
  // the array after counting the number of elements.
31005
  iter.reset_array();
31006
  return count;
31007
}
31008
SIMDJSON_POP_DISABLE_WARNINGS
31009
31010
simdjson_inline simdjson_result<bool> array::is_empty() & noexcept {
31011
  bool is_not_empty;
31012
  auto error = iter.reset_array().get(is_not_empty);
31013
  if(error) { return error; }
31014
  return !is_not_empty;
31015
}
31016
31017
inline simdjson_result<bool> array::reset() & noexcept {
31018
  return iter.reset_array();
31019
}
31020
31021
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
31022
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
31023
  json_pointer = json_pointer.substr(1);
31024
  // - means "the append position" or "the element after the end of the array"
31025
  // We don't support this, because we're returning a real element, not a position.
31026
  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
31027
31028
  // Read the array index
31029
  size_t array_index = 0;
31030
  size_t i;
31031
  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
31032
    uint8_t digit = uint8_t(json_pointer[i] - '0');
31033
    // Check for non-digit in array index. If it's there, we're trying to get a field in an object
31034
    if (digit > 9) { return INCORRECT_TYPE; }
31035
    array_index = array_index*10 + digit;
31036
  }
31037
31038
  // 0 followed by other digits is invalid
31039
  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
31040
31041
  // Empty string is invalid; so is a "/" with no digits before it
31042
  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
31043
  // Get the child
31044
  auto child = at(array_index);
31045
  // If there is an error, it ends here
31046
  if(child.error()) {
31047
    return child;
31048
  }
31049
31050
  // If there is a /, we're not done yet, call recursively.
31051
  if (i < json_pointer.length()) {
31052
    child = child.at_pointer(json_pointer.substr(i));
31053
  }
31054
  return child;
31055
}
31056
31057
inline std::string json_path_to_pointer_conversion(std::string_view json_path) {
31058
  if (json_path.empty() || (json_path.front() != '.' &&
31059
      json_path.front() != '[')) {
31060
    return "-1"; // This is just a sentinel value, the caller should check for this and return an error.
31061
  }
31062
31063
  std::string result;
31064
  // Reserve space to reduce allocations, adjusting for potential increases due
31065
  // to escaping.
31066
  result.reserve(json_path.size() * 2);
31067
31068
  size_t i = 0;
31069
31070
  while (i < json_path.length()) {
31071
    if (json_path[i] == '.') {
31072
      result += '/';
31073
    } else if (json_path[i] == '[') {
31074
      result += '/';
31075
      ++i; // Move past the '['
31076
      while (i < json_path.length() && json_path[i] != ']') {
31077
          if (json_path[i] == '~') {
31078
            result += "~0";
31079
          } else if (json_path[i] == '/') {
31080
            result += "~1";
31081
          } else {
31082
            result += json_path[i];
31083
          }
31084
          ++i;
31085
      }
31086
      if (i == json_path.length() || json_path[i] != ']') {
31087
          return "-1"; // Using sentinel value that will be handled as an error by the caller.
31088
      }
31089
    } else {
31090
      if (json_path[i] == '~') {
31091
          result += "~0";
31092
      } else if (json_path[i] == '/') {
31093
          result += "~1";
31094
      } else {
31095
          result += json_path[i];
31096
      }
31097
    }
31098
    ++i;
31099
  }
31100
31101
  return result;
31102
}
31103
31104
inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept {
31105
  auto json_pointer = json_path_to_pointer_conversion(json_path);
31106
  if (json_pointer == "-1") { return INVALID_JSON_POINTER; }
31107
  return at_pointer(json_pointer);
31108
}
31109
31110
simdjson_inline simdjson_result<value> array::at(size_t index) noexcept {
31111
  size_t i = 0;
31112
  for (auto value : *this) {
31113
    if (i == index) { return value; }
31114
    i++;
31115
  }
31116
  return INDEX_OUT_OF_BOUNDS;
31117
}
31118
31119
} // namespace ondemand
31120
} // namespace arm64
31121
} // namespace simdjson
31122
31123
namespace simdjson {
31124
31125
simdjson_inline simdjson_result<arm64::ondemand::array>::simdjson_result(
31126
  arm64::ondemand::array &&value
31127
) noexcept
31128
  : implementation_simdjson_result_base<arm64::ondemand::array>(
31129
      std::forward<arm64::ondemand::array>(value)
31130
    )
31131
{
31132
}
31133
simdjson_inline simdjson_result<arm64::ondemand::array>::simdjson_result(
31134
  error_code error
31135
) noexcept
31136
  : implementation_simdjson_result_base<arm64::ondemand::array>(error)
31137
{
31138
}
31139
31140
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::array>::begin() noexcept {
31141
  if (error()) { return error(); }
31142
  return first.begin();
31143
}
31144
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::array>::end() noexcept {
31145
  if (error()) { return error(); }
31146
  return first.end();
31147
}
31148
simdjson_inline  simdjson_result<size_t> simdjson_result<arm64::ondemand::array>::count_elements() & noexcept {
31149
  if (error()) { return error(); }
31150
  return first.count_elements();
31151
}
31152
simdjson_inline  simdjson_result<bool> simdjson_result<arm64::ondemand::array>::is_empty() & noexcept {
31153
  if (error()) { return error(); }
31154
  return first.is_empty();
31155
}
31156
simdjson_inline  simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::array>::at(size_t index) noexcept {
31157
  if (error()) { return error(); }
31158
  return first.at(index);
31159
}
31160
simdjson_inline  simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::array>::at_pointer(std::string_view json_pointer) noexcept {
31161
  if (error()) { return error(); }
31162
  return first.at_pointer(json_pointer);
31163
}
31164
simdjson_inline  simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::array>::at_path(std::string_view json_path) noexcept {
31165
  if (error()) { return error(); }
31166
  return first.at_path(json_path);
31167
}
31168
simdjson_inline  simdjson_result<std::string_view> simdjson_result<arm64::ondemand::array>::raw_json() noexcept {
31169
  if (error()) { return error(); }
31170
  return first.raw_json();
31171
}
31172
} // namespace simdjson
31173
31174
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
31175
/* end file simdjson/generic/ondemand/array-inl.h for arm64 */
31176
/* including simdjson/generic/ondemand/array_iterator-inl.h for arm64: #include "simdjson/generic/ondemand/array_iterator-inl.h" */
31177
/* begin file simdjson/generic/ondemand/array_iterator-inl.h for arm64 */
31178
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
31179
31180
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
31181
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H */
31182
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
31183
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
31184
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
31185
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
31186
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
31187
31188
namespace simdjson {
31189
namespace arm64 {
31190
namespace ondemand {
31191
31192
simdjson_inline array_iterator::array_iterator(const value_iterator &_iter) noexcept
31193
  : iter{_iter}
31194
{}
31195
31196
simdjson_inline simdjson_result<value> array_iterator::operator*() noexcept {
31197
  if (iter.error()) { iter.abandon(); return iter.error(); }
31198
  return value(iter.child());
31199
}
31200
simdjson_inline bool array_iterator::operator==(const array_iterator &other) const noexcept {
31201
  return !(*this != other);
31202
}
31203
simdjson_inline bool array_iterator::operator!=(const array_iterator &) const noexcept {
31204
  return iter.is_open();
31205
}
31206
simdjson_inline array_iterator &array_iterator::operator++() noexcept {
31207
  error_code error;
31208
  // PERF NOTE this is a safety rail ... users should exit loops as soon as they receive an error, so we'll never get here.
31209
  // However, it does not seem to make a perf difference, so we add it out of an abundance of caution.
31210
  if (( error = iter.error() )) { return *this; }
31211
  if (( error = iter.skip_child() )) { return *this; }
31212
  if (( error = iter.has_next_element().error() )) { return *this; }
31213
  return *this;
31214
}
31215
31216
} // namespace ondemand
31217
} // namespace arm64
31218
} // namespace simdjson
31219
31220
namespace simdjson {
31221
31222
simdjson_inline simdjson_result<arm64::ondemand::array_iterator>::simdjson_result(
31223
  arm64::ondemand::array_iterator &&value
31224
) noexcept
31225
  : arm64::implementation_simdjson_result_base<arm64::ondemand::array_iterator>(std::forward<arm64::ondemand::array_iterator>(value))
31226
{
31227
  first.iter.assert_is_valid();
31228
}
31229
simdjson_inline simdjson_result<arm64::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
31230
  : arm64::implementation_simdjson_result_base<arm64::ondemand::array_iterator>({}, error)
31231
{
31232
}
31233
31234
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::array_iterator>::operator*() noexcept {
31235
  if (error()) { return error(); }
31236
  return *first;
31237
}
31238
simdjson_inline bool simdjson_result<arm64::ondemand::array_iterator>::operator==(const simdjson_result<arm64::ondemand::array_iterator> &other) const noexcept {
31239
  if (!first.iter.is_valid()) { return !error(); }
31240
  return first == other.first;
31241
}
31242
simdjson_inline bool simdjson_result<arm64::ondemand::array_iterator>::operator!=(const simdjson_result<arm64::ondemand::array_iterator> &other) const noexcept {
31243
  if (!first.iter.is_valid()) { return error(); }
31244
  return first != other.first;
31245
}
31246
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> &simdjson_result<arm64::ondemand::array_iterator>::operator++() noexcept {
31247
  // Clear the error if there is one, so we don't yield it twice
31248
  if (error()) { second = SUCCESS; return *this; }
31249
  ++(first);
31250
  return *this;
31251
}
31252
31253
} // namespace simdjson
31254
31255
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
31256
/* end file simdjson/generic/ondemand/array_iterator-inl.h for arm64 */
31257
/* including simdjson/generic/ondemand/document-inl.h for arm64: #include "simdjson/generic/ondemand/document-inl.h" */
31258
/* begin file simdjson/generic/ondemand/document-inl.h for arm64 */
31259
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
31260
31261
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
31262
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */
31263
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
31264
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */
31265
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
31266
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
31267
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
31268
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
31269
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
31270
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
31271
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */
31272
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
31273
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
31274
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
31275
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
31276
31277
namespace simdjson {
31278
namespace arm64 {
31279
namespace ondemand {
31280
31281
simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept
31282
  : iter{std::forward<json_iterator>(_iter)}
31283
{
31284
  logger::log_start_value(iter, "document");
31285
}
31286
31287
simdjson_inline document document::start(json_iterator &&iter) noexcept {
31288
  return document(std::forward<json_iterator>(iter));
31289
}
31290
31291
inline void document::rewind() noexcept {
31292
  iter.rewind();
31293
}
31294
31295
inline std::string document::to_debug_string() noexcept {
31296
  return iter.to_string();
31297
}
31298
31299
inline simdjson_result<const char *> document::current_location() const noexcept {
31300
  return iter.current_location();
31301
}
31302
31303
inline int32_t document::current_depth() const noexcept {
31304
  return iter.depth();
31305
}
31306
31307
inline bool document::at_end() const noexcept {
31308
  return iter.at_end();
31309
}
31310
31311
31312
inline bool document::is_alive() noexcept {
31313
  return iter.is_alive();
31314
}
31315
simdjson_inline value_iterator document::resume_value_iterator() noexcept {
31316
  return value_iterator(&iter, 1, iter.root_position());
31317
}
31318
simdjson_inline value_iterator document::get_root_value_iterator() noexcept {
31319
  return resume_value_iterator();
31320
}
31321
simdjson_inline simdjson_result<object> document::start_or_resume_object() noexcept {
31322
  if (iter.at_root()) {
31323
    return get_object();
31324
  } else {
31325
    return object::resume(resume_value_iterator());
31326
  }
31327
}
31328
simdjson_inline simdjson_result<value> document::get_value() noexcept {
31329
  // Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
31330
  // gets called.
31331
31332
  // It is the convention throughout the code that  the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether
31333
  // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error.
31334
#if SIMDJSON_DEVELOPMENT_CHECKS
31335
  if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; }
31336
#endif
31337
  // assert_at_root() serves two purposes: in Debug mode, whether or not
31338
  // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of
31339
  // the document (this will typically be redundant). In release mode, it generates
31340
  // SIMDJSON_ASSUME statements to allow the compiler to make assumptions.
31341
  iter.assert_at_root();
31342
  switch (*iter.peek()) {
31343
    case '[': {
31344
      // The following lines check that the document ends with ].
31345
      auto value_iterator = get_root_value_iterator();
31346
      auto error = value_iterator.check_root_array();
31347
      if(error) { return error; }
31348
      return value(get_root_value_iterator());
31349
    }
31350
    case '{': {
31351
      // The following lines would check that the document ends with }.
31352
      auto value_iterator = get_root_value_iterator();
31353
      auto error = value_iterator.check_root_object();
31354
      if(error) { return error; }
31355
      return value(get_root_value_iterator());
31356
    }
31357
    default:
31358
      // Unfortunately, scalar documents are a special case in simdjson and they cannot
31359
      // be safely converted to value instances.
31360
      return SCALAR_DOCUMENT_AS_VALUE;
31361
  }
31362
}
31363
simdjson_inline simdjson_result<array> document::get_array() & noexcept {
31364
  auto value = get_root_value_iterator();
31365
  return array::start_root(value);
31366
}
31367
simdjson_inline simdjson_result<object> document::get_object() & noexcept {
31368
  auto value = get_root_value_iterator();
31369
  return object::start_root(value);
31370
}
31371
31372
/**
31373
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
31374
 * give an error, so we check for trailing content. We want to disallow trailing
31375
 * content.
31376
 * Thus, in several implementations below, we pass a 'true' parameter value to
31377
 * a get_root_value_iterator() method: this indicates that we disallow trailing content.
31378
 */
31379
31380
simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
31381
  return get_root_value_iterator().get_root_uint64(true);
31382
}
31383
simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
31384
  return get_root_value_iterator().get_root_uint64_in_string(true);
31385
}
31386
simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
31387
  return get_root_value_iterator().get_root_int64(true);
31388
}
31389
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
31390
  return get_root_value_iterator().get_root_int64_in_string(true);
31391
}
31392
simdjson_inline simdjson_result<double> document::get_double() noexcept {
31393
  return get_root_value_iterator().get_root_double(true);
31394
}
31395
simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
31396
  return get_root_value_iterator().get_root_double_in_string(true);
31397
}
31398
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
31399
  return get_root_value_iterator().get_root_string(true, allow_replacement);
31400
}
31401
template <typename string_type>
31402
simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
31403
  return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
31404
}
31405
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
31406
  return get_root_value_iterator().get_root_wobbly_string(true);
31407
}
31408
simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
31409
  return get_root_value_iterator().get_root_raw_json_string(true);
31410
}
31411
simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
31412
  return get_root_value_iterator().get_root_bool(true);
31413
}
31414
simdjson_inline simdjson_result<bool> document::is_null() noexcept {
31415
  return get_root_value_iterator().is_root_null(true);
31416
}
31417
31418
template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
31419
template<> simdjson_inline simdjson_result<object> document::get() & noexcept { return get_object(); }
31420
template<> simdjson_inline simdjson_result<raw_json_string> document::get() & noexcept { return get_raw_json_string(); }
31421
template<> simdjson_inline simdjson_result<std::string_view> document::get() & noexcept { return get_string(false); }
31422
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
31423
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
31424
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
31425
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
31426
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
31427
31428
template<> simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
31429
template<> simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
31430
template<> simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
31431
template<> simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
31432
template<> simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
31433
template<> simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
31434
template<> simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
31435
31436
template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
31437
  return get<T>().get(out);
31438
}
31439
template<typename T> simdjson_inline error_code document::get(T &out) && noexcept {
31440
  return std::forward<document>(*this).get<T>().get(out);
31441
}
31442
31443
#if SIMDJSON_EXCEPTIONS
31444
template <class T>
31445
simdjson_inline document::operator T() noexcept(false) { return get<T>(); }
31446
simdjson_inline document::operator array() & noexcept(false) { return get_array(); }
31447
simdjson_inline document::operator object() & noexcept(false) { return get_object(); }
31448
simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); }
31449
simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); }
31450
simdjson_inline document::operator double() noexcept(false) { return get_double(); }
31451
simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); }
31452
simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
31453
simdjson_inline document::operator bool() noexcept(false) { return get_bool(); }
31454
simdjson_inline document::operator value() noexcept(false) { return get_value(); }
31455
31456
#endif
31457
simdjson_inline simdjson_result<size_t> document::count_elements() & noexcept {
31458
  auto a = get_array();
31459
  simdjson_result<size_t> answer = a.count_elements();
31460
  /* If there was an array, we are now left pointing at its first element. */
31461
  if(answer.error() == SUCCESS) { rewind(); }
31462
  return answer;
31463
}
31464
simdjson_inline simdjson_result<size_t> document::count_fields() & noexcept {
31465
  auto a = get_object();
31466
  simdjson_result<size_t> answer = a.count_fields();
31467
  /* If there was an object, we are now left pointing at its first element. */
31468
  if(answer.error() == SUCCESS) { rewind(); }
31469
  return answer;
31470
}
31471
simdjson_inline simdjson_result<value> document::at(size_t index) & noexcept {
31472
  auto a = get_array();
31473
  return a.at(index);
31474
}
31475
simdjson_inline simdjson_result<array_iterator> document::begin() & noexcept {
31476
  return get_array().begin();
31477
}
31478
simdjson_inline simdjson_result<array_iterator> document::end() & noexcept {
31479
  return {};
31480
}
31481
31482
simdjson_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
31483
  return start_or_resume_object().find_field(key);
31484
}
31485
simdjson_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
31486
  return start_or_resume_object().find_field(key);
31487
}
31488
simdjson_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
31489
  return start_or_resume_object().find_field_unordered(key);
31490
}
31491
simdjson_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
31492
  return start_or_resume_object().find_field_unordered(key);
31493
}
31494
simdjson_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
31495
  return start_or_resume_object()[key];
31496
}
31497
simdjson_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
31498
  return start_or_resume_object()[key];
31499
}
31500
31501
simdjson_inline error_code document::consume() noexcept {
31502
  auto error = iter.skip_child(0);
31503
  if(error) { iter.abandon(); }
31504
  return error;
31505
}
31506
31507
simdjson_inline simdjson_result<std::string_view> document::raw_json() noexcept {
31508
  auto _iter = get_root_value_iterator();
31509
  const uint8_t * starting_point{_iter.peek_start()};
31510
  auto error = consume();
31511
  if(error) { return error; }
31512
  // After 'consume()', we could be left pointing just beyond the document, but that
31513
  // is ok because we are not going to dereference the final pointer position, we just
31514
  // use it to compute the length in bytes.
31515
  const uint8_t * final_point{iter.unsafe_pointer()};
31516
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
31517
}
31518
31519
simdjson_inline simdjson_result<json_type> document::type() noexcept {
31520
  return get_root_value_iterator().type();
31521
}
31522
31523
simdjson_inline simdjson_result<bool> document::is_scalar() noexcept {
31524
  json_type this_type;
31525
  auto error = type().get(this_type);
31526
  if(error) { return error; }
31527
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
31528
}
31529
31530
simdjson_inline simdjson_result<bool> document::is_string() noexcept {
31531
  json_type this_type;
31532
  auto error = type().get(this_type);
31533
  if(error) { return error; }
31534
  return (this_type == json_type::string);
31535
}
31536
31537
simdjson_inline bool document::is_negative() noexcept {
31538
  return get_root_value_iterator().is_root_negative();
31539
}
31540
31541
simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
31542
  return get_root_value_iterator().is_root_integer(true);
31543
}
31544
31545
simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
31546
  return get_root_value_iterator().get_root_number_type(true);
31547
}
31548
31549
simdjson_inline simdjson_result<number> document::get_number() noexcept {
31550
  return get_root_value_iterator().get_root_number(true);
31551
}
31552
31553
31554
simdjson_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
31555
  auto _iter = get_root_value_iterator();
31556
  return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_root_length());
31557
}
31558
31559
simdjson_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
31560
  rewind(); // Rewind the document each time at_pointer is called
31561
  if (json_pointer.empty()) {
31562
    return this->get_value();
31563
  }
31564
  json_type t;
31565
  SIMDJSON_TRY(type().get(t));
31566
  switch (t)
31567
  {
31568
    case json_type::array:
31569
      return (*this).get_array().at_pointer(json_pointer);
31570
    case json_type::object:
31571
      return (*this).get_object().at_pointer(json_pointer);
31572
    default:
31573
      return INVALID_JSON_POINTER;
31574
  }
31575
}
31576
31577
simdjson_inline simdjson_result<value> document::at_path(std::string_view json_path) noexcept {
31578
  rewind(); // Rewind the document each time at_pointer is called
31579
  if (json_path.empty()) {
31580
      return this->get_value();
31581
  }
31582
  json_type t;
31583
  SIMDJSON_TRY(type().get(t));
31584
  switch (t) {
31585
  case json_type::array:
31586
      return (*this).get_array().at_path(json_path);
31587
  case json_type::object:
31588
      return (*this).get_object().at_path(json_path);
31589
  default:
31590
      return INVALID_JSON_POINTER;
31591
  }
31592
}
31593
31594
} // namespace ondemand
31595
} // namespace arm64
31596
} // namespace simdjson
31597
31598
namespace simdjson {
31599
31600
simdjson_inline simdjson_result<arm64::ondemand::document>::simdjson_result(
31601
  arm64::ondemand::document &&value
31602
) noexcept :
31603
    implementation_simdjson_result_base<arm64::ondemand::document>(
31604
      std::forward<arm64::ondemand::document>(value)
31605
    )
31606
{
31607
}
31608
simdjson_inline simdjson_result<arm64::ondemand::document>::simdjson_result(
31609
  error_code error
31610
) noexcept :
31611
    implementation_simdjson_result_base<arm64::ondemand::document>(
31612
      error
31613
    )
31614
{
31615
}
31616
simdjson_inline simdjson_result<size_t> simdjson_result<arm64::ondemand::document>::count_elements() & noexcept {
31617
  if (error()) { return error(); }
31618
  return first.count_elements();
31619
}
31620
simdjson_inline simdjson_result<size_t> simdjson_result<arm64::ondemand::document>::count_fields() & noexcept {
31621
  if (error()) { return error(); }
31622
  return first.count_fields();
31623
}
31624
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::at(size_t index) & noexcept {
31625
  if (error()) { return error(); }
31626
  return first.at(index);
31627
}
31628
simdjson_inline error_code simdjson_result<arm64::ondemand::document>::rewind() noexcept {
31629
  if (error()) { return error(); }
31630
  first.rewind();
31631
  return SUCCESS;
31632
}
31633
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::document>::begin() & noexcept {
31634
  if (error()) { return error(); }
31635
  return first.begin();
31636
}
31637
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::document>::end() & noexcept {
31638
  return {};
31639
}
31640
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
31641
  if (error()) { return error(); }
31642
  return first.find_field_unordered(key);
31643
}
31644
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::find_field_unordered(const char *key) & noexcept {
31645
  if (error()) { return error(); }
31646
  return first.find_field_unordered(key);
31647
}
31648
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::operator[](std::string_view key) & noexcept {
31649
  if (error()) { return error(); }
31650
  return first[key];
31651
}
31652
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::operator[](const char *key) & noexcept {
31653
  if (error()) { return error(); }
31654
  return first[key];
31655
}
31656
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::find_field(std::string_view key) & noexcept {
31657
  if (error()) { return error(); }
31658
  return first.find_field(key);
31659
}
31660
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::find_field(const char *key) & noexcept {
31661
  if (error()) { return error(); }
31662
  return first.find_field(key);
31663
}
31664
simdjson_inline simdjson_result<arm64::ondemand::array> simdjson_result<arm64::ondemand::document>::get_array() & noexcept {
31665
  if (error()) { return error(); }
31666
  return first.get_array();
31667
}
31668
simdjson_inline simdjson_result<arm64::ondemand::object> simdjson_result<arm64::ondemand::document>::get_object() & noexcept {
31669
  if (error()) { return error(); }
31670
  return first.get_object();
31671
}
31672
simdjson_inline simdjson_result<uint64_t> simdjson_result<arm64::ondemand::document>::get_uint64() noexcept {
31673
  if (error()) { return error(); }
31674
  return first.get_uint64();
31675
}
31676
simdjson_inline simdjson_result<uint64_t> simdjson_result<arm64::ondemand::document>::get_uint64_in_string() noexcept {
31677
  if (error()) { return error(); }
31678
  return first.get_uint64_in_string();
31679
}
31680
simdjson_inline simdjson_result<int64_t> simdjson_result<arm64::ondemand::document>::get_int64() noexcept {
31681
  if (error()) { return error(); }
31682
  return first.get_int64();
31683
}
31684
simdjson_inline simdjson_result<int64_t> simdjson_result<arm64::ondemand::document>::get_int64_in_string() noexcept {
31685
  if (error()) { return error(); }
31686
  return first.get_int64_in_string();
31687
}
31688
simdjson_inline simdjson_result<double> simdjson_result<arm64::ondemand::document>::get_double() noexcept {
31689
  if (error()) { return error(); }
31690
  return first.get_double();
31691
}
31692
simdjson_inline simdjson_result<double> simdjson_result<arm64::ondemand::document>::get_double_in_string() noexcept {
31693
  if (error()) { return error(); }
31694
  return first.get_double_in_string();
31695
}
31696
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::document>::get_string(bool allow_replacement) noexcept {
31697
  if (error()) { return error(); }
31698
  return first.get_string(allow_replacement);
31699
}
31700
template <typename string_type>
31701
simdjson_inline error_code simdjson_result<arm64::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
31702
  if (error()) { return error(); }
31703
  return first.get_string(receiver, allow_replacement);
31704
}
31705
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::document>::get_wobbly_string() noexcept {
31706
  if (error()) { return error(); }
31707
  return first.get_wobbly_string();
31708
}
31709
simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> simdjson_result<arm64::ondemand::document>::get_raw_json_string() noexcept {
31710
  if (error()) { return error(); }
31711
  return first.get_raw_json_string();
31712
}
31713
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document>::get_bool() noexcept {
31714
  if (error()) { return error(); }
31715
  return first.get_bool();
31716
}
31717
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::get_value() noexcept {
31718
  if (error()) { return error(); }
31719
  return first.get_value();
31720
}
31721
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document>::is_null() noexcept {
31722
  if (error()) { return error(); }
31723
  return first.is_null();
31724
}
31725
31726
template<typename T>
31727
simdjson_inline simdjson_result<T> simdjson_result<arm64::ondemand::document>::get() & noexcept {
31728
  if (error()) { return error(); }
31729
  return first.get<T>();
31730
}
31731
template<typename T>
31732
simdjson_inline simdjson_result<T> simdjson_result<arm64::ondemand::document>::get() && noexcept {
31733
  if (error()) { return error(); }
31734
  return std::forward<arm64::ondemand::document>(first).get<T>();
31735
}
31736
template<typename T>
31737
simdjson_inline error_code simdjson_result<arm64::ondemand::document>::get(T &out) & noexcept {
31738
  if (error()) { return error(); }
31739
  return first.get<T>(out);
31740
}
31741
template<typename T>
31742
simdjson_inline error_code simdjson_result<arm64::ondemand::document>::get(T &out) && noexcept {
31743
  if (error()) { return error(); }
31744
  return std::forward<arm64::ondemand::document>(first).get<T>(out);
31745
}
31746
31747
template<> simdjson_inline simdjson_result<arm64::ondemand::document> simdjson_result<arm64::ondemand::document>::get<arm64::ondemand::document>() & noexcept = delete;
31748
template<> simdjson_inline simdjson_result<arm64::ondemand::document> simdjson_result<arm64::ondemand::document>::get<arm64::ondemand::document>() && noexcept {
31749
  if (error()) { return error(); }
31750
  return std::forward<arm64::ondemand::document>(first);
31751
}
31752
template<> simdjson_inline error_code simdjson_result<arm64::ondemand::document>::get<arm64::ondemand::document>(arm64::ondemand::document &out) & noexcept = delete;
31753
template<> simdjson_inline error_code simdjson_result<arm64::ondemand::document>::get<arm64::ondemand::document>(arm64::ondemand::document &out) && noexcept {
31754
  if (error()) { return error(); }
31755
  out = std::forward<arm64::ondemand::document>(first);
31756
  return SUCCESS;
31757
}
31758
31759
simdjson_inline simdjson_result<arm64::ondemand::json_type> simdjson_result<arm64::ondemand::document>::type() noexcept {
31760
  if (error()) { return error(); }
31761
  return first.type();
31762
}
31763
31764
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document>::is_scalar() noexcept {
31765
  if (error()) { return error(); }
31766
  return first.is_scalar();
31767
}
31768
31769
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document>::is_string() noexcept {
31770
  if (error()) { return error(); }
31771
  return first.is_string();
31772
}
31773
31774
simdjson_inline bool simdjson_result<arm64::ondemand::document>::is_negative() noexcept {
31775
  if (error()) { return error(); }
31776
  return first.is_negative();
31777
}
31778
31779
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document>::is_integer() noexcept {
31780
  if (error()) { return error(); }
31781
  return first.is_integer();
31782
}
31783
31784
simdjson_inline simdjson_result<arm64::number_type> simdjson_result<arm64::ondemand::document>::get_number_type() noexcept {
31785
  if (error()) { return error(); }
31786
  return first.get_number_type();
31787
}
31788
31789
simdjson_inline simdjson_result<arm64::ondemand::number> simdjson_result<arm64::ondemand::document>::get_number() noexcept {
31790
  if (error()) { return error(); }
31791
  return first.get_number();
31792
}
31793
31794
31795
#if SIMDJSON_EXCEPTIONS
31796
template <class T, typename std::enable_if<std::is_same<T, arm64::ondemand::document>::value == false>::type>
31797
simdjson_inline simdjson_result<arm64::ondemand::document>::operator T() noexcept(false) {
31798
  if (error()) { throw simdjson_error(error()); }
31799
  return first;
31800
}
31801
simdjson_inline simdjson_result<arm64::ondemand::document>::operator arm64::ondemand::array() & noexcept(false) {
31802
  if (error()) { throw simdjson_error(error()); }
31803
  return first;
31804
}
31805
simdjson_inline simdjson_result<arm64::ondemand::document>::operator arm64::ondemand::object() & noexcept(false) {
31806
  if (error()) { throw simdjson_error(error()); }
31807
  return first;
31808
}
31809
simdjson_inline simdjson_result<arm64::ondemand::document>::operator uint64_t() noexcept(false) {
31810
  if (error()) { throw simdjson_error(error()); }
31811
  return first;
31812
}
31813
simdjson_inline simdjson_result<arm64::ondemand::document>::operator int64_t() noexcept(false) {
31814
  if (error()) { throw simdjson_error(error()); }
31815
  return first;
31816
}
31817
simdjson_inline simdjson_result<arm64::ondemand::document>::operator double() noexcept(false) {
31818
  if (error()) { throw simdjson_error(error()); }
31819
  return first;
31820
}
31821
simdjson_inline simdjson_result<arm64::ondemand::document>::operator std::string_view() noexcept(false) {
31822
  if (error()) { throw simdjson_error(error()); }
31823
  return first;
31824
}
31825
simdjson_inline simdjson_result<arm64::ondemand::document>::operator arm64::ondemand::raw_json_string() noexcept(false) {
31826
  if (error()) { throw simdjson_error(error()); }
31827
  return first;
31828
}
31829
simdjson_inline simdjson_result<arm64::ondemand::document>::operator bool() noexcept(false) {
31830
  if (error()) { throw simdjson_error(error()); }
31831
  return first;
31832
}
31833
simdjson_inline simdjson_result<arm64::ondemand::document>::operator arm64::ondemand::value() noexcept(false) {
31834
  if (error()) { throw simdjson_error(error()); }
31835
  return first;
31836
}
31837
#endif
31838
31839
31840
simdjson_inline simdjson_result<const char *> simdjson_result<arm64::ondemand::document>::current_location() noexcept {
31841
  if (error()) { return error(); }
31842
  return first.current_location();
31843
}
31844
31845
simdjson_inline bool simdjson_result<arm64::ondemand::document>::at_end() const noexcept {
31846
  if (error()) { return error(); }
31847
  return first.at_end();
31848
}
31849
31850
31851
simdjson_inline int32_t simdjson_result<arm64::ondemand::document>::current_depth() const noexcept {
31852
  if (error()) { return error(); }
31853
  return first.current_depth();
31854
}
31855
31856
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::document>::raw_json_token() noexcept {
31857
  if (error()) { return error(); }
31858
  return first.raw_json_token();
31859
}
31860
31861
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::at_pointer(std::string_view json_pointer) noexcept {
31862
  if (error()) { return error(); }
31863
  return first.at_pointer(json_pointer);
31864
}
31865
31866
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document>::at_path(std::string_view json_path) noexcept {
31867
  if (error()) { return error(); }
31868
  return first.at_path(json_path);
31869
}
31870
31871
} // namespace simdjson
31872
31873
31874
namespace simdjson {
31875
namespace arm64 {
31876
namespace ondemand {
31877
31878
simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {}
31879
simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
31880
simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
31881
simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
31882
simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
31883
/**
31884
 * The document_reference instances are used primarily/solely for streams of JSON
31885
 * documents.
31886
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
31887
 * give an error, so we check for trailing content.
31888
 *
31889
 * However, for streams of JSON documents, we want to be able to start from
31890
 * "321" "321" "321"
31891
 * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
31892
 * successfully each time.
31893
 *
31894
 * To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
31895
 * this indicates that we allow trailing content.
31896
 */
31897
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
31898
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
31899
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
31900
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
31901
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
31902
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
31903
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
31904
template <typename string_type>
31905
simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
31906
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
31907
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
31908
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
31909
simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
31910
simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
31911
template<> simdjson_inline simdjson_result<array> document_reference::get() & noexcept { return get_array(); }
31912
template<> simdjson_inline simdjson_result<object> document_reference::get() & noexcept { return get_object(); }
31913
template<> simdjson_inline simdjson_result<raw_json_string> document_reference::get() & noexcept { return get_raw_json_string(); }
31914
template<> simdjson_inline simdjson_result<std::string_view> document_reference::get() & noexcept { return get_string(false); }
31915
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
31916
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
31917
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
31918
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
31919
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
31920
#if SIMDJSON_EXCEPTIONS
31921
template <class T>
31922
simdjson_inline document_reference::operator T() noexcept(false) { return get<T>(); }
31923
simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
31924
simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
31925
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
31926
simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
31927
simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
31928
simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
31929
simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
31930
simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
31931
simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
31932
#endif
31933
simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
31934
simdjson_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
31935
simdjson_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
31936
simdjson_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
31937
simdjson_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
31938
simdjson_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
31939
simdjson_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
31940
simdjson_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
31941
simdjson_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
31942
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
31943
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
31944
simdjson_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
31945
simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
31946
simdjson_inline simdjson_result<bool> document_reference::is_string() noexcept { return doc->is_string(); }
31947
simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
31948
simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
31949
simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
31950
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
31951
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
31952
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
31953
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
31954
simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
31955
simdjson_inline simdjson_result<value> document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); }
31956
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
31957
simdjson_inline document_reference::operator document&() const noexcept { return *doc; }
31958
31959
} // namespace ondemand
31960
} // namespace arm64
31961
} // namespace simdjson
31962
31963
31964
31965
namespace simdjson {
31966
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::simdjson_result(arm64::ondemand::document_reference value, error_code error)
31967
  noexcept : implementation_simdjson_result_base<arm64::ondemand::document_reference>(std::forward<arm64::ondemand::document_reference>(value), error) {}
31968
31969
31970
simdjson_inline simdjson_result<size_t> simdjson_result<arm64::ondemand::document_reference>::count_elements() & noexcept {
31971
  if (error()) { return error(); }
31972
  return first.count_elements();
31973
}
31974
simdjson_inline simdjson_result<size_t> simdjson_result<arm64::ondemand::document_reference>::count_fields() & noexcept {
31975
  if (error()) { return error(); }
31976
  return first.count_fields();
31977
}
31978
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::at(size_t index) & noexcept {
31979
  if (error()) { return error(); }
31980
  return first.at(index);
31981
}
31982
simdjson_inline error_code simdjson_result<arm64::ondemand::document_reference>::rewind() noexcept {
31983
  if (error()) { return error(); }
31984
  first.rewind();
31985
  return SUCCESS;
31986
}
31987
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::document_reference>::begin() & noexcept {
31988
  if (error()) { return error(); }
31989
  return first.begin();
31990
}
31991
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::document_reference>::end() & noexcept {
31992
  return {};
31993
}
31994
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
31995
  if (error()) { return error(); }
31996
  return first.find_field_unordered(key);
31997
}
31998
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
31999
  if (error()) { return error(); }
32000
  return first.find_field_unordered(key);
32001
}
32002
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
32003
  if (error()) { return error(); }
32004
  return first[key];
32005
}
32006
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::operator[](const char *key) & noexcept {
32007
  if (error()) { return error(); }
32008
  return first[key];
32009
}
32010
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
32011
  if (error()) { return error(); }
32012
  return first.find_field(key);
32013
}
32014
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::find_field(const char *key) & noexcept {
32015
  if (error()) { return error(); }
32016
  return first.find_field(key);
32017
}
32018
simdjson_inline simdjson_result<arm64::ondemand::array> simdjson_result<arm64::ondemand::document_reference>::get_array() & noexcept {
32019
  if (error()) { return error(); }
32020
  return first.get_array();
32021
}
32022
simdjson_inline simdjson_result<arm64::ondemand::object> simdjson_result<arm64::ondemand::document_reference>::get_object() & noexcept {
32023
  if (error()) { return error(); }
32024
  return first.get_object();
32025
}
32026
simdjson_inline simdjson_result<uint64_t> simdjson_result<arm64::ondemand::document_reference>::get_uint64() noexcept {
32027
  if (error()) { return error(); }
32028
  return first.get_uint64();
32029
}
32030
simdjson_inline simdjson_result<uint64_t> simdjson_result<arm64::ondemand::document_reference>::get_uint64_in_string() noexcept {
32031
  if (error()) { return error(); }
32032
  return first.get_uint64_in_string();
32033
}
32034
simdjson_inline simdjson_result<int64_t> simdjson_result<arm64::ondemand::document_reference>::get_int64() noexcept {
32035
  if (error()) { return error(); }
32036
  return first.get_int64();
32037
}
32038
simdjson_inline simdjson_result<int64_t> simdjson_result<arm64::ondemand::document_reference>::get_int64_in_string() noexcept {
32039
  if (error()) { return error(); }
32040
  return first.get_int64_in_string();
32041
}
32042
simdjson_inline simdjson_result<double> simdjson_result<arm64::ondemand::document_reference>::get_double() noexcept {
32043
  if (error()) { return error(); }
32044
  return first.get_double();
32045
}
32046
simdjson_inline simdjson_result<double> simdjson_result<arm64::ondemand::document_reference>::get_double_in_string() noexcept {
32047
  if (error()) { return error(); }
32048
  return first.get_double_in_string();
32049
}
32050
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::document_reference>::get_string(bool allow_replacement) noexcept {
32051
  if (error()) { return error(); }
32052
  return first.get_string(allow_replacement);
32053
}
32054
template <typename string_type>
32055
simdjson_inline error_code simdjson_result<arm64::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
32056
  if (error()) { return error(); }
32057
  return first.get_string(receiver, allow_replacement);
32058
}
32059
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::document_reference>::get_wobbly_string() noexcept {
32060
  if (error()) { return error(); }
32061
  return first.get_wobbly_string();
32062
}
32063
simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> simdjson_result<arm64::ondemand::document_reference>::get_raw_json_string() noexcept {
32064
  if (error()) { return error(); }
32065
  return first.get_raw_json_string();
32066
}
32067
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document_reference>::get_bool() noexcept {
32068
  if (error()) { return error(); }
32069
  return first.get_bool();
32070
}
32071
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::get_value() noexcept {
32072
  if (error()) { return error(); }
32073
  return first.get_value();
32074
}
32075
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document_reference>::is_null() noexcept {
32076
  if (error()) { return error(); }
32077
  return first.is_null();
32078
}
32079
simdjson_inline simdjson_result<arm64::ondemand::json_type> simdjson_result<arm64::ondemand::document_reference>::type() noexcept {
32080
  if (error()) { return error(); }
32081
  return first.type();
32082
}
32083
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document_reference>::is_scalar() noexcept {
32084
  if (error()) { return error(); }
32085
  return first.is_scalar();
32086
}
32087
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document_reference>::is_string() noexcept {
32088
  if (error()) { return error(); }
32089
  return first.is_string();
32090
}
32091
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document_reference>::is_negative() noexcept {
32092
  if (error()) { return error(); }
32093
  return first.is_negative();
32094
}
32095
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::document_reference>::is_integer() noexcept {
32096
  if (error()) { return error(); }
32097
  return first.is_integer();
32098
}
32099
simdjson_inline simdjson_result<arm64::number_type> simdjson_result<arm64::ondemand::document_reference>::get_number_type() noexcept {
32100
  if (error()) { return error(); }
32101
  return first.get_number_type();
32102
}
32103
simdjson_inline simdjson_result<arm64::ondemand::number> simdjson_result<arm64::ondemand::document_reference>::get_number() noexcept {
32104
  if (error()) { return error(); }
32105
  return first.get_number();
32106
}
32107
#if SIMDJSON_EXCEPTIONS
32108
template <class T, typename std::enable_if<std::is_same<T, arm64::ondemand::document_reference>::value == false>::type>
32109
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator T() noexcept(false) {
32110
  if (error()) { throw simdjson_error(error()); }
32111
  return first;
32112
}
32113
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator arm64::ondemand::array() & noexcept(false) {
32114
  if (error()) { throw simdjson_error(error()); }
32115
  return first;
32116
}
32117
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator arm64::ondemand::object() & noexcept(false) {
32118
  if (error()) { throw simdjson_error(error()); }
32119
  return first;
32120
}
32121
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator uint64_t() noexcept(false) {
32122
  if (error()) { throw simdjson_error(error()); }
32123
  return first;
32124
}
32125
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator int64_t() noexcept(false) {
32126
  if (error()) { throw simdjson_error(error()); }
32127
  return first;
32128
}
32129
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator double() noexcept(false) {
32130
  if (error()) { throw simdjson_error(error()); }
32131
  return first;
32132
}
32133
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator std::string_view() noexcept(false) {
32134
  if (error()) { throw simdjson_error(error()); }
32135
  return first;
32136
}
32137
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator arm64::ondemand::raw_json_string() noexcept(false) {
32138
  if (error()) { throw simdjson_error(error()); }
32139
  return first;
32140
}
32141
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator bool() noexcept(false) {
32142
  if (error()) { throw simdjson_error(error()); }
32143
  return first;
32144
}
32145
simdjson_inline simdjson_result<arm64::ondemand::document_reference>::operator arm64::ondemand::value() noexcept(false) {
32146
  if (error()) { throw simdjson_error(error()); }
32147
  return first;
32148
}
32149
#endif
32150
32151
simdjson_inline simdjson_result<const char *> simdjson_result<arm64::ondemand::document_reference>::current_location() noexcept {
32152
  if (error()) { return error(); }
32153
  return first.current_location();
32154
}
32155
32156
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::document_reference>::raw_json_token() noexcept {
32157
  if (error()) { return error(); }
32158
  return first.raw_json_token();
32159
}
32160
32161
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
32162
  if (error()) { return error(); }
32163
  return first.at_pointer(json_pointer);
32164
}
32165
32166
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::document_reference>::at_path(std::string_view json_path) noexcept {
32167
  if (error()) {
32168
      return error();
32169
  }
32170
  return first.at_path(json_path);
32171
}
32172
32173
} // namespace simdjson
32174
32175
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
32176
/* end file simdjson/generic/ondemand/document-inl.h for arm64 */
32177
/* including simdjson/generic/ondemand/document_stream-inl.h for arm64: #include "simdjson/generic/ondemand/document_stream-inl.h" */
32178
/* begin file simdjson/generic/ondemand/document_stream-inl.h for arm64 */
32179
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
32180
32181
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
32182
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */
32183
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
32184
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
32185
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
32186
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
32187
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
32188
32189
#include <algorithm>
32190
#include <stdexcept>
32191
32192
namespace simdjson {
32193
namespace arm64 {
32194
namespace ondemand {
32195
32196
#ifdef SIMDJSON_THREADS_ENABLED
32197
32198
inline void stage1_worker::finish() {
32199
  // After calling "run" someone would call finish() to wait
32200
  // for the end of the processing.
32201
  // This function will wait until either the thread has done
32202
  // the processing or, else, the destructor has been called.
32203
  std::unique_lock<std::mutex> lock(locking_mutex);
32204
  cond_var.wait(lock, [this]{return has_work == false;});
32205
}
32206
32207
inline stage1_worker::~stage1_worker() {
32208
  // The thread may never outlive the stage1_worker instance
32209
  // and will always be stopped/joined before the stage1_worker
32210
  // instance is gone.
32211
  stop_thread();
32212
}
32213
32214
inline void stage1_worker::start_thread() {
32215
  std::unique_lock<std::mutex> lock(locking_mutex);
32216
  if(thread.joinable()) {
32217
    return; // This should never happen but we never want to create more than one thread.
32218
  }
32219
  thread = std::thread([this]{
32220
      while(true) {
32221
        std::unique_lock<std::mutex> thread_lock(locking_mutex);
32222
        // We wait for either "run" or "stop_thread" to be called.
32223
        cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
32224
        // If, for some reason, the stop_thread() method was called (i.e., the
32225
        // destructor of stage1_worker is called, then we want to immediately destroy
32226
        // the thread (and not do any more processing).
32227
        if(!can_work) {
32228
          break;
32229
        }
32230
        this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
32231
              this->_next_batch_start);
32232
        this->has_work = false;
32233
        // The condition variable call should be moved after thread_lock.unlock() for performance
32234
        // reasons but thread sanitizers may report it as a data race if we do.
32235
        // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
32236
        cond_var.notify_one(); // will notify "finish"
32237
        thread_lock.unlock();
32238
      }
32239
    }
32240
  );
32241
}
32242
32243
32244
inline void stage1_worker::stop_thread() {
32245
  std::unique_lock<std::mutex> lock(locking_mutex);
32246
  // We have to make sure that all locks can be released.
32247
  can_work = false;
32248
  has_work = false;
32249
  cond_var.notify_all();
32250
  lock.unlock();
32251
  if(thread.joinable()) {
32252
    thread.join();
32253
  }
32254
}
32255
32256
inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) {
32257
  std::unique_lock<std::mutex> lock(locking_mutex);
32258
  owner = ds;
32259
  _next_batch_start = next_batch_start;
32260
  stage1_thread_parser = stage1;
32261
  has_work = true;
32262
  // The condition variable call should be moved after thread_lock.unlock() for performance
32263
  // reasons but thread sanitizers may report it as a data race if we do.
32264
  // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
32265
  cond_var.notify_one(); // will notify the thread lock that we have work
32266
  lock.unlock();
32267
}
32268
32269
#endif  // SIMDJSON_THREADS_ENABLED
32270
32271
simdjson_inline document_stream::document_stream(
32272
  ondemand::parser &_parser,
32273
  const uint8_t *_buf,
32274
  size_t _len,
32275
  size_t _batch_size,
32276
  bool _allow_comma_separated
32277
) noexcept
32278
  : parser{&_parser},
32279
    buf{_buf},
32280
    len{_len},
32281
    batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
32282
    allow_comma_separated{_allow_comma_separated},
32283
    error{SUCCESS}
32284
    #ifdef SIMDJSON_THREADS_ENABLED
32285
    , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
32286
    #endif
32287
{
32288
#ifdef SIMDJSON_THREADS_ENABLED
32289
  if(worker.get() == nullptr) {
32290
    error = MEMALLOC;
32291
  }
32292
#endif
32293
}
32294
32295
simdjson_inline document_stream::document_stream() noexcept
32296
  : parser{nullptr},
32297
    buf{nullptr},
32298
    len{0},
32299
    batch_size{0},
32300
    allow_comma_separated{false},
32301
    error{UNINITIALIZED}
32302
    #ifdef SIMDJSON_THREADS_ENABLED
32303
    , use_thread(false)
32304
    #endif
32305
{
32306
}
32307
32308
simdjson_inline document_stream::~document_stream() noexcept
32309
{
32310
  #ifdef SIMDJSON_THREADS_ENABLED
32311
  worker.reset();
32312
  #endif
32313
}
32314
32315
inline size_t document_stream::size_in_bytes() const noexcept {
32316
  return len;
32317
}
32318
32319
inline size_t document_stream::truncated_bytes() const noexcept {
32320
  if(error == CAPACITY) { return len - batch_start; }
32321
  return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
32322
}
32323
32324
simdjson_inline document_stream::iterator::iterator() noexcept
32325
  : stream{nullptr}, finished{true} {
32326
}
32327
32328
simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
32329
  : stream{_stream}, finished{is_end} {
32330
}
32331
32332
simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
32333
  //if(stream->error) { return stream->error; }
32334
  return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
32335
}
32336
32337
simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
32338
  // If there is an error, then we want the iterator
32339
  // to be finished, no matter what. (E.g., we do not
32340
  // keep generating documents with errors, or go beyond
32341
  // a document with errors.)
32342
  //
32343
  // Users do not have to call "operator*()" when they use operator++,
32344
  // so we need to end the stream in the operator++ function.
32345
  //
32346
  // Note that setting finished = true is essential otherwise
32347
  // we would enter an infinite loop.
32348
  if (stream->error) { finished = true; }
32349
  // Note that stream->error() is guarded against error conditions
32350
  // (it will immediately return if stream->error casts to false).
32351
  // In effect, this next function does nothing when (stream->error)
32352
  // is true (hence the risk of an infinite loop).
32353
  stream->next();
32354
  // If that was the last document, we're finished.
32355
  // It is the only type of error we do not want to appear
32356
  // in operator*.
32357
  if (stream->error == EMPTY) { finished = true; }
32358
  // If we had any other kind of error (not EMPTY) then we want
32359
  // to pass it along to the operator* and we cannot mark the result
32360
  // as "finished" just yet.
32361
  return *this;
32362
}
32363
32364
simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
32365
  return finished != other.finished;
32366
}
32367
32368
simdjson_inline document_stream::iterator document_stream::begin() noexcept {
32369
  start();
32370
  // If there are no documents, we're finished.
32371
  return iterator(this, error == EMPTY);
32372
}
32373
32374
simdjson_inline document_stream::iterator document_stream::end() noexcept {
32375
  return iterator(this, true);
32376
}
32377
32378
inline void document_stream::start() noexcept {
32379
  if (error) { return; }
32380
  error = parser->allocate(batch_size);
32381
  if (error) { return; }
32382
  // Always run the first stage 1 parse immediately
32383
  batch_start = 0;
32384
  error = run_stage1(*parser, batch_start);
32385
  while(error == EMPTY) {
32386
    // In exceptional cases, we may start with an empty block
32387
    batch_start = next_batch_start();
32388
    if (batch_start >= len) { return; }
32389
    error = run_stage1(*parser, batch_start);
32390
  }
32391
  if (error) { return; }
32392
  doc_index = batch_start;
32393
  doc = document(json_iterator(&buf[batch_start], parser));
32394
  doc.iter._streaming = true;
32395
32396
  #ifdef SIMDJSON_THREADS_ENABLED
32397
  if (use_thread && next_batch_start() < len) {
32398
    // Kick off the first thread on next batch if needed
32399
    error = stage1_thread_parser.allocate(batch_size);
32400
    if (error) { return; }
32401
    worker->start_thread();
32402
    start_stage1_thread();
32403
    if (error) { return; }
32404
  }
32405
  #endif // SIMDJSON_THREADS_ENABLED
32406
}
32407
32408
inline void document_stream::next() noexcept {
32409
  // We always enter at once once in an error condition.
32410
  if (error) { return; }
32411
  next_document();
32412
  if (error) { return; }
32413
  auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get();
32414
  doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index];
32415
32416
  // Check if at end of structural indexes (i.e. at end of batch)
32417
  if(cur_struct_index >= static_cast<int64_t>(parser->implementation->n_structural_indexes)) {
32418
    error = EMPTY;
32419
    // Load another batch (if available)
32420
    while (error == EMPTY) {
32421
      batch_start = next_batch_start();
32422
      if (batch_start >= len) { break; }
32423
      #ifdef SIMDJSON_THREADS_ENABLED
32424
      if(use_thread) {
32425
        load_from_stage1_thread();
32426
      } else {
32427
        error = run_stage1(*parser, batch_start);
32428
      }
32429
      #else
32430
      error = run_stage1(*parser, batch_start);
32431
      #endif
32432
      /**
32433
       * Whenever we move to another window, we need to update all pointers to make
32434
       * it appear as if the input buffer started at the beginning of the window.
32435
       *
32436
       * Take this input:
32437
       *
32438
       * {"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]  [15,  11,   12, 13]  [154,  110,   112, 1311]
32439
       *
32440
       * Say you process the following window...
32441
       *
32442
       * '{"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]'
32443
       *
32444
       * When you do so, the json_iterator has a pointer at the beginning of the memory region
32445
       * (pointing at the beginning of '{"z"...'.
32446
       *
32447
       * When you move to the window that starts at...
32448
       *
32449
       * '[7,  10,   9]  [15,  11,   12, 13] ...
32450
       *
32451
       * then it is not sufficient to just run stage 1. You also need to re-anchor the
32452
       * json_iterator so that it believes we are starting at '[7,  10,   9]...'.
32453
       *
32454
       * Under the DOM front-end, this gets done automatically because the parser owns
32455
       * the pointer the data, and when you call stage1 and then stage2 on the same
32456
       * parser, then stage2 will run on the pointer acquired by stage1.
32457
       *
32458
       * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that
32459
       * we used. But json_iterator has no callback when stage1 is called on the parser.
32460
       * In fact, I think that the parser is unaware of json_iterator.
32461
       *
32462
       *
32463
       * So we need to re-anchor the json_iterator after each call to stage 1 so that
32464
       * all of the pointers are in sync.
32465
       */
32466
      doc.iter = json_iterator(&buf[batch_start], parser);
32467
      doc.iter._streaming = true;
32468
      /**
32469
       * End of resync.
32470
       */
32471
32472
      if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
32473
      doc_index = batch_start;
32474
    }
32475
  }
32476
}
32477
32478
inline void document_stream::next_document() noexcept {
32479
  // Go to next place where depth=0 (document depth)
32480
  error = doc.iter.skip_child(0);
32481
  if (error) { return; }
32482
  // Always set depth=1 at the start of document
32483
  doc.iter._depth = 1;
32484
  // consume comma if comma separated is allowed
32485
  if (allow_comma_separated) { doc.iter.consume_character(','); }
32486
  // Resets the string buffer at the beginning, thus invalidating the strings.
32487
  doc.iter._string_buf_loc = parser->string_buf.get();
32488
  doc.iter._root = doc.iter.position();
32489
}
32490
32491
inline size_t document_stream::next_batch_start() const noexcept {
32492
  return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
32493
}
32494
32495
inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept {
32496
  // This code only updates the structural index in the parser, it does not update any json_iterator
32497
  // instance.
32498
  size_t remaining = len - _batch_start;
32499
  if (remaining <= batch_size) {
32500
    return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
32501
  } else {
32502
    return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
32503
  }
32504
}
32505
32506
simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
32507
  return stream->doc_index;
32508
}
32509
32510
simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
32511
  auto depth = stream->doc.iter.depth();
32512
  auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get();
32513
32514
  // If at root, process the first token to determine if scalar value
32515
  if (stream->doc.iter.at_root()) {
32516
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
32517
      case '{': case '[':   // Depth=1 already at start of document
32518
        break;
32519
      case '}': case ']':
32520
        depth--;
32521
        break;
32522
      default:    // Scalar value document
32523
        // TODO: Remove any trailing whitespaces
32524
        // This returns a string spanning from start of value to the beginning of the next document (excluded)
32525
        return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[++cur_struct_index] - current_index() - 1);
32526
    }
32527
    cur_struct_index++;
32528
  }
32529
32530
  while (cur_struct_index <= static_cast<int64_t>(stream->parser->implementation->n_structural_indexes)) {
32531
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
32532
      case '{': case '[':
32533
        depth++;
32534
        break;
32535
      case '}': case ']':
32536
        depth--;
32537
        break;
32538
    }
32539
    if (depth == 0) { break; }
32540
    cur_struct_index++;
32541
  }
32542
32543
  return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);;
32544
}
32545
32546
inline error_code document_stream::iterator::error() const noexcept {
32547
  return stream->error;
32548
}
32549
32550
#ifdef SIMDJSON_THREADS_ENABLED
32551
32552
inline void document_stream::load_from_stage1_thread() noexcept {
32553
  worker->finish();
32554
  // Swap to the parser that was loaded up in the thread. Make sure the parser has
32555
  // enough memory to swap to, as well.
32556
  std::swap(stage1_thread_parser,*parser);
32557
  error = stage1_thread_error;
32558
  if (error) { return; }
32559
32560
  // If there's anything left, start the stage 1 thread!
32561
  if (next_batch_start() < len) {
32562
    start_stage1_thread();
32563
  }
32564
}
32565
32566
inline void document_stream::start_stage1_thread() noexcept {
32567
  // we call the thread on a lambda that will update
32568
  // this->stage1_thread_error
32569
  // there is only one thread that may write to this value
32570
  // TODO this is NOT exception-safe.
32571
  this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
32572
  size_t _next_batch_start = this->next_batch_start();
32573
32574
  worker->run(this, & this->stage1_thread_parser, _next_batch_start);
32575
}
32576
32577
#endif // SIMDJSON_THREADS_ENABLED
32578
32579
} // namespace ondemand
32580
} // namespace arm64
32581
} // namespace simdjson
32582
32583
namespace simdjson {
32584
32585
simdjson_inline simdjson_result<arm64::ondemand::document_stream>::simdjson_result(
32586
  error_code error
32587
) noexcept :
32588
    implementation_simdjson_result_base<arm64::ondemand::document_stream>(error)
32589
{
32590
}
32591
simdjson_inline simdjson_result<arm64::ondemand::document_stream>::simdjson_result(
32592
  arm64::ondemand::document_stream &&value
32593
) noexcept :
32594
    implementation_simdjson_result_base<arm64::ondemand::document_stream>(
32595
      std::forward<arm64::ondemand::document_stream>(value)
32596
    )
32597
{
32598
}
32599
32600
}
32601
32602
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
32603
/* end file simdjson/generic/ondemand/document_stream-inl.h for arm64 */
32604
/* including simdjson/generic/ondemand/field-inl.h for arm64: #include "simdjson/generic/ondemand/field-inl.h" */
32605
/* begin file simdjson/generic/ondemand/field-inl.h for arm64 */
32606
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
32607
32608
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
32609
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */
32610
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
32611
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
32612
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
32613
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
32614
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
32615
32616
namespace simdjson {
32617
namespace arm64 {
32618
namespace ondemand {
32619
32620
// clang 6 does not think the default constructor can be noexcept, so we make it explicit
32621
simdjson_inline field::field() noexcept : std::pair<raw_json_string, ondemand::value>() {}
32622
32623
simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept
32624
  : std::pair<raw_json_string, ondemand::value>(key, std::forward<ondemand::value>(value))
32625
{
32626
}
32627
32628
simdjson_inline simdjson_result<field> field::start(value_iterator &parent_iter) noexcept {
32629
  raw_json_string key;
32630
  SIMDJSON_TRY( parent_iter.field_key().get(key) );
32631
  SIMDJSON_TRY( parent_iter.field_value() );
32632
  return field::start(parent_iter, key);
32633
}
32634
32635
simdjson_inline simdjson_result<field> field::start(const value_iterator &parent_iter, raw_json_string key) noexcept {
32636
    return field(key, parent_iter.child());
32637
}
32638
32639
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> field::unescaped_key(bool allow_replacement) noexcept {
32640
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us.
32641
  simdjson_result<std::string_view> answer = first.unescape(second.iter.json_iter(), allow_replacement);
32642
  first.consume();
32643
  return answer;
32644
}
32645
32646
simdjson_inline raw_json_string field::key() const noexcept {
32647
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
32648
  return first;
32649
}
32650
32651
32652
simdjson_inline std::string_view field::key_raw_json_token() const noexcept {
32653
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
32654
  return std::string_view(reinterpret_cast<const char*>(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1);
32655
}
32656
32657
simdjson_inline value &field::value() & noexcept {
32658
  return second;
32659
}
32660
32661
simdjson_inline value field::value() && noexcept {
32662
  return std::forward<field>(*this).second;
32663
}
32664
32665
} // namespace ondemand
32666
} // namespace arm64
32667
} // namespace simdjson
32668
32669
namespace simdjson {
32670
32671
simdjson_inline simdjson_result<arm64::ondemand::field>::simdjson_result(
32672
  arm64::ondemand::field &&value
32673
) noexcept :
32674
    implementation_simdjson_result_base<arm64::ondemand::field>(
32675
      std::forward<arm64::ondemand::field>(value)
32676
    )
32677
{
32678
}
32679
simdjson_inline simdjson_result<arm64::ondemand::field>::simdjson_result(
32680
  error_code error
32681
) noexcept :
32682
    implementation_simdjson_result_base<arm64::ondemand::field>(error)
32683
{
32684
}
32685
32686
simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> simdjson_result<arm64::ondemand::field>::key() noexcept {
32687
  if (error()) { return error(); }
32688
  return first.key();
32689
}
32690
32691
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::field>::key_raw_json_token() noexcept {
32692
  if (error()) { return error(); }
32693
  return first.key_raw_json_token();
32694
}
32695
32696
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::field>::unescaped_key(bool allow_replacement) noexcept {
32697
  if (error()) { return error(); }
32698
  return first.unescaped_key(allow_replacement);
32699
}
32700
32701
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::field>::value() noexcept {
32702
  if (error()) { return error(); }
32703
  return std::move(first.value());
32704
}
32705
32706
} // namespace simdjson
32707
32708
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
32709
/* end file simdjson/generic/ondemand/field-inl.h for arm64 */
32710
/* including simdjson/generic/ondemand/json_iterator-inl.h for arm64: #include "simdjson/generic/ondemand/json_iterator-inl.h" */
32711
/* begin file simdjson/generic/ondemand/json_iterator-inl.h for arm64 */
32712
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
32713
32714
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
32715
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */
32716
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
32717
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
32718
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
32719
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
32720
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
32721
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */
32722
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */
32723
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */
32724
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
32725
32726
namespace simdjson {
32727
namespace arm64 {
32728
namespace ondemand {
32729
32730
simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
32731
  : token(std::forward<token_iterator>(other.token)),
32732
    parser{other.parser},
32733
    _string_buf_loc{other._string_buf_loc},
32734
    error{other.error},
32735
    _depth{other._depth},
32736
    _root{other._root},
32737
    _streaming{other._streaming}
32738
{
32739
  other.parser = nullptr;
32740
}
32741
simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept {
32742
  token = other.token;
32743
  parser = other.parser;
32744
  _string_buf_loc = other._string_buf_loc;
32745
  error = other.error;
32746
  _depth = other._depth;
32747
  _root = other._root;
32748
  _streaming = other._streaming;
32749
  other.parser = nullptr;
32750
  return *this;
32751
}
32752
32753
simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept
32754
  : token(buf, &_parser->implementation->structural_indexes[0]),
32755
    parser{_parser},
32756
    _string_buf_loc{parser->string_buf.get()},
32757
    _depth{1},
32758
    _root{parser->implementation->structural_indexes.get()},
32759
    _streaming{false}
32760
32761
{
32762
  logger::log_headers();
32763
#if SIMDJSON_CHECK_EOF
32764
  assert_more_tokens();
32765
#endif
32766
}
32767
32768
inline void json_iterator::rewind() noexcept {
32769
  token.set_position( root_position() );
32770
  logger::log_headers(); // We start again
32771
  _string_buf_loc = parser->string_buf.get();
32772
  _depth = 1;
32773
}
32774
32775
inline bool json_iterator::balanced() const noexcept {
32776
  token_iterator ti(token);
32777
  int32_t count{0};
32778
  ti.set_position( root_position() );
32779
  while(ti.peek() <= peek_last()) {
32780
    switch (*ti.return_current_and_advance())
32781
    {
32782
    case '[': case '{':
32783
      count++;
32784
      break;
32785
    case ']': case '}':
32786
      count--;
32787
      break;
32788
    default:
32789
      break;
32790
    }
32791
  }
32792
  return count == 0;
32793
}
32794
32795
32796
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
32797
// relating depth and parent_depth, which is a desired effect. The warning does not show up if the
32798
// skip_child() function is not marked inline).
32799
SIMDJSON_PUSH_DISABLE_WARNINGS
32800
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
32801
simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
32802
  if (depth() <= parent_depth) { return SUCCESS; }
32803
  switch (*return_current_and_advance()) {
32804
    // TODO consider whether matching braces is a requirement: if non-matching braces indicates
32805
    // *missing* braces, then future lookups are not in the object/arrays they think they are,
32806
    // violating the rule "validate enough structure that the user can be confident they are
32807
    // looking at the right values."
32808
    // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
32809
32810
    // For the first open array/object in a value, we've already incremented depth, so keep it the same
32811
    // We never stop at colon, but if we did, it wouldn't affect depth
32812
    case '[': case '{': case ':':
32813
      logger::log_start_value(*this, "skip");
32814
      break;
32815
    // If there is a comma, we have just finished a value in an array/object, and need to get back in
32816
    case ',':
32817
      logger::log_value(*this, "skip");
32818
      break;
32819
    // ] or } means we just finished a value and need to jump out of the array/object
32820
    case ']': case '}':
32821
      logger::log_end_value(*this, "skip");
32822
      _depth--;
32823
      if (depth() <= parent_depth) { return SUCCESS; }
32824
#if SIMDJSON_CHECK_EOF
32825
      // If there are no more tokens, the parent is incomplete.
32826
      if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
32827
#endif // SIMDJSON_CHECK_EOF
32828
      break;
32829
    case '"':
32830
      if(*peek() == ':') {
32831
        // We are at a key!!!
32832
        // This might happen if you just started an object and you skip it immediately.
32833
        // Performance note: it would be nice to get rid of this check as it is somewhat
32834
        // expensive.
32835
        // https://github.com/simdjson/simdjson/issues/1742
32836
        logger::log_value(*this, "key");
32837
        return_current_and_advance(); // eat up the ':'
32838
        break; // important!!!
32839
      }
32840
      simdjson_fallthrough;
32841
    // Anything else must be a scalar value
32842
    default:
32843
      // For the first scalar, we will have incremented depth already, so we decrement it here.
32844
      logger::log_value(*this, "skip");
32845
      _depth--;
32846
      if (depth() <= parent_depth) { return SUCCESS; }
32847
      break;
32848
  }
32849
32850
  // Now that we've considered the first value, we only increment/decrement for arrays/objects
32851
  while (position() < end_position()) {
32852
    switch (*return_current_and_advance()) {
32853
      case '[': case '{':
32854
        logger::log_start_value(*this, "skip");
32855
        _depth++;
32856
        break;
32857
      // TODO consider whether matching braces is a requirement: if non-matching braces indicates
32858
      // *missing* braces, then future lookups are not in the object/arrays they think they are,
32859
      // violating the rule "validate enough structure that the user can be confident they are
32860
      // looking at the right values."
32861
      // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
32862
      case ']': case '}':
32863
        logger::log_end_value(*this, "skip");
32864
        _depth--;
32865
        if (depth() <= parent_depth) { return SUCCESS; }
32866
        break;
32867
      default:
32868
        logger::log_value(*this, "skip", "");
32869
        break;
32870
    }
32871
  }
32872
32873
  return report_error(TAPE_ERROR, "not enough close braces");
32874
}
32875
32876
SIMDJSON_POP_DISABLE_WARNINGS
32877
32878
simdjson_inline bool json_iterator::at_root() const noexcept {
32879
  return position() == root_position();
32880
}
32881
32882
simdjson_inline bool json_iterator::is_single_token() const noexcept {
32883
  return parser->implementation->n_structural_indexes == 1;
32884
}
32885
32886
simdjson_inline bool json_iterator::streaming() const noexcept {
32887
  return _streaming;
32888
}
32889
32890
simdjson_inline token_position json_iterator::root_position() const noexcept {
32891
  return _root;
32892
}
32893
32894
simdjson_inline void json_iterator::assert_at_document_depth() const noexcept {
32895
  SIMDJSON_ASSUME( _depth == 1 );
32896
}
32897
32898
simdjson_inline void json_iterator::assert_at_root() const noexcept {
32899
  SIMDJSON_ASSUME( _depth == 1 );
32900
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
32901
  // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument
32902
  // has side effects that will be discarded.
32903
  SIMDJSON_ASSUME( token.position() == _root );
32904
#endif
32905
}
32906
32907
simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
32908
  assert_valid_position(token._position + required_tokens - 1);
32909
}
32910
32911
simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
32912
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
32913
  SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
32914
  SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
32915
#endif
32916
}
32917
32918
simdjson_inline bool json_iterator::at_end() const noexcept {
32919
  return position() == end_position();
32920
}
32921
simdjson_inline token_position json_iterator::end_position() const noexcept {
32922
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
32923
  return &parser->implementation->structural_indexes[n_structural_indexes];
32924
}
32925
32926
inline std::string json_iterator::to_string() const noexcept {
32927
  if( !is_alive() ) { return "dead json_iterator instance"; }
32928
  const char * current_structural = reinterpret_cast<const char *>(token.peek());
32929
  return std::string("json_iterator [ depth : ") + std::to_string(_depth)
32930
          + std::string(", structural : '") + std::string(current_structural,1)
32931
          + std::string("', offset : ") + std::to_string(token.current_offset())
32932
          + std::string("', error : ") + error_message(error)
32933
          + std::string(" ]");
32934
}
32935
32936
inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
32937
  if (!is_alive()) {    // Unrecoverable error
32938
    if (!at_root()) {
32939
      return reinterpret_cast<const char *>(token.peek(-1));
32940
    } else {
32941
      return reinterpret_cast<const char *>(token.peek());
32942
    }
32943
  }
32944
  if (at_end()) {
32945
    return OUT_OF_BOUNDS;
32946
  }
32947
  return reinterpret_cast<const char *>(token.peek());
32948
}
32949
32950
simdjson_inline bool json_iterator::is_alive() const noexcept {
32951
  return parser;
32952
}
32953
32954
simdjson_inline void json_iterator::abandon() noexcept {
32955
  parser = nullptr;
32956
  _depth = 0;
32957
}
32958
32959
simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
32960
#if SIMDJSON_CHECK_EOF
32961
  assert_more_tokens();
32962
#endif // SIMDJSON_CHECK_EOF
32963
  return token.return_current_and_advance();
32964
}
32965
32966
simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
32967
  // deliberately done without safety guard:
32968
  return token.peek();
32969
}
32970
32971
simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
32972
#if SIMDJSON_CHECK_EOF
32973
  assert_more_tokens(delta+1);
32974
#endif // SIMDJSON_CHECK_EOF
32975
  return token.peek(delta);
32976
}
32977
32978
simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
32979
#if SIMDJSON_CHECK_EOF
32980
  assert_more_tokens(delta+1);
32981
#endif // #if SIMDJSON_CHECK_EOF
32982
  return token.peek_length(delta);
32983
}
32984
32985
simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
32986
  // todo: currently we require end-of-string buffering, but the following
32987
  // assert_valid_position should be turned on if/when we lift that condition.
32988
  // assert_valid_position(position);
32989
  // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
32990
  // is ON by default, we have no choice but to disable it for real with a comment.
32991
  return token.peek(position);
32992
}
32993
32994
simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
32995
#if SIMDJSON_CHECK_EOF
32996
  assert_valid_position(position);
32997
#endif // SIMDJSON_CHECK_EOF
32998
  return token.peek_length(position);
32999
}
33000
simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept {
33001
#if SIMDJSON_CHECK_EOF
33002
  assert_valid_position(position);
33003
#endif // SIMDJSON_CHECK_EOF
33004
  return token.peek_root_length(position);
33005
}
33006
33007
simdjson_inline token_position json_iterator::last_position() const noexcept {
33008
  // The following line fails under some compilers...
33009
  // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0);
33010
  // since it has side-effects.
33011
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
33012
  SIMDJSON_ASSUME(n_structural_indexes > 0);
33013
  return &parser->implementation->structural_indexes[n_structural_indexes - 1];
33014
}
33015
simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept {
33016
  return token.peek(last_position());
33017
}
33018
33019
simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
33020
  SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
33021
  SIMDJSON_ASSUME(_depth == parent_depth + 1);
33022
  _depth = parent_depth;
33023
}
33024
33025
simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
33026
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
33027
  SIMDJSON_ASSUME(_depth == child_depth - 1);
33028
  _depth = child_depth;
33029
}
33030
33031
simdjson_inline depth_t json_iterator::depth() const noexcept {
33032
  return _depth;
33033
}
33034
33035
simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
33036
  return _string_buf_loc;
33037
}
33038
33039
simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept {
33040
  SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD);
33041
  logger::log_error(*this, message);
33042
  error = _error;
33043
  return error;
33044
}
33045
33046
simdjson_inline token_position json_iterator::position() const noexcept {
33047
  return token.position();
33048
}
33049
33050
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept {
33051
  return parser->unescape(in, _string_buf_loc, allow_replacement);
33052
}
33053
33054
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in) noexcept {
33055
  return parser->unescape_wobbly(in, _string_buf_loc);
33056
}
33057
33058
simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
33059
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
33060
  SIMDJSON_ASSUME(_depth == child_depth - 1);
33061
#if SIMDJSON_DEVELOPMENT_CHECKS
33062
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
33063
  SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
33064
  SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
33065
#endif
33066
#endif
33067
  token.set_position(position);
33068
  _depth = child_depth;
33069
}
33070
33071
simdjson_inline error_code json_iterator::consume_character(char c) noexcept {
33072
  if (*peek() == c) {
33073
    return_current_and_advance();
33074
    return SUCCESS;
33075
  }
33076
  return TAPE_ERROR;
33077
}
33078
33079
#if SIMDJSON_DEVELOPMENT_CHECKS
33080
33081
simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
33082
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
33083
  return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
33084
}
33085
33086
simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
33087
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
33088
  if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
33089
}
33090
33091
#endif
33092
33093
33094
simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept {
33095
  SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD);
33096
  logger::log_error(*this, message);
33097
  return _error;
33098
}
33099
33100
33101
simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept {
33102
  // This function is not expected to be called in performance-sensitive settings.
33103
  // Let us guard against silly cases:
33104
  if((N < max_len) || (N == 0)) { return false; }
33105
  // Copy to the buffer.
33106
  std::memcpy(tmpbuf, json, max_len);
33107
  if(N > max_len) { // We pad whatever remains with ' '.
33108
    std::memset(tmpbuf + max_len, ' ', N - max_len);
33109
  }
33110
  return true;
33111
}
33112
33113
} // namespace ondemand
33114
} // namespace arm64
33115
} // namespace simdjson
33116
33117
namespace simdjson {
33118
33119
simdjson_inline simdjson_result<arm64::ondemand::json_iterator>::simdjson_result(arm64::ondemand::json_iterator &&value) noexcept
33120
    : implementation_simdjson_result_base<arm64::ondemand::json_iterator>(std::forward<arm64::ondemand::json_iterator>(value)) {}
33121
simdjson_inline simdjson_result<arm64::ondemand::json_iterator>::simdjson_result(error_code error) noexcept
33122
    : implementation_simdjson_result_base<arm64::ondemand::json_iterator>(error) {}
33123
33124
} // namespace simdjson
33125
33126
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
33127
/* end file simdjson/generic/ondemand/json_iterator-inl.h for arm64 */
33128
/* including simdjson/generic/ondemand/json_type-inl.h for arm64: #include "simdjson/generic/ondemand/json_type-inl.h" */
33129
/* begin file simdjson/generic/ondemand/json_type-inl.h for arm64 */
33130
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
33131
33132
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
33133
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */
33134
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
33135
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
33136
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
33137
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
33138
33139
namespace simdjson {
33140
namespace arm64 {
33141
namespace ondemand {
33142
33143
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
33144
    switch (type) {
33145
        case json_type::array: out << "array"; break;
33146
        case json_type::object: out << "object"; break;
33147
        case json_type::number: out << "number"; break;
33148
        case json_type::string: out << "string"; break;
33149
        case json_type::boolean: out << "boolean"; break;
33150
        case json_type::null: out << "null"; break;
33151
        default: SIMDJSON_UNREACHABLE();
33152
    }
33153
    return out;
33154
}
33155
33156
#if SIMDJSON_EXCEPTIONS
33157
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
33158
    return out << type.value();
33159
}
33160
#endif
33161
33162
33163
33164
simdjson_inline number_type number::get_number_type() const noexcept {
33165
  return type;
33166
}
33167
33168
simdjson_inline bool number::is_uint64() const noexcept {
33169
  return get_number_type() == number_type::unsigned_integer;
33170
}
33171
33172
simdjson_inline uint64_t number::get_uint64() const noexcept {
33173
  return payload.unsigned_integer;
33174
}
33175
33176
simdjson_inline number::operator uint64_t() const noexcept {
33177
  return get_uint64();
33178
}
33179
33180
simdjson_inline bool number::is_int64() const noexcept {
33181
  return get_number_type() == number_type::signed_integer;
33182
}
33183
33184
simdjson_inline int64_t number::get_int64() const noexcept {
33185
  return payload.signed_integer;
33186
}
33187
33188
simdjson_inline number::operator int64_t() const noexcept {
33189
  return get_int64();
33190
}
33191
33192
simdjson_inline bool number::is_double() const noexcept {
33193
    return get_number_type() == number_type::floating_point_number;
33194
}
33195
33196
simdjson_inline double number::get_double() const noexcept {
33197
  return payload.floating_point_number;
33198
}
33199
33200
simdjson_inline number::operator double() const noexcept {
33201
  return get_double();
33202
}
33203
33204
simdjson_inline double number::as_double() const noexcept {
33205
  if(is_double()) {
33206
    return payload.floating_point_number;
33207
  }
33208
  if(is_int64()) {
33209
    return double(payload.signed_integer);
33210
  }
33211
  return double(payload.unsigned_integer);
33212
}
33213
33214
simdjson_inline void number::append_s64(int64_t value) noexcept {
33215
  payload.signed_integer = value;
33216
  type = number_type::signed_integer;
33217
}
33218
33219
simdjson_inline void number::append_u64(uint64_t value) noexcept {
33220
  payload.unsigned_integer = value;
33221
  type = number_type::unsigned_integer;
33222
}
33223
33224
simdjson_inline void number::append_double(double value) noexcept {
33225
  payload.floating_point_number = value;
33226
  type = number_type::floating_point_number;
33227
}
33228
33229
simdjson_inline void number::skip_double() noexcept {
33230
  type = number_type::floating_point_number;
33231
}
33232
33233
} // namespace ondemand
33234
} // namespace arm64
33235
} // namespace simdjson
33236
33237
namespace simdjson {
33238
33239
simdjson_inline simdjson_result<arm64::ondemand::json_type>::simdjson_result(arm64::ondemand::json_type &&value) noexcept
33240
    : implementation_simdjson_result_base<arm64::ondemand::json_type>(std::forward<arm64::ondemand::json_type>(value)) {}
33241
simdjson_inline simdjson_result<arm64::ondemand::json_type>::simdjson_result(error_code error) noexcept
33242
    : implementation_simdjson_result_base<arm64::ondemand::json_type>(error) {}
33243
33244
} // namespace simdjson
33245
33246
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
33247
/* end file simdjson/generic/ondemand/json_type-inl.h for arm64 */
33248
/* including simdjson/generic/ondemand/logger-inl.h for arm64: #include "simdjson/generic/ondemand/logger-inl.h" */
33249
/* begin file simdjson/generic/ondemand/logger-inl.h for arm64 */
33250
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
33251
33252
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
33253
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */
33254
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
33255
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
33256
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
33257
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
33258
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
33259
33260
#include <memory>
33261
#include <cstring>
33262
33263
namespace simdjson {
33264
namespace arm64 {
33265
namespace ondemand {
33266
namespace logger {
33267
33268
static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
33269
static constexpr const int LOG_EVENT_LEN = 20;
33270
static constexpr const int LOG_BUFFER_LEN = 30;
33271
static constexpr const int LOG_SMALL_BUFFER_LEN = 10;
33272
static int log_depth = 0; // Not threadsafe. Log only.
33273
33274
// Helper to turn unprintable or newline characters into spaces
33275
static inline char printable_char(char c) {
33276
  if (c >= 0x20) {
33277
    return c;
33278
  } else {
33279
    return ' ';
33280
  }
33281
}
33282
33283
template<typename... Args>
33284
static inline std::string string_format(const std::string& format, const Args&... args)
33285
{
33286
  SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
33287
  int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
33288
  auto size = static_cast<size_t>(size_s);
33289
  if (size <= 0) return std::string();
33290
  std::unique_ptr<char[]> buf(new char[size]);
33291
  std::snprintf(buf.get(), size, format.c_str(), args...);
33292
  SIMDJSON_POP_DISABLE_WARNINGS
33293
  return std::string(buf.get(), buf.get() + size - 1);
33294
}
33295
33296
static inline log_level get_log_level_from_env()
33297
{
33298
  SIMDJSON_PUSH_DISABLE_WARNINGS
33299
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
33300
      char *lvl = getenv("SIMDJSON_LOG_LEVEL");
33301
  SIMDJSON_POP_DISABLE_WARNINGS
33302
  if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; }
33303
  return log_level::info;
33304
}
33305
33306
static inline log_level log_threshold()
33307
{
33308
  static log_level threshold = get_log_level_from_env();
33309
  return threshold;
33310
}
33311
33312
static inline bool should_log(log_level level)
33313
{
33314
  return level >= log_threshold();
33315
}
33316
33317
inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
33318
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
33319
}
33320
33321
inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
33322
  log_line(iter, index, depth, "", type, detail, log_level::info);
33323
}
33324
inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
33325
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
33326
}
33327
33328
inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
33329
  log_line(iter, index, depth, "+", type, detail, log_level::info);
33330
  if (LOG_ENABLED) { log_depth++; }
33331
}
33332
inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
33333
  log_line(iter, "+", type, "", delta, depth_delta, log_level::info);
33334
  if (LOG_ENABLED) { log_depth++; }
33335
}
33336
33337
inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
33338
  if (LOG_ENABLED) { log_depth--; }
33339
  log_line(iter, "-", type, "", delta, depth_delta, log_level::info);
33340
}
33341
33342
inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
33343
  log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error);
33344
}
33345
inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept {
33346
  log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error);
33347
}
33348
33349
inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
33350
  log_event(iter.json_iter(), type, detail, delta, depth_delta);
33351
}
33352
33353
inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
33354
  log_value(iter.json_iter(), type, detail, delta, depth_delta);
33355
}
33356
33357
inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
33358
  log_start_value(iter.json_iter(), type, delta, depth_delta);
33359
}
33360
33361
inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
33362
  log_end_value(iter.json_iter(), type, delta, depth_delta);
33363
}
33364
33365
inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
33366
  log_error(iter.json_iter(), error, detail, delta, depth_delta);
33367
}
33368
33369
inline void log_headers() noexcept {
33370
  if (LOG_ENABLED) {
33371
    if (simdjson_unlikely(should_log(log_level::info))) {
33372
      // Technically a static variable is not thread-safe, but if you are using threads and logging... well...
33373
      static bool displayed_hint{false};
33374
      log_depth = 0;
33375
      printf("\n");
33376
      if (!displayed_hint) {
33377
        // We only print this helpful header once.
33378
        printf("# Logging provides the depth and position of the iterator user-visible steps:\n");
33379
        printf("# +array says 'this is where we were when we discovered the start array'\n");
33380
        printf(
33381
            "# -array says 'this is where we were when we ended the array'\n");
33382
        printf("# skip says 'this is a structural or value I am skipping'\n");
33383
        printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
33384
        printf("#\n");
33385
        printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
33386
        printf("# in addition to the depth being displayed.\n");
33387
        printf("#\n");
33388
        printf("# Every token in the document has a single depth determined by the tokens before it,\n");
33389
        printf("# and is not affected by what the token actually is.\n");
33390
        printf("#\n");
33391
        printf("# Not all structural elements are presented as tokens in the logs.\n");
33392
        printf("#\n");
33393
        printf("# We never give control to the user within an empty array or an empty object.\n");
33394
        printf("#\n");
33395
        printf("# Inside an array, having a depth greater than the array's depth means that\n");
33396
        printf("# we are pointing inside a value.\n");
33397
        printf("# Having a depth equal to the array means that we are pointing right before a value.\n");
33398
        printf("# Having a depth smaller than the array means that we have moved beyond the array.\n");
33399
        displayed_hint = true;
33400
      }
33401
      printf("\n");
33402
      printf("| %-*s ", LOG_EVENT_LEN, "Event");
33403
      printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
33404
      printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next");
33405
      // printf("| %-*s ", 5,                    "Next#");
33406
      printf("| %-*s ", 5, "Depth");
33407
      printf("| Detail ");
33408
      printf("|\n");
33409
33410
      printf("|%.*s", LOG_EVENT_LEN + 2, DASHES);
33411
      printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES);
33412
      printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
33413
      // printf("|%.*s", 5+2, DASHES);
33414
      printf("|%.*s", 5 + 2, DASHES);
33415
      printf("|--------");
33416
      printf("|\n");
33417
      fflush(stdout);
33418
    }
33419
  }
33420
}
33421
33422
template <typename... Args>
33423
inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept {
33424
  log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
33425
}
33426
33427
template <typename... Args>
33428
inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
33429
  if (LOG_ENABLED) {
33430
    if (simdjson_unlikely(should_log(level))) {
33431
      const int indent = depth * 2;
33432
      const auto buf = iter.token.buf;
33433
      auto msg = string_format(title, std::forward<Args>(args)...);
33434
      printf("| %*s%s%-*s ", indent, "", title_prefix,
33435
             LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str());
33436
      {
33437
        // Print the current structural.
33438
        printf("| ");
33439
        // Before we begin, the index might point right before the document.
33440
        // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
33441
        if (index < iter._root) {
33442
          printf("%*s", LOG_BUFFER_LEN, "");
33443
        } else {
33444
          auto current_structural = &buf[*index];
33445
          for (int i = 0; i < LOG_BUFFER_LEN; i++) {
33446
            printf("%c", printable_char(current_structural[i]));
33447
          }
33448
        }
33449
        printf(" ");
33450
      }
33451
      {
33452
        // Print the next structural.
33453
        printf("| ");
33454
        auto next_structural = &buf[*(index + 1)];
33455
        for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
33456
          printf("%c", printable_char(next_structural[i]));
33457
        }
33458
        printf(" ");
33459
      }
33460
      // printf("| %5u ", *(index+1));
33461
      printf("| %5i ", depth);
33462
      printf("| %6.*s ", int(detail.size()), detail.data());
33463
      printf("|\n");
33464
      fflush(stdout);
33465
    }
33466
  }
33467
}
33468
33469
} // namespace logger
33470
} // namespace ondemand
33471
} // namespace arm64
33472
} // namespace simdjson
33473
33474
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
33475
/* end file simdjson/generic/ondemand/logger-inl.h for arm64 */
33476
/* including simdjson/generic/ondemand/object-inl.h for arm64: #include "simdjson/generic/ondemand/object-inl.h" */
33477
/* begin file simdjson/generic/ondemand/object-inl.h for arm64 */
33478
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
33479
33480
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
33481
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */
33482
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
33483
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
33484
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
33485
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
33486
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
33487
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
33488
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
33489
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
33490
33491
namespace simdjson {
33492
namespace arm64 {
33493
namespace ondemand {
33494
33495
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
33496
  bool has_value;
33497
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
33498
  if (!has_value) {
33499
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
33500
    return NO_SUCH_FIELD;
33501
  }
33502
  return value(iter.child());
33503
}
33504
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
33505
  bool has_value;
33506
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
33507
  if (!has_value) {
33508
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
33509
    return NO_SUCH_FIELD;
33510
  }
33511
  return value(iter.child());
33512
}
33513
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
33514
  return find_field_unordered(key);
33515
}
33516
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
33517
  return std::forward<object>(*this).find_field_unordered(key);
33518
}
33519
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
33520
  bool has_value;
33521
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
33522
  if (!has_value) {
33523
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
33524
    return NO_SUCH_FIELD;
33525
  }
33526
  return value(iter.child());
33527
}
33528
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
33529
  bool has_value;
33530
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
33531
  if (!has_value) {
33532
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
33533
    return NO_SUCH_FIELD;
33534
  }
33535
  return value(iter.child());
33536
}
33537
33538
simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
33539
  SIMDJSON_TRY( iter.start_object().error() );
33540
  return object(iter);
33541
}
33542
simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
33543
  SIMDJSON_TRY( iter.start_root_object().error() );
33544
  return object(iter);
33545
}
33546
simdjson_inline error_code object::consume() noexcept {
33547
  if(iter.is_at_key()) {
33548
    /**
33549
     * whenever you are pointing at a key, calling skip_child() is
33550
     * unsafe because you will hit a string and you will assume that
33551
     * it is string value, and this mistake will lead you to make bad
33552
     * depth computation.
33553
     */
33554
    /**
33555
     * We want to 'consume' the key. We could really
33556
     * just do _json_iter->return_current_and_advance(); at this
33557
     * point, but, for clarity, we will use the high-level API to
33558
     * eat the key. We assume that the compiler optimizes away
33559
     * most of the work.
33560
     */
33561
    simdjson_unused raw_json_string actual_key;
33562
    auto error = iter.field_key().get(actual_key);
33563
    if (error) { iter.abandon(); return error; };
33564
    // Let us move to the value while we are at it.
33565
    if ((error = iter.field_value())) { iter.abandon(); return error; }
33566
  }
33567
  auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
33568
  if(error_skip) { iter.abandon(); }
33569
  return error_skip;
33570
}
33571
33572
simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
33573
  const uint8_t * starting_point{iter.peek_start()};
33574
  auto error = consume();
33575
  if(error) { return error; }
33576
  const uint8_t * final_point{iter._json_iter->peek()};
33577
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
33578
}
33579
33580
simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
33581
  SIMDJSON_TRY( iter.started_object().error() );
33582
  return object(iter);
33583
}
33584
33585
simdjson_inline object object::resume(const value_iterator &iter) noexcept {
33586
  return iter;
33587
}
33588
33589
simdjson_inline object::object(const value_iterator &_iter) noexcept
33590
  : iter{_iter}
33591
{
33592
}
33593
33594
simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
33595
#if SIMDJSON_DEVELOPMENT_CHECKS
33596
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
33597
#endif
33598
  return object_iterator(iter);
33599
}
33600
simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
33601
  return object_iterator(iter);
33602
}
33603
33604
inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
33605
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
33606
  json_pointer = json_pointer.substr(1);
33607
  size_t slash = json_pointer.find('/');
33608
  std::string_view key = json_pointer.substr(0, slash);
33609
  // Grab the child with the given key
33610
  simdjson_result<value> child;
33611
33612
  // If there is an escape character in the key, unescape it and then get the child.
33613
  size_t escape = key.find('~');
33614
  if (escape != std::string_view::npos) {
33615
    // Unescape the key
33616
    std::string unescaped(key);
33617
    do {
33618
      switch (unescaped[escape+1]) {
33619
        case '0':
33620
          unescaped.replace(escape, 2, "~");
33621
          break;
33622
        case '1':
33623
          unescaped.replace(escape, 2, "/");
33624
          break;
33625
        default:
33626
          return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
33627
      }
33628
      escape = unescaped.find('~', escape+1);
33629
    } while (escape != std::string::npos);
33630
    child = find_field(unescaped);  // Take note find_field does not unescape keys when matching
33631
  } else {
33632
    child = find_field(key);
33633
  }
33634
  if(child.error()) {
33635
    return child; // we do not continue if there was an error
33636
  }
33637
  // If there is a /, we have to recurse and look up more of the path
33638
  if (slash != std::string_view::npos) {
33639
    child = child.at_pointer(json_pointer.substr(slash));
33640
  }
33641
  return child;
33642
}
33643
33644
inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
33645
  auto json_pointer = json_path_to_pointer_conversion(json_path);
33646
  if (json_pointer == "-1") {
33647
    return INVALID_JSON_POINTER;
33648
  }
33649
  return at_pointer(json_pointer);
33650
}
33651
33652
simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
33653
  size_t count{0};
33654
  // Important: we do not consume any of the values.
33655
  for(simdjson_unused auto v : *this) { count++; }
33656
  // The above loop will always succeed, but we want to report errors.
33657
  if(iter.error()) { return iter.error(); }
33658
  // We need to move back at the start because we expect users to iterate through
33659
  // the object after counting the number of elements.
33660
  iter.reset_object();
33661
  return count;
33662
}
33663
33664
simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
33665
  bool is_not_empty;
33666
  auto error = iter.reset_object().get(is_not_empty);
33667
  if(error) { return error; }
33668
  return !is_not_empty;
33669
}
33670
33671
simdjson_inline simdjson_result<bool> object::reset() & noexcept {
33672
  return iter.reset_object();
33673
}
33674
33675
} // namespace ondemand
33676
} // namespace arm64
33677
} // namespace simdjson
33678
33679
namespace simdjson {
33680
33681
simdjson_inline simdjson_result<arm64::ondemand::object>::simdjson_result(arm64::ondemand::object &&value) noexcept
33682
    : implementation_simdjson_result_base<arm64::ondemand::object>(std::forward<arm64::ondemand::object>(value)) {}
33683
simdjson_inline simdjson_result<arm64::ondemand::object>::simdjson_result(error_code error) noexcept
33684
    : implementation_simdjson_result_base<arm64::ondemand::object>(error) {}
33685
33686
simdjson_inline simdjson_result<arm64::ondemand::object_iterator> simdjson_result<arm64::ondemand::object>::begin() noexcept {
33687
  if (error()) { return error(); }
33688
  return first.begin();
33689
}
33690
simdjson_inline simdjson_result<arm64::ondemand::object_iterator> simdjson_result<arm64::ondemand::object>::end() noexcept {
33691
  if (error()) { return error(); }
33692
  return first.end();
33693
}
33694
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
33695
  if (error()) { return error(); }
33696
  return first.find_field_unordered(key);
33697
}
33698
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
33699
  if (error()) { return error(); }
33700
  return std::forward<arm64::ondemand::object>(first).find_field_unordered(key);
33701
}
33702
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::operator[](std::string_view key) & noexcept {
33703
  if (error()) { return error(); }
33704
  return first[key];
33705
}
33706
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::operator[](std::string_view key) && noexcept {
33707
  if (error()) { return error(); }
33708
  return std::forward<arm64::ondemand::object>(first)[key];
33709
}
33710
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::find_field(std::string_view key) & noexcept {
33711
  if (error()) { return error(); }
33712
  return first.find_field(key);
33713
}
33714
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::find_field(std::string_view key) && noexcept {
33715
  if (error()) { return error(); }
33716
  return std::forward<arm64::ondemand::object>(first).find_field(key);
33717
}
33718
33719
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
33720
  if (error()) { return error(); }
33721
  return first.at_pointer(json_pointer);
33722
}
33723
33724
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::object>::at_path(
33725
    std::string_view json_path) noexcept {
33726
  if (error()) {
33727
    return error();
33728
  }
33729
  return first.at_path(json_path);
33730
}
33731
33732
inline simdjson_result<bool> simdjson_result<arm64::ondemand::object>::reset() noexcept {
33733
  if (error()) { return error(); }
33734
  return first.reset();
33735
}
33736
33737
inline simdjson_result<bool> simdjson_result<arm64::ondemand::object>::is_empty() noexcept {
33738
  if (error()) { return error(); }
33739
  return first.is_empty();
33740
}
33741
33742
simdjson_inline  simdjson_result<size_t> simdjson_result<arm64::ondemand::object>::count_fields() & noexcept {
33743
  if (error()) { return error(); }
33744
  return first.count_fields();
33745
}
33746
33747
simdjson_inline  simdjson_result<std::string_view> simdjson_result<arm64::ondemand::object>::raw_json() noexcept {
33748
  if (error()) { return error(); }
33749
  return first.raw_json();
33750
}
33751
} // namespace simdjson
33752
33753
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
33754
/* end file simdjson/generic/ondemand/object-inl.h for arm64 */
33755
/* including simdjson/generic/ondemand/object_iterator-inl.h for arm64: #include "simdjson/generic/ondemand/object_iterator-inl.h" */
33756
/* begin file simdjson/generic/ondemand/object_iterator-inl.h for arm64 */
33757
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
33758
33759
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
33760
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */
33761
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
33762
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
33763
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */
33764
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
33765
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
33766
33767
namespace simdjson {
33768
namespace arm64 {
33769
namespace ondemand {
33770
33771
//
33772
// object_iterator
33773
//
33774
33775
simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
33776
  : iter{_iter}
33777
{}
33778
33779
simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
33780
  error_code error = iter.error();
33781
  if (error) { iter.abandon(); return error; }
33782
  auto result = field::start(iter);
33783
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
33784
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
33785
  if (result.error()) { iter.abandon(); }
33786
  return result;
33787
}
33788
simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
33789
  return !(*this != other);
33790
}
33791
simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
33792
  return iter.is_open();
33793
}
33794
33795
SIMDJSON_PUSH_DISABLE_WARNINGS
33796
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
33797
simdjson_inline object_iterator &object_iterator::operator++() noexcept {
33798
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
33799
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
33800
  if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
33801
33802
  simdjson_unused error_code error;
33803
  if ((error = iter.skip_child() )) { return *this; }
33804
33805
  simdjson_unused bool has_value;
33806
  if ((error = iter.has_next_field().get(has_value) )) { return *this; };
33807
  return *this;
33808
}
33809
SIMDJSON_POP_DISABLE_WARNINGS
33810
33811
//
33812
// ### Live States
33813
//
33814
// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
33815
// always SUCCESS:
33816
//
33817
// - Start: This is the state when the object is first found and the iterator is just past the {.
33818
//   In this state, at_start == true.
33819
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
33820
//   iterate over, the iterator is at the , or } before the next value. In this state,
33821
//   depth == iter.depth, at_start == false, and error == SUCCESS.
33822
// - Unfinished Business: When we hand an array/object to the user which they do not fully
33823
//   iterate over, we need to finish that iteration by skipping child values until we reach the
33824
//   Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
33825
//
33826
// ## Error States
33827
//
33828
// In error states, we will yield exactly one more value before stopping. iter.depth == depth
33829
// and at_start is always false. We decrement after yielding the error, moving to the Finished
33830
// state.
33831
//
33832
// - Chained Error: When the object iterator is part of an error chain--for example, in
33833
//   `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
33834
//   object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
33835
//   iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
33836
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
33837
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
33838
//   error == TAPE_ERROR, iter.depth == depth, and at_start == false.
33839
//
33840
// Errors that occur while reading a field to give to the user (such as when the key is not a
33841
// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
33842
// moving to the Finished state without transitioning through an Error state at all.
33843
//
33844
// ## Terminal State
33845
//
33846
// The terminal state has iter.depth < depth. at_start is always false.
33847
//
33848
// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
33849
//   In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
33850
//
33851
33852
} // namespace ondemand
33853
} // namespace arm64
33854
} // namespace simdjson
33855
33856
namespace simdjson {
33857
33858
simdjson_inline simdjson_result<arm64::ondemand::object_iterator>::simdjson_result(
33859
  arm64::ondemand::object_iterator &&value
33860
) noexcept
33861
  : implementation_simdjson_result_base<arm64::ondemand::object_iterator>(std::forward<arm64::ondemand::object_iterator>(value))
33862
{
33863
  first.iter.assert_is_valid();
33864
}
33865
simdjson_inline simdjson_result<arm64::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
33866
  : implementation_simdjson_result_base<arm64::ondemand::object_iterator>({}, error)
33867
{
33868
}
33869
33870
simdjson_inline simdjson_result<arm64::ondemand::field> simdjson_result<arm64::ondemand::object_iterator>::operator*() noexcept {
33871
  if (error()) { return error(); }
33872
  return *first;
33873
}
33874
// If we're iterating and there is an error, return the error once.
33875
simdjson_inline bool simdjson_result<arm64::ondemand::object_iterator>::operator==(const simdjson_result<arm64::ondemand::object_iterator> &other) const noexcept {
33876
  if (!first.iter.is_valid()) { return !error(); }
33877
  return first == other.first;
33878
}
33879
// If we're iterating and there is an error, return the error once.
33880
simdjson_inline bool simdjson_result<arm64::ondemand::object_iterator>::operator!=(const simdjson_result<arm64::ondemand::object_iterator> &other) const noexcept {
33881
  if (!first.iter.is_valid()) { return error(); }
33882
  return first != other.first;
33883
}
33884
// Checks for ']' and ','
33885
simdjson_inline simdjson_result<arm64::ondemand::object_iterator> &simdjson_result<arm64::ondemand::object_iterator>::operator++() noexcept {
33886
  // Clear the error if there is one, so we don't yield it twice
33887
  if (error()) { second = SUCCESS; return *this; }
33888
  ++first;
33889
  return *this;
33890
}
33891
33892
} // namespace simdjson
33893
33894
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
33895
/* end file simdjson/generic/ondemand/object_iterator-inl.h for arm64 */
33896
/* including simdjson/generic/ondemand/parser-inl.h for arm64: #include "simdjson/generic/ondemand/parser-inl.h" */
33897
/* begin file simdjson/generic/ondemand/parser-inl.h for arm64 */
33898
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
33899
33900
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
33901
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */
33902
/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */
33903
/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */
33904
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
33905
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
33906
/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */
33907
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
33908
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
33909
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
33910
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
33911
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
33912
33913
namespace simdjson {
33914
namespace arm64 {
33915
namespace ondemand {
33916
33917
simdjson_inline parser::parser(size_t max_capacity) noexcept
33918
  : _max_capacity{max_capacity} {
33919
}
33920
33921
simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept {
33922
  if (new_capacity > max_capacity()) { return CAPACITY; }
33923
  if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; }
33924
33925
  // string_capacity copied from document::allocate
33926
  _capacity = 0;
33927
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64);
33928
  string_buf.reset(new (std::nothrow) uint8_t[string_capacity]);
33929
#if SIMDJSON_DEVELOPMENT_CHECKS
33930
  start_positions.reset(new (std::nothrow) token_position[new_max_depth]);
33931
#endif
33932
  if (implementation) {
33933
    SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
33934
    SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
33935
  } else {
33936
    SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
33937
  }
33938
  _capacity = new_capacity;
33939
  _max_depth = new_max_depth;
33940
  return SUCCESS;
33941
}
33942
33943
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(padded_string_view json) & noexcept {
33944
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
33945
33946
  json.remove_utf8_bom();
33947
33948
  // Allocate if needed
33949
  if (capacity() < json.length() || !string_buf) {
33950
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
33951
  }
33952
33953
  // Run stage 1.
33954
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
33955
  return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this });
33956
}
33957
33958
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const char *json, size_t len, size_t allocated) & noexcept {
33959
  return iterate(padded_string_view(json, len, allocated));
33960
}
33961
33962
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept {
33963
  return iterate(padded_string_view(json, len, allocated));
33964
}
33965
33966
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string_view json, size_t allocated) & noexcept {
33967
  return iterate(padded_string_view(json, allocated));
33968
}
33969
33970
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
33971
  if(json.capacity() - json.size() < SIMDJSON_PADDING) {
33972
    json.reserve(json.size() + SIMDJSON_PADDING);
33973
  }
33974
  return iterate(padded_string_view(json));
33975
}
33976
33977
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
33978
  return iterate(padded_string_view(json));
33979
}
33980
33981
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string_view> &result) & noexcept {
33982
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
33983
  SIMDJSON_TRY( result.error() );
33984
  padded_string_view json = result.value_unsafe();
33985
  return iterate(json);
33986
}
33987
33988
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
33989
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
33990
  SIMDJSON_TRY( result.error() );
33991
  const padded_string &json = result.value_unsafe();
33992
  return iterate(json);
33993
}
33994
33995
simdjson_warn_unused simdjson_inline simdjson_result<json_iterator> parser::iterate_raw(padded_string_view json) & noexcept {
33996
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
33997
33998
  json.remove_utf8_bom();
33999
34000
  // Allocate if needed
34001
  if (capacity() < json.length()) {
34002
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
34003
  }
34004
34005
  // Run stage 1.
34006
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
34007
  return json_iterator(reinterpret_cast<const uint8_t *>(json.data()), this);
34008
}
34009
34010
inline simdjson_result<document_stream> parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
34011
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
34012
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
34013
    buf += 3;
34014
    len -= 3;
34015
  }
34016
  if(allow_comma_separated && batch_size < len) { batch_size = len; }
34017
  return document_stream(*this, buf, len, batch_size, allow_comma_separated);
34018
}
34019
inline simdjson_result<document_stream> parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
34020
  return iterate_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size, allow_comma_separated);
34021
}
34022
inline simdjson_result<document_stream> parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept {
34023
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
34024
}
34025
inline simdjson_result<document_stream> parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept {
34026
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
34027
}
34028
34029
simdjson_inline size_t parser::capacity() const noexcept {
34030
  return _capacity;
34031
}
34032
simdjson_inline size_t parser::max_capacity() const noexcept {
34033
  return _max_capacity;
34034
}
34035
simdjson_inline size_t parser::max_depth() const noexcept {
34036
  return _max_depth;
34037
}
34038
34039
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
34040
  if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
34041
    _max_capacity = max_capacity;
34042
  } else {
34043
    _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
34044
  }
34045
}
34046
34047
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept {
34048
  uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement);
34049
  if (!end) { return STRING_ERROR; }
34050
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
34051
  dst = end;
34052
  return result;
34053
}
34054
34055
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept {
34056
  uint8_t *end = implementation->parse_wobbly_string(in.buf, dst);
34057
  if (!end) { return STRING_ERROR; }
34058
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
34059
  dst = end;
34060
  return result;
34061
}
34062
34063
} // namespace ondemand
34064
} // namespace arm64
34065
} // namespace simdjson
34066
34067
namespace simdjson {
34068
34069
simdjson_inline simdjson_result<arm64::ondemand::parser>::simdjson_result(arm64::ondemand::parser &&value) noexcept
34070
    : implementation_simdjson_result_base<arm64::ondemand::parser>(std::forward<arm64::ondemand::parser>(value)) {}
34071
simdjson_inline simdjson_result<arm64::ondemand::parser>::simdjson_result(error_code error) noexcept
34072
    : implementation_simdjson_result_base<arm64::ondemand::parser>(error) {}
34073
34074
} // namespace simdjson
34075
34076
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
34077
/* end file simdjson/generic/ondemand/parser-inl.h for arm64 */
34078
/* including simdjson/generic/ondemand/raw_json_string-inl.h for arm64: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
34079
/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for arm64 */
34080
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
34081
34082
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
34083
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */
34084
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
34085
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
34086
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
34087
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
34088
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
34089
34090
namespace simdjson {
34091
34092
namespace arm64 {
34093
namespace ondemand {
34094
34095
simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
34096
34097
simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
34098
34099
34100
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
34101
  size_t pos{0};
34102
  // if the content has no escape character, just scan through it quickly!
34103
  for(;pos < target.size() && target[pos] != '\\';pos++) {}
34104
  // slow path may begin.
34105
  bool escaping{false};
34106
  for(;pos < target.size();pos++) {
34107
    if((target[pos] == '"') && !escaping) {
34108
      return false;
34109
    } else if(target[pos] == '\\') {
34110
      escaping = !escaping;
34111
    } else {
34112
      escaping = false;
34113
    }
34114
  }
34115
  return true;
34116
}
34117
34118
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
34119
  size_t pos{0};
34120
  // if the content has no escape character, just scan through it quickly!
34121
  for(;target[pos] && target[pos] != '\\';pos++) {}
34122
  // slow path may begin.
34123
  bool escaping{false};
34124
  for(;target[pos];pos++) {
34125
    if((target[pos] == '"') && !escaping) {
34126
      return false;
34127
    } else if(target[pos] == '\\') {
34128
      escaping = !escaping;
34129
    } else {
34130
      escaping = false;
34131
    }
34132
  }
34133
  return true;
34134
}
34135
34136
34137
simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
34138
  // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
34139
  return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
34140
}
34141
34142
simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
34143
  // Assumptions: does not contain unescaped quote characters, and
34144
  // the raw content is quote terminated within a valid JSON string.
34145
  if(target.size() <= SIMDJSON_PADDING) {
34146
    return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
34147
  }
34148
  const char * r{raw()};
34149
  size_t pos{0};
34150
  for(;pos < target.size();pos++) {
34151
    if(r[pos] != target[pos]) { return false; }
34152
  }
34153
  if(r[pos] != '"') { return false; }
34154
  return true;
34155
}
34156
34157
simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
34158
  const char * r{raw()};
34159
  size_t pos{0};
34160
  bool escaping{false};
34161
  for(;pos < target.size();pos++) {
34162
    if(r[pos] != target[pos]) { return false; }
34163
    // if target is a compile-time constant and it is free from
34164
    // quotes, then the next part could get optimized away through
34165
    // inlining.
34166
    if((target[pos] == '"') && !escaping) {
34167
      // We have reached the end of the raw_json_string but
34168
      // the target is not done.
34169
      return false;
34170
    } else if(target[pos] == '\\') {
34171
      escaping = !escaping;
34172
    } else {
34173
      escaping = false;
34174
    }
34175
  }
34176
  if(r[pos] != '"') { return false; }
34177
  return true;
34178
}
34179
34180
34181
simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
34182
  // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
34183
  // the raw content is quote terminated within a valid JSON string.
34184
  const char * r{raw()};
34185
  size_t pos{0};
34186
  for(;target[pos];pos++) {
34187
    if(r[pos] != target[pos]) { return false; }
34188
  }
34189
  if(r[pos] != '"') { return false; }
34190
  return true;
34191
}
34192
34193
simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
34194
  // Assumptions: does not contain unescaped quote characters, and
34195
  // the raw content is quote terminated within a valid JSON string.
34196
  const char * r{raw()};
34197
  size_t pos{0};
34198
  bool escaping{false};
34199
  for(;target[pos];pos++) {
34200
    if(r[pos] != target[pos]) { return false; }
34201
    // if target is a compile-time constant and it is free from
34202
    // quotes, then the next part could get optimized away through
34203
    // inlining.
34204
    if((target[pos] == '"') && !escaping) {
34205
      // We have reached the end of the raw_json_string but
34206
      // the target is not done.
34207
      return false;
34208
    } else if(target[pos] == '\\') {
34209
      escaping = !escaping;
34210
    } else {
34211
      escaping = false;
34212
    }
34213
  }
34214
  if(r[pos] != '"') { return false; }
34215
  return true;
34216
}
34217
34218
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
34219
  return a.unsafe_is_equal(c);
34220
}
34221
34222
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
34223
  return a == c;
34224
}
34225
34226
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
34227
  return !(a == c);
34228
}
34229
34230
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
34231
  return !(a == c);
34232
}
34233
34234
34235
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
34236
  return iter.unescape(*this, allow_replacement);
34237
}
34238
34239
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
34240
  return iter.unescape_wobbly(*this);
34241
}
34242
34243
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
34244
  bool in_escape = false;
34245
  const char *s = str.raw();
34246
  while (true) {
34247
    switch (*s) {
34248
      case '\\': in_escape = !in_escape; break;
34249
      case '"': if (in_escape) { in_escape = false; } else { return out; } break;
34250
      default: if (in_escape) { in_escape = false; }
34251
    }
34252
    out << *s;
34253
    s++;
34254
  }
34255
}
34256
34257
} // namespace ondemand
34258
} // namespace arm64
34259
} // namespace simdjson
34260
34261
namespace simdjson {
34262
34263
simdjson_inline simdjson_result<arm64::ondemand::raw_json_string>::simdjson_result(arm64::ondemand::raw_json_string &&value) noexcept
34264
    : implementation_simdjson_result_base<arm64::ondemand::raw_json_string>(std::forward<arm64::ondemand::raw_json_string>(value)) {}
34265
simdjson_inline simdjson_result<arm64::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
34266
    : implementation_simdjson_result_base<arm64::ondemand::raw_json_string>(error) {}
34267
34268
simdjson_inline simdjson_result<const char *> simdjson_result<arm64::ondemand::raw_json_string>::raw() const noexcept {
34269
  if (error()) { return error(); }
34270
  return first.raw();
34271
}
34272
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<arm64::ondemand::raw_json_string>::unescape(arm64::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
34273
  if (error()) { return error(); }
34274
  return first.unescape(iter, allow_replacement);
34275
}
34276
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<arm64::ondemand::raw_json_string>::unescape_wobbly(arm64::ondemand::json_iterator &iter) const noexcept {
34277
  if (error()) { return error(); }
34278
  return first.unescape_wobbly(iter);
34279
}
34280
} // namespace simdjson
34281
34282
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
34283
/* end file simdjson/generic/ondemand/raw_json_string-inl.h for arm64 */
34284
/* including simdjson/generic/ondemand/serialization-inl.h for arm64: #include "simdjson/generic/ondemand/serialization-inl.h" */
34285
/* begin file simdjson/generic/ondemand/serialization-inl.h for arm64 */
34286
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
34287
34288
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
34289
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */
34290
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
34291
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
34292
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
34293
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
34294
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
34295
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */
34296
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
34297
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
34298
34299
namespace simdjson {
34300
34301
inline std::string_view trim(const std::string_view str) noexcept {
34302
  // We can almost surely do better by rolling our own find_first_not_of function.
34303
  size_t first = str.find_first_not_of(" \t\n\r");
34304
  // If we have the empty string (just white space), then no trimming is possible, and
34305
  // we return the empty string_view.
34306
  if (std::string_view::npos == first) { return std::string_view(); }
34307
  size_t last = str.find_last_not_of(" \t\n\r");
34308
  return str.substr(first, (last - first + 1));
34309
}
34310
34311
34312
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::document& x) noexcept {
34313
  std::string_view v;
34314
  auto error = x.raw_json().get(v);
34315
  if(error) {return error; }
34316
  return trim(v);
34317
}
34318
34319
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::document_reference& x) noexcept {
34320
  std::string_view v;
34321
  auto error = x.raw_json().get(v);
34322
  if(error) {return error; }
34323
  return trim(v);
34324
}
34325
34326
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::value& x) noexcept {
34327
  /**
34328
   * If we somehow receive a value that has already been consumed,
34329
   * then the following code could be in trouble. E.g., we create
34330
   * an array as needed, but if an array was already created, then
34331
   * it could be bad.
34332
   */
34333
  using namespace arm64::ondemand;
34334
  arm64::ondemand::json_type t;
34335
  auto error = x.type().get(t);
34336
  if(error != SUCCESS) { return error; }
34337
  switch (t)
34338
  {
34339
    case json_type::array:
34340
    {
34341
      arm64::ondemand::array array;
34342
      error = x.get_array().get(array);
34343
      if(error) { return error; }
34344
      return to_json_string(array);
34345
    }
34346
    case json_type::object:
34347
    {
34348
      arm64::ondemand::object object;
34349
      error = x.get_object().get(object);
34350
      if(error) { return error; }
34351
      return to_json_string(object);
34352
    }
34353
    default:
34354
      return trim(x.raw_json_token());
34355
  }
34356
}
34357
34358
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::object& x) noexcept {
34359
  std::string_view v;
34360
  auto error = x.raw_json().get(v);
34361
  if(error) {return error; }
34362
  return trim(v);
34363
}
34364
34365
inline simdjson_result<std::string_view> to_json_string(arm64::ondemand::array& x) noexcept {
34366
  std::string_view v;
34367
  auto error = x.raw_json().get(v);
34368
  if(error) {return error; }
34369
  return trim(v);
34370
}
34371
34372
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::document> x) {
34373
  if (x.error()) { return x.error(); }
34374
  return to_json_string(x.value_unsafe());
34375
}
34376
34377
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::document_reference> x) {
34378
  if (x.error()) { return x.error(); }
34379
  return to_json_string(x.value_unsafe());
34380
}
34381
34382
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::value> x) {
34383
  if (x.error()) { return x.error(); }
34384
  return to_json_string(x.value_unsafe());
34385
}
34386
34387
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::object> x) {
34388
  if (x.error()) { return x.error(); }
34389
  return to_json_string(x.value_unsafe());
34390
}
34391
34392
inline simdjson_result<std::string_view> to_json_string(simdjson_result<arm64::ondemand::array> x) {
34393
  if (x.error()) { return x.error(); }
34394
  return to_json_string(x.value_unsafe());
34395
}
34396
} // namespace simdjson
34397
34398
namespace simdjson { namespace arm64 { namespace ondemand {
34399
34400
#if SIMDJSON_EXCEPTIONS
34401
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::value x) {
34402
  std::string_view v;
34403
  auto error = simdjson::to_json_string(x).get(v);
34404
  if(error == simdjson::SUCCESS) {
34405
    return (out << v);
34406
  } else {
34407
    throw simdjson::simdjson_error(error);
34408
  }
34409
}
34410
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::value> x) {
34411
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
34412
  return (out << x.value());
34413
}
34414
#else
34415
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::value x) {
34416
  std::string_view v;
34417
  auto error = simdjson::to_json_string(x).get(v);
34418
  if(error == simdjson::SUCCESS) {
34419
    return (out << v);
34420
  } else {
34421
    return (out << error);
34422
  }
34423
}
34424
#endif
34425
34426
#if SIMDJSON_EXCEPTIONS
34427
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::array value) {
34428
  std::string_view v;
34429
  auto error = simdjson::to_json_string(value).get(v);
34430
  if(error == simdjson::SUCCESS) {
34431
    return (out << v);
34432
  } else {
34433
    throw simdjson::simdjson_error(error);
34434
  }
34435
}
34436
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::array> x) {
34437
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
34438
  return (out << x.value());
34439
}
34440
#else
34441
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::array value) {
34442
  std::string_view v;
34443
  auto error = simdjson::to_json_string(value).get(v);
34444
  if(error == simdjson::SUCCESS) {
34445
    return (out << v);
34446
  } else {
34447
    return (out << error);
34448
  }
34449
}
34450
#endif
34451
34452
#if SIMDJSON_EXCEPTIONS
34453
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::document& value)  {
34454
  std::string_view v;
34455
  auto error = simdjson::to_json_string(value).get(v);
34456
  if(error == simdjson::SUCCESS) {
34457
    return (out << v);
34458
  } else {
34459
    throw simdjson::simdjson_error(error);
34460
  }
34461
}
34462
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::document_reference& value)  {
34463
  std::string_view v;
34464
  auto error = simdjson::to_json_string(value).get(v);
34465
  if(error == simdjson::SUCCESS) {
34466
    return (out << v);
34467
  } else {
34468
    throw simdjson::simdjson_error(error);
34469
  }
34470
}
34471
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::document>&& x) {
34472
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
34473
  return (out << x.value());
34474
}
34475
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::arm64::ondemand::document_reference>&& x) {
34476
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
34477
  return (out << x.value());
34478
}
34479
#else
34480
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::document& value)  {
34481
  std::string_view v;
34482
  auto error = simdjson::to_json_string(value).get(v);
34483
  if(error == simdjson::SUCCESS) {
34484
    return (out << v);
34485
  } else {
34486
    return (out << error);
34487
  }
34488
}
34489
#endif
34490
34491
#if SIMDJSON_EXCEPTIONS
34492
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::object value) {
34493
  std::string_view v;
34494
  auto error = simdjson::to_json_string(value).get(v);
34495
  if(error == simdjson::SUCCESS) {
34496
    return (out << v);
34497
  } else {
34498
    throw simdjson::simdjson_error(error);
34499
  }
34500
}
34501
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::arm64::ondemand::object> x) {
34502
  if (x.error()) { throw  simdjson::simdjson_error(x.error()); }
34503
  return (out << x.value());
34504
}
34505
#else
34506
inline std::ostream& operator<<(std::ostream& out, simdjson::arm64::ondemand::object value) {
34507
  std::string_view v;
34508
  auto error = simdjson::to_json_string(value).get(v);
34509
  if(error == simdjson::SUCCESS) {
34510
    return (out << v);
34511
  } else {
34512
    return (out << error);
34513
  }
34514
}
34515
#endif
34516
}}} // namespace simdjson::arm64::ondemand
34517
34518
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
34519
/* end file simdjson/generic/ondemand/serialization-inl.h for arm64 */
34520
/* including simdjson/generic/ondemand/token_iterator-inl.h for arm64: #include "simdjson/generic/ondemand/token_iterator-inl.h" */
34521
/* begin file simdjson/generic/ondemand/token_iterator-inl.h for arm64 */
34522
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
34523
34524
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
34525
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */
34526
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
34527
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
34528
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
34529
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
34530
34531
namespace simdjson {
34532
namespace arm64 {
34533
namespace ondemand {
34534
34535
simdjson_inline token_iterator::token_iterator(
34536
  const uint8_t *_buf,
34537
  token_position position
34538
) noexcept : buf{_buf}, _position{position}
34539
{
34540
}
34541
34542
simdjson_inline uint32_t token_iterator::current_offset() const noexcept {
34543
  return *(_position);
34544
}
34545
34546
34547
simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept {
34548
  return &buf[*(_position++)];
34549
}
34550
34551
simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept {
34552
  return &buf[*position];
34553
}
34554
simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept {
34555
  return *position;
34556
}
34557
simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept {
34558
  return *(position+1) - *position;
34559
}
34560
34561
simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept {
34562
  return *(position+2) - *(position) > *(position+1) - *(position) ?
34563
      *(position+1) - *(position)
34564
      : *(position+2) - *(position);
34565
}
34566
simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept {
34567
  return &buf[*(_position+delta)];
34568
}
34569
simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept {
34570
  return *(_position+delta);
34571
}
34572
simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept {
34573
  return *(_position+delta+1) - *(_position+delta);
34574
}
34575
34576
simdjson_inline token_position token_iterator::position() const noexcept {
34577
  return _position;
34578
}
34579
simdjson_inline void token_iterator::set_position(token_position target_position) noexcept {
34580
  _position = target_position;
34581
}
34582
34583
simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept {
34584
  return _position == other._position;
34585
}
34586
simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept {
34587
  return _position != other._position;
34588
}
34589
simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept {
34590
  return _position > other._position;
34591
}
34592
simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept {
34593
  return _position >= other._position;
34594
}
34595
simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept {
34596
  return _position < other._position;
34597
}
34598
simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept {
34599
  return _position <= other._position;
34600
}
34601
34602
} // namespace ondemand
34603
} // namespace arm64
34604
} // namespace simdjson
34605
34606
namespace simdjson {
34607
34608
simdjson_inline simdjson_result<arm64::ondemand::token_iterator>::simdjson_result(arm64::ondemand::token_iterator &&value) noexcept
34609
    : implementation_simdjson_result_base<arm64::ondemand::token_iterator>(std::forward<arm64::ondemand::token_iterator>(value)) {}
34610
simdjson_inline simdjson_result<arm64::ondemand::token_iterator>::simdjson_result(error_code error) noexcept
34611
    : implementation_simdjson_result_base<arm64::ondemand::token_iterator>(error) {}
34612
34613
} // namespace simdjson
34614
34615
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
34616
/* end file simdjson/generic/ondemand/token_iterator-inl.h for arm64 */
34617
/* including simdjson/generic/ondemand/value-inl.h for arm64: #include "simdjson/generic/ondemand/value-inl.h" */
34618
/* begin file simdjson/generic/ondemand/value-inl.h for arm64 */
34619
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
34620
34621
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
34622
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */
34623
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
34624
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
34625
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
34626
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
34627
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
34628
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
34629
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
34630
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
34631
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
34632
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
34633
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
34634
34635
namespace simdjson {
34636
namespace arm64 {
34637
namespace ondemand {
34638
34639
simdjson_inline value::value(const value_iterator &_iter) noexcept
34640
  : iter{_iter}
34641
{
34642
}
34643
simdjson_inline value value::start(const value_iterator &iter) noexcept {
34644
  return iter;
34645
}
34646
simdjson_inline value value::resume(const value_iterator &iter) noexcept {
34647
  return iter;
34648
}
34649
34650
simdjson_inline simdjson_result<array> value::get_array() noexcept {
34651
  return array::start(iter);
34652
}
34653
simdjson_inline simdjson_result<object> value::get_object() noexcept {
34654
  return object::start(iter);
34655
}
34656
simdjson_inline simdjson_result<object> value::start_or_resume_object() noexcept {
34657
  if (iter.at_start()) {
34658
    return get_object();
34659
  } else {
34660
    return object::resume(iter);
34661
  }
34662
}
34663
34664
simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
34665
  return iter.get_raw_json_string();
34666
}
34667
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
34668
  return iter.get_string(allow_replacement);
34669
}
34670
template <typename string_type>
34671
simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
34672
  return iter.get_string(receiver, allow_replacement);
34673
}
34674
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
34675
  return iter.get_wobbly_string();
34676
}
34677
simdjson_inline simdjson_result<double> value::get_double() noexcept {
34678
  return iter.get_double();
34679
}
34680
simdjson_inline simdjson_result<double> value::get_double_in_string() noexcept {
34681
  return iter.get_double_in_string();
34682
}
34683
simdjson_inline simdjson_result<uint64_t> value::get_uint64() noexcept {
34684
  return iter.get_uint64();
34685
}
34686
simdjson_inline simdjson_result<uint64_t> value::get_uint64_in_string() noexcept {
34687
  return iter.get_uint64_in_string();
34688
}
34689
simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
34690
  return iter.get_int64();
34691
}
34692
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
34693
  return iter.get_int64_in_string();
34694
}
34695
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
34696
  return iter.get_bool();
34697
}
34698
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
34699
  return iter.is_null();
34700
}
34701
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
34702
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
34703
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
34704
template<> simdjson_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(false); }
34705
template<> simdjson_inline simdjson_result<number> value::get() noexcept { return get_number(); }
34706
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
34707
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
34708
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
34709
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
34710
34711
template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
34712
  return get<T>().get(out);
34713
}
34714
34715
#if SIMDJSON_EXCEPTIONS
34716
template <class T>
34717
simdjson_inline value::operator T() noexcept(false) {
34718
  return get<T>();
34719
}
34720
simdjson_inline value::operator array() noexcept(false) {
34721
  return get_array();
34722
}
34723
simdjson_inline value::operator object() noexcept(false) {
34724
  return get_object();
34725
}
34726
simdjson_inline value::operator uint64_t() noexcept(false) {
34727
  return get_uint64();
34728
}
34729
simdjson_inline value::operator int64_t() noexcept(false) {
34730
  return get_int64();
34731
}
34732
simdjson_inline value::operator double() noexcept(false) {
34733
  return get_double();
34734
}
34735
simdjson_inline value::operator std::string_view() noexcept(false) {
34736
  return get_string(false);
34737
}
34738
simdjson_inline value::operator raw_json_string() noexcept(false) {
34739
  return get_raw_json_string();
34740
}
34741
simdjson_inline value::operator bool() noexcept(false) {
34742
  return get_bool();
34743
}
34744
#endif
34745
34746
simdjson_inline simdjson_result<array_iterator> value::begin() & noexcept {
34747
  return get_array().begin();
34748
}
34749
simdjson_inline simdjson_result<array_iterator> value::end() & noexcept {
34750
  return {};
34751
}
34752
simdjson_inline simdjson_result<size_t> value::count_elements() & noexcept {
34753
  simdjson_result<size_t> answer;
34754
  auto a = get_array();
34755
  answer = a.count_elements();
34756
  // count_elements leaves you pointing inside the array, at the first element.
34757
  // We need to move back so that the user can create a new array (which requires that
34758
  // we point at '[').
34759
  iter.move_at_start();
34760
  return answer;
34761
}
34762
simdjson_inline simdjson_result<size_t> value::count_fields() & noexcept {
34763
  simdjson_result<size_t> answer;
34764
  auto a = get_object();
34765
  answer = a.count_fields();
34766
  iter.move_at_start();
34767
  return answer;
34768
}
34769
simdjson_inline simdjson_result<value> value::at(size_t index) noexcept {
34770
  auto a = get_array();
34771
  return a.at(index);
34772
}
34773
34774
simdjson_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
34775
  return start_or_resume_object().find_field(key);
34776
}
34777
simdjson_inline simdjson_result<value> value::find_field(const char *key) noexcept {
34778
  return start_or_resume_object().find_field(key);
34779
}
34780
34781
simdjson_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
34782
  return start_or_resume_object().find_field_unordered(key);
34783
}
34784
simdjson_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
34785
  return start_or_resume_object().find_field_unordered(key);
34786
}
34787
34788
simdjson_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
34789
  return start_or_resume_object()[key];
34790
}
34791
simdjson_inline simdjson_result<value> value::operator[](const char *key) noexcept {
34792
  return start_or_resume_object()[key];
34793
}
34794
34795
simdjson_inline simdjson_result<json_type> value::type() noexcept {
34796
  return iter.type();
34797
}
34798
34799
simdjson_inline simdjson_result<bool> value::is_scalar() noexcept {
34800
  json_type this_type;
34801
  auto error = type().get(this_type);
34802
  if(error) { return error; }
34803
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
34804
}
34805
34806
simdjson_inline simdjson_result<bool> value::is_string() noexcept {
34807
  json_type this_type;
34808
  auto error = type().get(this_type);
34809
  if(error) { return error; }
34810
  return (this_type == json_type::string);
34811
}
34812
34813
34814
simdjson_inline bool value::is_negative() noexcept {
34815
  return iter.is_negative();
34816
}
34817
34818
simdjson_inline simdjson_result<bool> value::is_integer() noexcept {
34819
  return iter.is_integer();
34820
}
34821
simdjson_warn_unused simdjson_inline simdjson_result<number_type> value::get_number_type() noexcept {
34822
  return iter.get_number_type();
34823
}
34824
simdjson_warn_unused simdjson_inline simdjson_result<number> value::get_number() noexcept {
34825
  return iter.get_number();
34826
}
34827
34828
simdjson_inline std::string_view value::raw_json_token() noexcept {
34829
  return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
34830
}
34831
34832
simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
34833
  json_type t;
34834
  SIMDJSON_TRY(type().get(t));
34835
  switch (t)
34836
  {
34837
    case json_type::array: {
34838
      ondemand::array array;
34839
      SIMDJSON_TRY(get_array().get(array));
34840
      return array.raw_json();
34841
    }
34842
    case json_type::object: {
34843
      ondemand::object object;
34844
      SIMDJSON_TRY(get_object().get(object));
34845
      return object.raw_json();
34846
    }
34847
    default:
34848
      return raw_json_token();
34849
  }
34850
}
34851
34852
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
34853
  return iter.json_iter().current_location();
34854
}
34855
34856
simdjson_inline int32_t value::current_depth() const noexcept{
34857
  return iter.json_iter().depth();
34858
}
34859
34860
simdjson_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
34861
  json_type t;
34862
  SIMDJSON_TRY(type().get(t));
34863
  switch (t)
34864
  {
34865
    case json_type::array:
34866
      return (*this).get_array().at_pointer(json_pointer);
34867
    case json_type::object:
34868
      return (*this).get_object().at_pointer(json_pointer);
34869
    default:
34870
      return INVALID_JSON_POINTER;
34871
  }
34872
}
34873
34874
simdjson_inline simdjson_result<value> value::at_path(std::string_view json_path) noexcept {
34875
  json_type t;
34876
  SIMDJSON_TRY(type().get(t));
34877
  switch (t) {
34878
  case json_type::array:
34879
      return (*this).get_array().at_path(json_path);
34880
  case json_type::object:
34881
      return (*this).get_object().at_path(json_path);
34882
  default:
34883
      return INVALID_JSON_POINTER;
34884
  }
34885
}
34886
34887
} // namespace ondemand
34888
} // namespace arm64
34889
} // namespace simdjson
34890
34891
namespace simdjson {
34892
34893
simdjson_inline simdjson_result<arm64::ondemand::value>::simdjson_result(
34894
  arm64::ondemand::value &&value
34895
) noexcept :
34896
    implementation_simdjson_result_base<arm64::ondemand::value>(
34897
      std::forward<arm64::ondemand::value>(value)
34898
    )
34899
{
34900
}
34901
simdjson_inline simdjson_result<arm64::ondemand::value>::simdjson_result(
34902
  error_code error
34903
) noexcept :
34904
    implementation_simdjson_result_base<arm64::ondemand::value>(error)
34905
{
34906
}
34907
simdjson_inline simdjson_result<size_t> simdjson_result<arm64::ondemand::value>::count_elements() & noexcept {
34908
  if (error()) { return error(); }
34909
  return first.count_elements();
34910
}
34911
simdjson_inline simdjson_result<size_t> simdjson_result<arm64::ondemand::value>::count_fields() & noexcept {
34912
  if (error()) { return error(); }
34913
  return first.count_fields();
34914
}
34915
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::at(size_t index) noexcept {
34916
  if (error()) { return error(); }
34917
  return first.at(index);
34918
}
34919
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::value>::begin() & noexcept {
34920
  if (error()) { return error(); }
34921
  return first.begin();
34922
}
34923
simdjson_inline simdjson_result<arm64::ondemand::array_iterator> simdjson_result<arm64::ondemand::value>::end() & noexcept {
34924
  if (error()) { return error(); }
34925
  return {};
34926
}
34927
34928
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::find_field(std::string_view key) noexcept {
34929
  if (error()) { return error(); }
34930
  return first.find_field(key);
34931
}
34932
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::find_field(const char *key) noexcept {
34933
  if (error()) { return error(); }
34934
  return first.find_field(key);
34935
}
34936
34937
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
34938
  if (error()) { return error(); }
34939
  return first.find_field_unordered(key);
34940
}
34941
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::find_field_unordered(const char *key) noexcept {
34942
  if (error()) { return error(); }
34943
  return first.find_field_unordered(key);
34944
}
34945
34946
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::operator[](std::string_view key) noexcept {
34947
  if (error()) { return error(); }
34948
  return first[key];
34949
}
34950
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::operator[](const char *key) noexcept {
34951
  if (error()) { return error(); }
34952
  return first[key];
34953
}
34954
34955
simdjson_inline simdjson_result<arm64::ondemand::array> simdjson_result<arm64::ondemand::value>::get_array() noexcept {
34956
  if (error()) { return error(); }
34957
  return first.get_array();
34958
}
34959
simdjson_inline simdjson_result<arm64::ondemand::object> simdjson_result<arm64::ondemand::value>::get_object() noexcept {
34960
  if (error()) { return error(); }
34961
  return first.get_object();
34962
}
34963
simdjson_inline simdjson_result<uint64_t> simdjson_result<arm64::ondemand::value>::get_uint64() noexcept {
34964
  if (error()) { return error(); }
34965
  return first.get_uint64();
34966
}
34967
simdjson_inline simdjson_result<uint64_t> simdjson_result<arm64::ondemand::value>::get_uint64_in_string() noexcept {
34968
  if (error()) { return error(); }
34969
  return first.get_uint64_in_string();
34970
}
34971
simdjson_inline simdjson_result<int64_t> simdjson_result<arm64::ondemand::value>::get_int64() noexcept {
34972
  if (error()) { return error(); }
34973
  return first.get_int64();
34974
}
34975
simdjson_inline simdjson_result<int64_t> simdjson_result<arm64::ondemand::value>::get_int64_in_string() noexcept {
34976
  if (error()) { return error(); }
34977
  return first.get_int64_in_string();
34978
}
34979
simdjson_inline simdjson_result<double> simdjson_result<arm64::ondemand::value>::get_double() noexcept {
34980
  if (error()) { return error(); }
34981
  return first.get_double();
34982
}
34983
simdjson_inline simdjson_result<double> simdjson_result<arm64::ondemand::value>::get_double_in_string() noexcept {
34984
  if (error()) { return error(); }
34985
  return first.get_double_in_string();
34986
}
34987
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::value>::get_string(bool allow_replacement) noexcept {
34988
  if (error()) { return error(); }
34989
  return first.get_string(allow_replacement);
34990
}
34991
template <typename string_type>
34992
simdjson_inline error_code simdjson_result<arm64::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
34993
  if (error()) { return error(); }
34994
  return first.get_string(receiver, allow_replacement);
34995
}
34996
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::value>::get_wobbly_string() noexcept {
34997
  if (error()) { return error(); }
34998
  return first.get_wobbly_string();
34999
}
35000
simdjson_inline simdjson_result<arm64::ondemand::raw_json_string> simdjson_result<arm64::ondemand::value>::get_raw_json_string() noexcept {
35001
  if (error()) { return error(); }
35002
  return first.get_raw_json_string();
35003
}
35004
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::value>::get_bool() noexcept {
35005
  if (error()) { return error(); }
35006
  return first.get_bool();
35007
}
35008
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::value>::is_null() noexcept {
35009
  if (error()) { return error(); }
35010
  return first.is_null();
35011
}
35012
35013
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<arm64::ondemand::value>::get() noexcept {
35014
  if (error()) { return error(); }
35015
  return first.get<T>();
35016
}
35017
template<typename T> simdjson_inline error_code simdjson_result<arm64::ondemand::value>::get(T &out) noexcept {
35018
  if (error()) { return error(); }
35019
  return first.get<T>(out);
35020
}
35021
35022
template<> simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::get<arm64::ondemand::value>() noexcept  {
35023
  if (error()) { return error(); }
35024
  return std::move(first);
35025
}
35026
template<> simdjson_inline error_code simdjson_result<arm64::ondemand::value>::get<arm64::ondemand::value>(arm64::ondemand::value &out) noexcept {
35027
  if (error()) { return error(); }
35028
  out = first;
35029
  return SUCCESS;
35030
}
35031
35032
simdjson_inline simdjson_result<arm64::ondemand::json_type> simdjson_result<arm64::ondemand::value>::type() noexcept {
35033
  if (error()) { return error(); }
35034
  return first.type();
35035
}
35036
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::value>::is_scalar() noexcept {
35037
  if (error()) { return error(); }
35038
  return first.is_scalar();
35039
}
35040
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::value>::is_string() noexcept {
35041
  if (error()) { return error(); }
35042
  return first.is_string();
35043
}
35044
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::value>::is_negative() noexcept {
35045
  if (error()) { return error(); }
35046
  return first.is_negative();
35047
}
35048
simdjson_inline simdjson_result<bool> simdjson_result<arm64::ondemand::value>::is_integer() noexcept {
35049
  if (error()) { return error(); }
35050
  return first.is_integer();
35051
}
35052
simdjson_inline simdjson_result<arm64::number_type> simdjson_result<arm64::ondemand::value>::get_number_type() noexcept {
35053
  if (error()) { return error(); }
35054
  return first.get_number_type();
35055
}
35056
simdjson_inline simdjson_result<arm64::ondemand::number> simdjson_result<arm64::ondemand::value>::get_number() noexcept {
35057
  if (error()) { return error(); }
35058
  return first.get_number();
35059
}
35060
#if SIMDJSON_EXCEPTIONS
35061
template <class T>
35062
simdjson_inline simdjson_result<arm64::ondemand::value>::operator T() noexcept(false) {
35063
  if (error()) { throw simdjson_error(error()); }
35064
  return static_cast<T>(first);
35065
}
35066
simdjson_inline simdjson_result<arm64::ondemand::value>::operator arm64::ondemand::array() noexcept(false) {
35067
  if (error()) { throw simdjson_error(error()); }
35068
  return first;
35069
}
35070
simdjson_inline simdjson_result<arm64::ondemand::value>::operator arm64::ondemand::object() noexcept(false) {
35071
  if (error()) { throw simdjson_error(error()); }
35072
  return first;
35073
}
35074
simdjson_inline simdjson_result<arm64::ondemand::value>::operator uint64_t() noexcept(false) {
35075
  if (error()) { throw simdjson_error(error()); }
35076
  return first;
35077
}
35078
simdjson_inline simdjson_result<arm64::ondemand::value>::operator int64_t() noexcept(false) {
35079
  if (error()) { throw simdjson_error(error()); }
35080
  return first;
35081
}
35082
simdjson_inline simdjson_result<arm64::ondemand::value>::operator double() noexcept(false) {
35083
  if (error()) { throw simdjson_error(error()); }
35084
  return first;
35085
}
35086
simdjson_inline simdjson_result<arm64::ondemand::value>::operator std::string_view() noexcept(false) {
35087
  if (error()) { throw simdjson_error(error()); }
35088
  return first;
35089
}
35090
simdjson_inline simdjson_result<arm64::ondemand::value>::operator arm64::ondemand::raw_json_string() noexcept(false) {
35091
  if (error()) { throw simdjson_error(error()); }
35092
  return first;
35093
}
35094
simdjson_inline simdjson_result<arm64::ondemand::value>::operator bool() noexcept(false) {
35095
  if (error()) { throw simdjson_error(error()); }
35096
  return first;
35097
}
35098
#endif
35099
35100
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::value>::raw_json_token() noexcept {
35101
  if (error()) { return error(); }
35102
  return first.raw_json_token();
35103
}
35104
35105
simdjson_inline simdjson_result<std::string_view> simdjson_result<arm64::ondemand::value>::raw_json() noexcept {
35106
  if (error()) { return error(); }
35107
  return first.raw_json();
35108
}
35109
35110
simdjson_inline simdjson_result<const char *> simdjson_result<arm64::ondemand::value>::current_location() noexcept {
35111
  if (error()) { return error(); }
35112
  return first.current_location();
35113
}
35114
35115
simdjson_inline simdjson_result<int32_t> simdjson_result<arm64::ondemand::value>::current_depth() const noexcept {
35116
  if (error()) { return error(); }
35117
  return first.current_depth();
35118
}
35119
35120
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::at_pointer(
35121
    std::string_view json_pointer) noexcept {
35122
  if (error()) {
35123
      return error();
35124
  }
35125
  return first.at_pointer(json_pointer);
35126
}
35127
35128
simdjson_inline simdjson_result<arm64::ondemand::value> simdjson_result<arm64::ondemand::value>::at_path(
35129
      std::string_view json_path) noexcept {
35130
  if (error()) {
35131
    return error();
35132
  }
35133
  return first.at_path(json_path);
35134
}
35135
35136
} // namespace simdjson
35137
35138
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
35139
/* end file simdjson/generic/ondemand/value-inl.h for arm64 */
35140
/* including simdjson/generic/ondemand/value_iterator-inl.h for arm64: #include "simdjson/generic/ondemand/value_iterator-inl.h" */
35141
/* begin file simdjson/generic/ondemand/value_iterator-inl.h for arm64 */
35142
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
35143
35144
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
35145
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */
35146
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
35147
/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */
35148
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
35149
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
35150
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */
35151
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
35152
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
35153
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
35154
35155
namespace simdjson {
35156
namespace arm64 {
35157
namespace ondemand {
35158
35159
simdjson_inline value_iterator::value_iterator(
35160
  json_iterator *json_iter,
35161
  depth_t depth,
35162
  token_position start_position
35163
) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
35164
{
35165
}
35166
35167
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
35168
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
35169
  return started_object();
35170
}
35171
35172
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
35173
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
35174
  return started_root_object();
35175
}
35176
35177
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
35178
  assert_at_container_start();
35179
#if SIMDJSON_DEVELOPMENT_CHECKS
35180
  _json_iter->set_start_position(_depth, start_position());
35181
#endif
35182
  if (*_json_iter->peek() == '}') {
35183
    logger::log_value(*_json_iter, "empty object");
35184
    _json_iter->return_current_and_advance();
35185
    end_container();
35186
    return false;
35187
  }
35188
  return true;
35189
}
35190
35191
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
35192
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
35193
  // current document. It only works in the normal mode where we have indexed a single document.
35194
  // Note that adding a check for 'streaming' is not expensive since we only have at most
35195
  // one root element.
35196
  if ( ! _json_iter->streaming() ) {
35197
    // The following lines do not fully protect against garbage content within the
35198
    // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
35199
    // call `at_end()` on the document instance at the end of the processing to
35200
    // ensure that the processing has finished at the end.
35201
    //
35202
    if (*_json_iter->peek_last() != '}') {
35203
      _json_iter->abandon();
35204
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
35205
    }
35206
    // If the last character is } *and* the first gibberish character is also '}'
35207
    // then on-demand could accidentally go over. So we need additional checks.
35208
    // https://github.com/simdjson/simdjson/issues/1834
35209
    // Checking that the document is balanced requires a full scan which is potentially
35210
    // expensive, but it only happens in edge cases where the first padding character is
35211
    // a closing bracket.
35212
    if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
35213
      _json_iter->abandon();
35214
      // The exact error would require more work. It will typically be an unclosed object.
35215
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
35216
    }
35217
  }
35218
  return SUCCESS;
35219
}
35220
35221
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
35222
  auto error = check_root_object();
35223
  if(error) { return error; }
35224
  return started_object();
35225
}
35226
35227
simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
35228
#if SIMDJSON_CHECK_EOF
35229
    if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
35230
    // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
35231
#endif // SIMDJSON_CHECK_EOF
35232
    _json_iter->ascend_to(depth()-1);
35233
    return SUCCESS;
35234
}
35235
35236
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
35237
  assert_at_next();
35238
35239
  // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
35240
  // obligated to verify there are more tokens if they are not the top level.
35241
  switch (*_json_iter->return_current_and_advance()) {
35242
    case '}':
35243
      logger::log_end_value(*_json_iter, "object");
35244
      SIMDJSON_TRY( end_container() );
35245
      return false;
35246
    case ',':
35247
      return true;
35248
    default:
35249
      return report_error(TAPE_ERROR, "Missing comma between object fields");
35250
  }
35251
}
35252
35253
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
35254
  error_code error;
35255
  bool has_value;
35256
  //
35257
  // Initially, the object can be in one of a few different places:
35258
  //
35259
  // 1. The start of the object, at the first field:
35260
  //
35261
  //    ```
35262
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35263
  //      ^ (depth 2, index 1)
35264
  //    ```
35265
  if (at_first_field()) {
35266
    has_value = true;
35267
35268
  //
35269
  // 2. When a previous search did not yield a value or the object is empty:
35270
  //
35271
  //    ```
35272
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35273
  //                                     ^ (depth 0)
35274
  //    { }
35275
  //        ^ (depth 0, index 2)
35276
  //    ```
35277
  //
35278
  } else if (!is_open()) {
35279
#if SIMDJSON_DEVELOPMENT_CHECKS
35280
    // If we're past the end of the object, we're being iterated out of order.
35281
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
35282
    // this object iterator will blithely scan that object for fields.
35283
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
35284
#endif
35285
    return false;
35286
35287
  // 3. When a previous search found a field or an iterator yielded a value:
35288
  //
35289
  //    ```
35290
  //    // When a field was not fully consumed (or not even touched at all)
35291
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35292
  //           ^ (depth 2)
35293
  //    // When a field was fully consumed
35294
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35295
  //                   ^ (depth 1)
35296
  //    // When the last field was fully consumed
35297
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35298
  //                                   ^ (depth 1)
35299
  //    ```
35300
  //
35301
  } else {
35302
    if ((error = skip_child() )) { abandon(); return error; }
35303
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
35304
#if SIMDJSON_DEVELOPMENT_CHECKS
35305
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
35306
#endif
35307
  }
35308
  while (has_value) {
35309
    // Get the key and colon, stopping at the value.
35310
    raw_json_string actual_key;
35311
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
35312
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
35313
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
35314
    // The depth is left unchanged by field_key().
35315
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
35316
    // field_value() will advance and check that we find a ':' separating the
35317
    // key and the value. It will also increment the depth by one.
35318
    if ((error = field_value() )) { abandon(); return error; }
35319
    // If it matches, stop and return
35320
    // We could do it this way if we wanted to allow arbitrary
35321
    // key content (including escaped quotes).
35322
    //if (actual_key.unsafe_is_equal(max_key_length, key)) {
35323
    // Instead we do the following which may trigger buffer overruns if the
35324
    // user provides an adversarial key (containing a well placed unescaped quote
35325
    // character and being longer than the number of bytes remaining in the JSON
35326
    // input).
35327
    if (actual_key.unsafe_is_equal(key)) {
35328
      logger::log_event(*this, "match", key, -2);
35329
      // If we return here, then we return while pointing at the ':' that we just checked.
35330
      return true;
35331
    }
35332
35333
    // No match: skip the value and see if , or } is next
35334
    logger::log_event(*this, "no match", key, -2);
35335
    // The call to skip_child is meant to skip over the value corresponding to the key.
35336
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
35337
    SIMDJSON_TRY( skip_child() ); // Skip the value entirely
35338
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
35339
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
35340
    // then we are in error and we abort.
35341
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
35342
  }
35343
35344
  // If the loop ended, we're out of fields to look at.
35345
  return false;
35346
}
35347
35348
SIMDJSON_PUSH_DISABLE_WARNINGS
35349
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
35350
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
35351
  /**
35352
   * When find_field_unordered_raw is called, we can either be pointing at the
35353
   * first key, pointing outside (at the closing brace) or if a key was matched
35354
   * we can be either pointing right afterthe ':' right before the value (that we need skip),
35355
   * or we may have consumed the value and we might be at a comma or at the
35356
   * final brace (ready for a call to has_next_field()).
35357
   */
35358
  error_code error;
35359
  bool has_value;
35360
35361
  // First, we scan from that point to the end.
35362
  // If we don't find a match, we may loop back around, and scan from the beginning to that point.
35363
  token_position search_start = _json_iter->position();
35364
35365
  // We want to know whether we need to go back to the beginning.
35366
  bool at_first = at_first_field();
35367
  ///////////////
35368
  // Initially, the object can be in one of a few different places:
35369
  //
35370
  // 1. At the first key:
35371
  //
35372
  //    ```
35373
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35374
  //      ^ (depth 2, index 1)
35375
  //    ```
35376
  //
35377
  if (at_first) {
35378
    has_value = true;
35379
35380
  // 2. When a previous search did not yield a value or the object is empty:
35381
  //
35382
  //    ```
35383
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35384
  //                                     ^ (depth 0)
35385
  //    { }
35386
  //        ^ (depth 0, index 2)
35387
  //    ```
35388
  //
35389
  } else if (!is_open()) {
35390
35391
#if SIMDJSON_DEVELOPMENT_CHECKS
35392
    // If we're past the end of the object, we're being iterated out of order.
35393
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
35394
    // this object iterator will blithely scan that object for fields.
35395
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
35396
#endif
35397
    SIMDJSON_TRY(reset_object().get(has_value));
35398
    at_first = true;
35399
  // 3. When a previous search found a field or an iterator yielded a value:
35400
  //
35401
  //    ```
35402
  //    // When a field was not fully consumed (or not even touched at all)
35403
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35404
  //           ^ (depth 2)
35405
  //    // When a field was fully consumed
35406
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35407
  //                   ^ (depth 1)
35408
  //    // When the last field was fully consumed
35409
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35410
  //                                   ^ (depth 1)
35411
  //    ```
35412
  //
35413
  } else {
35414
    // If someone queried a key but they not did access the value, then we are left pointing
35415
    // at the ':' and we need to move forward through the value... If the value was
35416
    // processed then skip_child() does not move the iterator (but may adjust the depth).
35417
    if ((error = skip_child() )) { abandon(); return error; }
35418
    search_start = _json_iter->position();
35419
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
35420
#if SIMDJSON_DEVELOPMENT_CHECKS
35421
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
35422
#endif
35423
  }
35424
35425
  // After initial processing, we will be in one of two states:
35426
  //
35427
  // ```
35428
  // // At the beginning of a field
35429
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35430
  //   ^ (depth 1)
35431
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35432
  //                  ^ (depth 1)
35433
  // // At the end of the object
35434
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
35435
  //                                  ^ (depth 0)
35436
  // ```
35437
  //
35438
  // Next, we find a match starting from the current position.
35439
  while (has_value) {
35440
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
35441
35442
    // Get the key and colon, stopping at the value.
35443
    raw_json_string actual_key;
35444
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
35445
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
35446
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
35447
    // The depth is left unchanged by field_key().
35448
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
35449
    // field_value() will advance and check that we find a ':' separating the
35450
    // key and the value. It will also increment the depth by one.
35451
    if ((error = field_value() )) { abandon(); return error; }
35452
35453
    // If it matches, stop and return
35454
    // We could do it this way if we wanted to allow arbitrary
35455
    // key content (including escaped quotes).
35456
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
35457
    // Instead we do the following which may trigger buffer overruns if the
35458
    // user provides an adversarial key (containing a well placed unescaped quote
35459
    // character and being longer than the number of bytes remaining in the JSON
35460
    // input).
35461
    if (actual_key.unsafe_is_equal(key)) {
35462
      logger::log_event(*this, "match", key, -2);
35463
      // If we return here, then we return while pointing at the ':' that we just checked.
35464
      return true;
35465
    }
35466
35467
    // No match: skip the value and see if , or } is next
35468
    logger::log_event(*this, "no match", key, -2);
35469
    // The call to skip_child is meant to skip over the value corresponding to the key.
35470
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
35471
    SIMDJSON_TRY( skip_child() );
35472
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
35473
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
35474
    // then we are in error and we abort.
35475
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
35476
  }
35477
  // Performance note: it maybe wasteful to rewind to the beginning when there might be
35478
  // no other query following. Indeed, it would require reskipping the whole object.
35479
  // Instead, you can just stay where you are. If there is a new query, there is always time
35480
  // to rewind.
35481
  if(at_first) { return false; }
35482
35483
  // If we reach the end without finding a match, search the rest of the fields starting at the
35484
  // beginning of the object.
35485
  // (We have already run through the object before, so we've already validated its structure. We
35486
  // don't check errors in this bit.)
35487
  SIMDJSON_TRY(reset_object().get(has_value));
35488
  while (true) {
35489
    SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
35490
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
35491
35492
    // Get the key and colon, stopping at the value.
35493
    raw_json_string actual_key;
35494
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
35495
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
35496
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
35497
    // The depth is left unchanged by field_key().
35498
    error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
35499
    // field_value() will advance and check that we find a ':' separating the
35500
    // key and the value.  It will also increment the depth by one.
35501
    error = field_value(); SIMDJSON_ASSUME(!error);
35502
35503
    // If it matches, stop and return
35504
    // We could do it this way if we wanted to allow arbitrary
35505
    // key content (including escaped quotes).
35506
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
35507
    // Instead we do the following which may trigger buffer overruns if the
35508
    // user provides an adversarial key (containing a well placed unescaped quote
35509
    // character and being longer than the number of bytes remaining in the JSON
35510
    // input).
35511
    if (actual_key.unsafe_is_equal(key)) {
35512
      logger::log_event(*this, "match", key, -2);
35513
      // If we return here, then we return while pointing at the ':' that we just checked.
35514
      return true;
35515
    }
35516
35517
    // No match: skip the value and see if , or } is next
35518
    logger::log_event(*this, "no match", key, -2);
35519
    // The call to skip_child is meant to skip over the value corresponding to the key.
35520
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
35521
    SIMDJSON_TRY( skip_child() );
35522
    // If we reached the end of the key-value pair we started from, then we know
35523
    // that the key is not there so we return false. We are either right before
35524
    // the next comma or the final brace.
35525
    if(_json_iter->position() == search_start) { return false; }
35526
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
35527
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
35528
    // then we are in error and we abort.
35529
    error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
35530
    // If we make the mistake of exiting here, then we could be left pointing at a key
35531
    // in the middle of an object. That's not an allowable state.
35532
  }
35533
  // If the loop ended, we're out of fields to look at. The program should
35534
  // never reach this point.
35535
  return false;
35536
}
35537
SIMDJSON_POP_DISABLE_WARNINGS
35538
35539
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
35540
  assert_at_next();
35541
35542
  const uint8_t *key = _json_iter->return_current_and_advance();
35543
  if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
35544
  return raw_json_string(key);
35545
}
35546
35547
simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
35548
  assert_at_next();
35549
35550
  if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
35551
  _json_iter->descend_to(depth()+1);
35552
  return SUCCESS;
35553
}
35554
35555
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
35556
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
35557
  return started_array();
35558
}
35559
35560
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
35561
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
35562
  return started_root_array();
35563
}
35564
35565
inline std::string value_iterator::to_string() const noexcept {
35566
  auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
35567
  if(_json_iter != nullptr) { answer +=  _json_iter->to_string(); }
35568
  answer += std::string(" ]");
35569
  return answer;
35570
}
35571
35572
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
35573
  assert_at_container_start();
35574
  if (*_json_iter->peek() == ']') {
35575
    logger::log_value(*_json_iter, "empty array");
35576
    _json_iter->return_current_and_advance();
35577
    SIMDJSON_TRY( end_container() );
35578
    return false;
35579
  }
35580
  _json_iter->descend_to(depth()+1);
35581
#if SIMDJSON_DEVELOPMENT_CHECKS
35582
  _json_iter->set_start_position(_depth, start_position());
35583
#endif
35584
  return true;
35585
}
35586
35587
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
35588
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
35589
  // current document. It only works in the normal mode where we have indexed a single document.
35590
  // Note that adding a check for 'streaming' is not expensive since we only have at most
35591
  // one root element.
35592
  if ( ! _json_iter->streaming() ) {
35593
    // The following lines do not fully protect against garbage content within the
35594
    // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
35595
    // also call `at_end()` on the document instance at the end of the processing to
35596
    // ensure that the processing has finished at the end.
35597
    //
35598
    if (*_json_iter->peek_last() != ']') {
35599
      _json_iter->abandon();
35600
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
35601
    }
35602
    // If the last character is ] *and* the first gibberish character is also ']'
35603
    // then on-demand could accidentally go over. So we need additional checks.
35604
    // https://github.com/simdjson/simdjson/issues/1834
35605
    // Checking that the document is balanced requires a full scan which is potentially
35606
    // expensive, but it only happens in edge cases where the first padding character is
35607
    // a closing bracket.
35608
    if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
35609
      _json_iter->abandon();
35610
      // The exact error would require more work. It will typically be an unclosed array.
35611
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
35612
    }
35613
  }
35614
  return SUCCESS;
35615
}
35616
35617
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
35618
  auto error = check_root_array();
35619
  if (error) { return error; }
35620
  return started_array();
35621
}
35622
35623
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
35624
  assert_at_next();
35625
35626
  logger::log_event(*this, "has_next_element");
35627
  switch (*_json_iter->return_current_and_advance()) {
35628
    case ']':
35629
      logger::log_end_value(*_json_iter, "array");
35630
      SIMDJSON_TRY( end_container() );
35631
      return false;
35632
    case ',':
35633
      _json_iter->descend_to(depth()+1);
35634
      return true;
35635
    default:
35636
      return report_error(TAPE_ERROR, "Missing comma between array elements");
35637
  }
35638
}
35639
35640
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
35641
  auto not_true = atomparsing::str4ncmp(json, "true");
35642
  auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
35643
  bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
35644
  if (error) { return incorrect_type_error("Not a boolean"); }
35645
  return simdjson_result<bool>(!not_true);
35646
}
35647
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
35648
  bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
35649
  // if we start with 'n', we must be a null
35650
  if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
35651
  return is_null_string;
35652
}
35653
35654
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
35655
  return get_raw_json_string().unescape(json_iter(), allow_replacement);
35656
}
35657
template <typename string_type>
35658
simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
35659
  std::string_view content;
35660
  auto err = get_string(allow_replacement).get(content);
35661
  if (err) { return err; }
35662
  receiver = content;
35663
  return SUCCESS;
35664
}
35665
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
35666
  return get_raw_json_string().unescape_wobbly(json_iter());
35667
}
35668
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
35669
  auto json = peek_scalar("string");
35670
  if (*json != '"') { return incorrect_type_error("Not a string"); }
35671
  advance_scalar("string");
35672
  return raw_json_string(json+1);
35673
}
35674
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
35675
  auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
35676
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
35677
  return result;
35678
}
35679
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
35680
  auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
35681
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
35682
  return result;
35683
}
35684
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
35685
  auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
35686
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
35687
  return result;
35688
}
35689
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
35690
  auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
35691
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
35692
  return result;
35693
}
35694
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
35695
  auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
35696
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
35697
  return result;
35698
}
35699
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
35700
  auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
35701
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
35702
  return result;
35703
}
35704
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
35705
  auto result = parse_bool(peek_non_root_scalar("bool"));
35706
  if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
35707
  return result;
35708
}
35709
simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
35710
  bool is_null_value;
35711
  SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
35712
  if(is_null_value) { advance_non_root_scalar("null"); }
35713
  return is_null_value;
35714
}
35715
simdjson_inline bool value_iterator::is_negative() noexcept {
35716
  return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
35717
}
35718
simdjson_inline bool value_iterator::is_root_negative() noexcept {
35719
  return numberparsing::is_negative(peek_root_scalar("numbersign"));
35720
}
35721
simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
35722
  return numberparsing::is_integer(peek_non_root_scalar("integer"));
35723
}
35724
simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
35725
  return numberparsing::get_number_type(peek_non_root_scalar("integer"));
35726
}
35727
simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
35728
  number num;
35729
  error_code error =  numberparsing::parse_number(peek_non_root_scalar("number"), num);
35730
  if(error) { return error; }
35731
  return num;
35732
}
35733
35734
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
35735
  auto max_len = peek_root_length();
35736
  auto json = peek_root_scalar("is_root_integer");
35737
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
35738
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
35739
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
35740
    return false; // if there are more than 20 characters, it cannot be represented as an integer.
35741
  }
35742
  auto answer = numberparsing::is_integer(tmpbuf);
35743
  // If the parsing was a success, we must still check that it is
35744
  // a single scalar. Note that we parse first because of cases like '[]' where
35745
  // getting TRAILING_CONTENT is wrong.
35746
  if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
35747
  return answer;
35748
}
35749
35750
simdjson_inline simdjson_result<arm64::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
35751
  auto max_len = peek_root_length();
35752
  auto json = peek_root_scalar("number");
35753
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
35754
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
35755
  // number: -0.<fraction>e-308.
35756
  uint8_t tmpbuf[1074+8+1+1];
35757
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
35758
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
35759
    if(numberparsing::check_if_integer(json, max_len)) {
35760
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35761
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
35762
      return number_type::big_integer;
35763
    }
35764
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
35765
    return NUMBER_ERROR;
35766
  }
35767
  auto answer = numberparsing::get_number_type(tmpbuf);
35768
  if (check_trailing && (answer.error() == SUCCESS)  && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35769
  return answer;
35770
}
35771
simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
35772
  auto max_len = peek_root_length();
35773
  auto json = peek_root_scalar("number");
35774
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
35775
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
35776
  // number: -0.<fraction>e-308.
35777
  // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
35778
  uint8_t tmpbuf[1074+8+1+1];
35779
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
35780
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
35781
    if(numberparsing::check_if_integer(json, max_len)) {
35782
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35783
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
35784
      return BIGINT_ERROR;
35785
    }
35786
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
35787
    return NUMBER_ERROR;
35788
  }
35789
  number num;
35790
  error_code error =  numberparsing::parse_number(tmpbuf, num);
35791
  if(error) { return error; }
35792
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35793
  advance_root_scalar("number");
35794
  return num;
35795
}
35796
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
35797
  return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
35798
}
35799
template <typename string_type>
35800
simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
35801
  std::string_view content;
35802
  auto err = get_root_string(check_trailing, allow_replacement).get(content);
35803
  if (err) { return err; }
35804
  receiver = content;
35805
  return SUCCESS;
35806
}
35807
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
35808
  return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
35809
}
35810
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
35811
  auto json = peek_scalar("string");
35812
  if (*json != '"') { return incorrect_type_error("Not a string"); }
35813
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35814
  advance_scalar("string");
35815
  return raw_json_string(json+1);
35816
}
35817
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
35818
  auto max_len = peek_root_length();
35819
  auto json = peek_root_scalar("uint64");
35820
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
35821
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
35822
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
35823
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
35824
    return NUMBER_ERROR;
35825
  }
35826
  auto result = numberparsing::parse_unsigned(tmpbuf);
35827
  if(result.error() == SUCCESS) {
35828
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35829
    advance_root_scalar("uint64");
35830
  }
35831
  return result;
35832
}
35833
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
35834
  auto max_len = peek_root_length();
35835
  auto json = peek_root_scalar("uint64");
35836
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
35837
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
35838
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
35839
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
35840
    return NUMBER_ERROR;
35841
  }
35842
  auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
35843
  if(result.error() == SUCCESS) {
35844
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35845
    advance_root_scalar("uint64");
35846
  }
35847
  return result;
35848
}
35849
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
35850
  auto max_len = peek_root_length();
35851
  auto json = peek_root_scalar("int64");
35852
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
35853
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
35854
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
35855
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
35856
    return NUMBER_ERROR;
35857
  }
35858
35859
  auto result = numberparsing::parse_integer(tmpbuf);
35860
  if(result.error() == SUCCESS) {
35861
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35862
    advance_root_scalar("int64");
35863
  }
35864
  return result;
35865
}
35866
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
35867
  auto max_len = peek_root_length();
35868
  auto json = peek_root_scalar("int64");
35869
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
35870
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
35871
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
35872
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
35873
    return NUMBER_ERROR;
35874
  }
35875
35876
  auto result = numberparsing::parse_integer_in_string(tmpbuf);
35877
  if(result.error() == SUCCESS) {
35878
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35879
    advance_root_scalar("int64");
35880
  }
35881
  return result;
35882
}
35883
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
35884
  auto max_len = peek_root_length();
35885
  auto json = peek_root_scalar("double");
35886
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
35887
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
35888
  // number: -0.<fraction>e-308.
35889
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
35890
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
35891
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
35892
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
35893
    return NUMBER_ERROR;
35894
  }
35895
  auto result = numberparsing::parse_double(tmpbuf);
35896
  if(result.error() == SUCCESS) {
35897
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35898
    advance_root_scalar("double");
35899
  }
35900
  return result;
35901
}
35902
35903
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
35904
  auto max_len = peek_root_length();
35905
  auto json = peek_root_scalar("double");
35906
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
35907
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
35908
  // number: -0.<fraction>e-308.
35909
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
35910
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
35911
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
35912
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
35913
    return NUMBER_ERROR;
35914
  }
35915
  auto result = numberparsing::parse_double_in_string(tmpbuf);
35916
  if(result.error() == SUCCESS) {
35917
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35918
    advance_root_scalar("double");
35919
  }
35920
  return result;
35921
}
35922
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
35923
  auto max_len = peek_root_length();
35924
  auto json = peek_root_scalar("bool");
35925
  uint8_t tmpbuf[5+1+1]; // +1 for null termination
35926
  tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
35927
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
35928
  auto result = parse_bool(tmpbuf);
35929
  if(result.error() == SUCCESS) {
35930
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35931
    advance_root_scalar("bool");
35932
  }
35933
  return result;
35934
}
35935
simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
35936
  auto max_len = peek_root_length();
35937
  auto json = peek_root_scalar("null");
35938
  bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
35939
         (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
35940
  if(result) { // we have something that looks like a null.
35941
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
35942
    advance_root_scalar("null");
35943
  }
35944
  return result;
35945
}
35946
35947
simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
35948
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
35949
  SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
35950
35951
  return _json_iter->skip_child(depth());
35952
}
35953
35954
simdjson_inline value_iterator value_iterator::child() const noexcept {
35955
  assert_at_child();
35956
  return { _json_iter, depth()+1, _json_iter->token.position() };
35957
}
35958
35959
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
35960
// relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
35961
// marked non-inline.
35962
SIMDJSON_PUSH_DISABLE_WARNINGS
35963
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
35964
simdjson_inline bool value_iterator::is_open() const noexcept {
35965
  return _json_iter->depth() >= depth();
35966
}
35967
SIMDJSON_POP_DISABLE_WARNINGS
35968
35969
simdjson_inline bool value_iterator::at_end() const noexcept {
35970
  return _json_iter->at_end();
35971
}
35972
35973
simdjson_inline bool value_iterator::at_start() const noexcept {
35974
  return _json_iter->token.position() == start_position();
35975
}
35976
35977
simdjson_inline bool value_iterator::at_first_field() const noexcept {
35978
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
35979
  return _json_iter->token.position() == start_position() + 1;
35980
}
35981
35982
simdjson_inline void value_iterator::abandon() noexcept {
35983
  _json_iter->abandon();
35984
}
35985
35986
simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
35987
  return _depth;
35988
}
35989
simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
35990
  return _json_iter->error;
35991
}
35992
simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
35993
  return _json_iter->string_buf_loc();
35994
}
35995
simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
35996
  return *_json_iter;
35997
}
35998
simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
35999
  return *_json_iter;
36000
}
36001
36002
simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
36003
  return _json_iter->peek(start_position());
36004
}
36005
simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
36006
  return _json_iter->peek_length(start_position());
36007
}
36008
simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
36009
  return _json_iter->peek_root_length(start_position());
36010
}
36011
36012
simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
36013
  logger::log_value(*_json_iter, start_position(), depth(), type);
36014
  // If we're not at the position anymore, we don't want to advance the cursor.
36015
  if (!is_at_start()) { return peek_start(); }
36016
36017
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
36018
  assert_at_start();
36019
  return _json_iter->peek();
36020
}
36021
36022
simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
36023
  logger::log_value(*_json_iter, start_position(), depth(), type);
36024
  // If we're not at the position anymore, we don't want to advance the cursor.
36025
  if (!is_at_start()) { return; }
36026
36027
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
36028
  assert_at_start();
36029
  _json_iter->return_current_and_advance();
36030
  _json_iter->ascend_to(depth()-1);
36031
}
36032
36033
simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
36034
  logger::log_start_value(*_json_iter, start_position(), depth(), type);
36035
  // If we're not at the position anymore, we don't want to advance the cursor.
36036
  const uint8_t *json;
36037
  if (!is_at_start()) {
36038
#if SIMDJSON_DEVELOPMENT_CHECKS
36039
    if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
36040
#endif
36041
    json = peek_start();
36042
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
36043
  } else {
36044
    assert_at_start();
36045
    /**
36046
     * We should be prudent. Let us peek. If it is not the right type, we
36047
     * return an error. Only once we have determined that we have the right
36048
     * type are we allowed to advance!
36049
     */
36050
    json = _json_iter->peek();
36051
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
36052
    _json_iter->return_current_and_advance();
36053
  }
36054
36055
36056
  return SUCCESS;
36057
}
36058
36059
36060
simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
36061
  logger::log_value(*_json_iter, start_position(), depth(), type);
36062
  if (!is_at_start()) { return peek_start(); }
36063
36064
  assert_at_root();
36065
  return _json_iter->peek();
36066
}
36067
simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
36068
  logger::log_value(*_json_iter, start_position(), depth(), type);
36069
  if (!is_at_start()) { return peek_start(); }
36070
36071
  assert_at_non_root_start();
36072
  return _json_iter->peek();
36073
}
36074
36075
simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
36076
  logger::log_value(*_json_iter, start_position(), depth(), type);
36077
  if (!is_at_start()) { return; }
36078
36079
  assert_at_root();
36080
  _json_iter->return_current_and_advance();
36081
  _json_iter->ascend_to(depth()-1);
36082
}
36083
simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
36084
  logger::log_value(*_json_iter, start_position(), depth(), type);
36085
  if (!is_at_start()) { return; }
36086
36087
  assert_at_non_root_start();
36088
  _json_iter->return_current_and_advance();
36089
  _json_iter->ascend_to(depth()-1);
36090
}
36091
36092
simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
36093
  logger::log_error(*_json_iter, start_position(), depth(), message);
36094
  return INCORRECT_TYPE;
36095
}
36096
36097
simdjson_inline bool value_iterator::is_at_start() const noexcept {
36098
  return position() == start_position();
36099
}
36100
36101
simdjson_inline bool value_iterator::is_at_key() const noexcept {
36102
  // Keys are at the same depth as the object.
36103
  // Note here that we could be safer and check that we are within an object,
36104
  // but we do not.
36105
  return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
36106
}
36107
36108
simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
36109
  // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
36110
  auto delta = position() - start_position();
36111
  return delta == 1 || delta == 2;
36112
}
36113
36114
inline void value_iterator::assert_at_start() const noexcept {
36115
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
36116
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
36117
  SIMDJSON_ASSUME( _depth > 0 );
36118
}
36119
36120
inline void value_iterator::assert_at_container_start() const noexcept {
36121
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
36122
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
36123
  SIMDJSON_ASSUME( _depth > 0 );
36124
}
36125
36126
inline void value_iterator::assert_at_next() const noexcept {
36127
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
36128
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
36129
  SIMDJSON_ASSUME( _depth > 0 );
36130
}
36131
36132
simdjson_inline void value_iterator::move_at_start() noexcept {
36133
  _json_iter->_depth = _depth;
36134
  _json_iter->token.set_position(_start_position);
36135
}
36136
36137
simdjson_inline void value_iterator::move_at_container_start() noexcept {
36138
  _json_iter->_depth = _depth;
36139
  _json_iter->token.set_position(_start_position + 1);
36140
}
36141
36142
simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
36143
  if(error()) { return error(); }
36144
  move_at_container_start();
36145
  return started_array();
36146
}
36147
36148
simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
36149
  if(error()) { return error(); }
36150
  move_at_container_start();
36151
  return started_object();
36152
}
36153
36154
inline void value_iterator::assert_at_child() const noexcept {
36155
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
36156
  SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
36157
  SIMDJSON_ASSUME( _depth > 0 );
36158
}
36159
36160
inline void value_iterator::assert_at_root() const noexcept {
36161
  assert_at_start();
36162
  SIMDJSON_ASSUME( _depth == 1 );
36163
}
36164
36165
inline void value_iterator::assert_at_non_root_start() const noexcept {
36166
  assert_at_start();
36167
  SIMDJSON_ASSUME( _depth > 1 );
36168
}
36169
36170
inline void value_iterator::assert_is_valid() const noexcept {
36171
  SIMDJSON_ASSUME( _json_iter != nullptr );
36172
}
36173
36174
simdjson_inline bool value_iterator::is_valid() const noexcept {
36175
  return _json_iter != nullptr;
36176
}
36177
36178
simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
36179
  switch (*peek_start()) {
36180
    case '{':
36181
      return json_type::object;
36182
    case '[':
36183
      return json_type::array;
36184
    case '"':
36185
      return json_type::string;
36186
    case 'n':
36187
      return json_type::null;
36188
    case 't': case 'f':
36189
      return json_type::boolean;
36190
    case '-':
36191
    case '0': case '1': case '2': case '3': case '4':
36192
    case '5': case '6': case '7': case '8': case '9':
36193
      return json_type::number;
36194
    default:
36195
      return TAPE_ERROR;
36196
  }
36197
}
36198
36199
simdjson_inline token_position value_iterator::start_position() const noexcept {
36200
  return _start_position;
36201
}
36202
36203
simdjson_inline token_position value_iterator::position() const noexcept {
36204
  return _json_iter->position();
36205
}
36206
36207
simdjson_inline token_position value_iterator::end_position() const noexcept {
36208
  return _json_iter->end_position();
36209
}
36210
36211
simdjson_inline token_position value_iterator::last_position() const noexcept {
36212
  return _json_iter->last_position();
36213
}
36214
36215
simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
36216
  return _json_iter->report_error(error, message);
36217
}
36218
36219
} // namespace ondemand
36220
} // namespace arm64
36221
} // namespace simdjson
36222
36223
namespace simdjson {
36224
36225
simdjson_inline simdjson_result<arm64::ondemand::value_iterator>::simdjson_result(arm64::ondemand::value_iterator &&value) noexcept
36226
    : implementation_simdjson_result_base<arm64::ondemand::value_iterator>(std::forward<arm64::ondemand::value_iterator>(value)) {}
36227
simdjson_inline simdjson_result<arm64::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
36228
    : implementation_simdjson_result_base<arm64::ondemand::value_iterator>(error) {}
36229
36230
} // namespace simdjson
36231
36232
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
36233
/* end file simdjson/generic/ondemand/value_iterator-inl.h for arm64 */
36234
/* end file simdjson/generic/ondemand/amalgamated.h for arm64 */
36235
/* including simdjson/arm64/end.h: #include "simdjson/arm64/end.h" */
36236
/* begin file simdjson/arm64/end.h */
36237
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
36238
/* amalgamation skipped (editor-only): #include "simdjson/arm64/base.h" */
36239
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
36240
36241
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
36242
/* undefining SIMDJSON_IMPLEMENTATION from "arm64" */
36243
#undef SIMDJSON_IMPLEMENTATION
36244
/* end file simdjson/arm64/end.h */
36245
36246
#endif // SIMDJSON_ARM64_ONDEMAND_H
36247
/* end file simdjson/arm64/ondemand.h */
36248
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
36249
/* including simdjson/fallback/ondemand.h: #include "simdjson/fallback/ondemand.h" */
36250
/* begin file simdjson/fallback/ondemand.h */
36251
#ifndef SIMDJSON_FALLBACK_ONDEMAND_H
36252
#define SIMDJSON_FALLBACK_ONDEMAND_H
36253
36254
/* including simdjson/fallback/begin.h: #include "simdjson/fallback/begin.h" */
36255
/* begin file simdjson/fallback/begin.h */
36256
/* defining SIMDJSON_IMPLEMENTATION to "fallback" */
36257
#define SIMDJSON_IMPLEMENTATION fallback
36258
/* including simdjson/fallback/base.h: #include "simdjson/fallback/base.h" */
36259
/* begin file simdjson/fallback/base.h */
36260
#ifndef SIMDJSON_FALLBACK_BASE_H
36261
#define SIMDJSON_FALLBACK_BASE_H
36262
36263
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
36264
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
36265
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
36266
36267
namespace simdjson {
36268
/**
36269
 * Fallback implementation (runs on any machine).
36270
 */
36271
namespace fallback {
36272
36273
class implementation;
36274
36275
} // namespace fallback
36276
} // namespace simdjson
36277
36278
#endif // SIMDJSON_FALLBACK_BASE_H
36279
/* end file simdjson/fallback/base.h */
36280
/* including simdjson/fallback/bitmanipulation.h: #include "simdjson/fallback/bitmanipulation.h" */
36281
/* begin file simdjson/fallback/bitmanipulation.h */
36282
#ifndef SIMDJSON_FALLBACK_BITMANIPULATION_H
36283
#define SIMDJSON_FALLBACK_BITMANIPULATION_H
36284
36285
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
36286
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
36287
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
36288
36289
namespace simdjson {
36290
namespace fallback {
36291
namespace {
36292
36293
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
36294
static inline unsigned char _BitScanForward64(unsigned long* ret, uint64_t x) {
36295
  unsigned long x0 = (unsigned long)x, top, bottom;
36296
  _BitScanForward(&top, (unsigned long)(x >> 32));
36297
  _BitScanForward(&bottom, x0);
36298
  *ret = x0 ? bottom : 32 + top;
36299
  return x != 0;
36300
}
36301
static unsigned char _BitScanReverse64(unsigned long* ret, uint64_t x) {
36302
  unsigned long x1 = (unsigned long)(x >> 32), top, bottom;
36303
  _BitScanReverse(&top, x1);
36304
  _BitScanReverse(&bottom, (unsigned long)x);
36305
  *ret = x1 ? top + 32 : bottom;
36306
  return x != 0;
36307
}
36308
#endif
36309
36310
/* result might be undefined when input_num is zero */
36311
simdjson_inline int leading_zeroes(uint64_t input_num) {
36312
#ifdef _MSC_VER
36313
  unsigned long leading_zero = 0;
36314
  // Search the mask data from most significant bit (MSB)
36315
  // to least significant bit (LSB) for a set bit (1).
36316
  if (_BitScanReverse64(&leading_zero, input_num))
36317
    return (int)(63 - leading_zero);
36318
  else
36319
    return 64;
36320
#else
36321
  return __builtin_clzll(input_num);
36322
#endif// _MSC_VER
36323
}
36324
36325
} // unnamed namespace
36326
} // namespace fallback
36327
} // namespace simdjson
36328
36329
#endif // SIMDJSON_FALLBACK_BITMANIPULATION_H
36330
/* end file simdjson/fallback/bitmanipulation.h */
36331
/* including simdjson/fallback/stringparsing_defs.h: #include "simdjson/fallback/stringparsing_defs.h" */
36332
/* begin file simdjson/fallback/stringparsing_defs.h */
36333
#ifndef SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
36334
#define SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
36335
36336
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
36337
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
36338
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
36339
36340
namespace simdjson {
36341
namespace fallback {
36342
namespace {
36343
36344
// Holds backslashes and quotes locations.
36345
struct backslash_and_quote {
36346
public:
36347
  static constexpr uint32_t BYTES_PROCESSED = 1;
36348
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
36349
36350
  simdjson_inline bool has_quote_first() { return c == '"'; }
36351
  simdjson_inline bool has_backslash() { return c == '\\'; }
36352
  simdjson_inline int quote_index() { return c == '"' ? 0 : 1; }
36353
  simdjson_inline int backslash_index() { return c == '\\' ? 0 : 1; }
36354
36355
  uint8_t c;
36356
}; // struct backslash_and_quote
36357
36358
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
36359
  // store to dest unconditionally - we can overwrite the bits we don't like later
36360
  dst[0] = src[0];
36361
  return { src[0] };
36362
}
36363
36364
} // unnamed namespace
36365
} // namespace fallback
36366
} // namespace simdjson
36367
36368
#endif // SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
36369
/* end file simdjson/fallback/stringparsing_defs.h */
36370
/* including simdjson/fallback/numberparsing_defs.h: #include "simdjson/fallback/numberparsing_defs.h" */
36371
/* begin file simdjson/fallback/numberparsing_defs.h */
36372
#ifndef SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
36373
#define SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
36374
36375
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
36376
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
36377
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
36378
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
36379
36380
#include <cstring>
36381
36382
#ifdef JSON_TEST_NUMBERS // for unit testing
36383
void found_invalid_number(const uint8_t *buf);
36384
void found_integer(int64_t result, const uint8_t *buf);
36385
void found_unsigned_integer(uint64_t result, const uint8_t *buf);
36386
void found_float(double result, const uint8_t *buf);
36387
#endif
36388
36389
namespace simdjson {
36390
namespace fallback {
36391
namespace numberparsing {
36392
36393
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
36394
/** @private */
36395
static simdjson_inline uint32_t parse_eight_digits_unrolled(const char *chars) {
36396
  uint64_t val;
36397
  memcpy(&val, chars, sizeof(uint64_t));
36398
  val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
36399
  val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
36400
  return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
36401
}
36402
36403
/** @private */
36404
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
36405
  return parse_eight_digits_unrolled(reinterpret_cast<const char *>(chars));
36406
}
36407
36408
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
36409
// this is a slow emulation routine for 32-bit
36410
//
36411
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
36412
  return x * (uint64_t)y;
36413
}
36414
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
36415
  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
36416
  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
36417
  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
36418
  uint64_t adbc_carry = !!(adbc < ad);
36419
  uint64_t lo = bd + (adbc << 32);
36420
  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
36421
        (adbc_carry << 32) + !!(lo < bd);
36422
  return lo;
36423
}
36424
#endif
36425
36426
/** @private */
36427
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
36428
  internal::value128 answer;
36429
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
36430
#ifdef _M_ARM64
36431
  // ARM64 has native support for 64-bit multiplications, no need to emultate
36432
  answer.high = __umulh(value1, value2);
36433
  answer.low = value1 * value2;
36434
#else
36435
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
36436
#endif // _M_ARM64
36437
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
36438
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
36439
  answer.low = uint64_t(r);
36440
  answer.high = uint64_t(r >> 64);
36441
#endif
36442
  return answer;
36443
}
36444
36445
} // namespace numberparsing
36446
} // namespace fallback
36447
} // namespace simdjson
36448
36449
#define SIMDJSON_SWAR_NUMBER_PARSING 1
36450
36451
#endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
36452
/* end file simdjson/fallback/numberparsing_defs.h */
36453
/* end file simdjson/fallback/begin.h */
36454
/* including simdjson/generic/ondemand/amalgamated.h for fallback: #include "simdjson/generic/ondemand/amalgamated.h" */
36455
/* begin file simdjson/generic/ondemand/amalgamated.h for fallback */
36456
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
36457
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
36458
#endif
36459
36460
// Stuff other things depend on
36461
/* including simdjson/generic/ondemand/base.h for fallback: #include "simdjson/generic/ondemand/base.h" */
36462
/* begin file simdjson/generic/ondemand/base.h for fallback */
36463
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
36464
36465
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
36466
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_BASE_H */
36467
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
36468
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
36469
36470
namespace simdjson {
36471
namespace fallback {
36472
/**
36473
 * A fast, simple, DOM-like interface that parses JSON as you use it.
36474
 *
36475
 * Designed for maximum speed and a lower memory profile.
36476
 */
36477
namespace ondemand {
36478
36479
/** Represents the depth of a JSON value (number of nested arrays/objects). */
36480
using depth_t = int32_t;
36481
36482
/** @copydoc simdjson::fallback::number_type */
36483
using number_type = simdjson::fallback::number_type;
36484
36485
/** @private Position in the JSON buffer indexes */
36486
using token_position = const uint32_t *;
36487
36488
class array;
36489
class array_iterator;
36490
class document;
36491
class document_reference;
36492
class document_stream;
36493
class field;
36494
class json_iterator;
36495
enum class json_type;
36496
struct number;
36497
class object;
36498
class object_iterator;
36499
class parser;
36500
class raw_json_string;
36501
class token_iterator;
36502
class value;
36503
class value_iterator;
36504
36505
} // namespace ondemand
36506
} // namespace fallback
36507
} // namespace simdjson
36508
36509
#endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H
36510
/* end file simdjson/generic/ondemand/base.h for fallback */
36511
/* including simdjson/generic/ondemand/value_iterator.h for fallback: #include "simdjson/generic/ondemand/value_iterator.h" */
36512
/* begin file simdjson/generic/ondemand/value_iterator.h for fallback */
36513
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
36514
36515
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
36516
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H */
36517
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
36518
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
36519
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
36520
36521
namespace simdjson {
36522
namespace fallback {
36523
namespace ondemand {
36524
36525
/**
36526
 * Iterates through a single JSON value at a particular depth.
36527
 *
36528
 * Does not keep track of the type of value: provides methods for objects, arrays and scalars and expects
36529
 * the caller to call the right ones.
36530
 *
36531
 * @private This is not intended for external use.
36532
 */
36533
class value_iterator {
36534
protected:
36535
  /** The underlying JSON iterator */
36536
  json_iterator *_json_iter{};
36537
  /** The depth of this value */
36538
  depth_t _depth{};
36539
  /**
36540
   * The starting token index for this value
36541
   */
36542
  token_position _start_position{};
36543
36544
public:
36545
0
  simdjson_inline value_iterator() noexcept = default;
36546
36547
  /**
36548
   * Denote that we're starting a document.
36549
   */
36550
  simdjson_inline void start_document() noexcept;
36551
36552
  /**
36553
   * Skips a non-iterated or partially-iterated JSON value, whether it is a scalar, array or object.
36554
   *
36555
   * Optimized for scalars.
36556
   */
36557
  simdjson_warn_unused simdjson_inline error_code skip_child() noexcept;
36558
36559
  /**
36560
   * Tell whether the iterator is at the EOF mark
36561
   */
36562
  simdjson_inline bool at_end() const noexcept;
36563
36564
  /**
36565
   * Tell whether the iterator is at the start of the value
36566
   */
36567
  simdjson_inline bool at_start() const noexcept;
36568
36569
  /**
36570
   * Tell whether the value is open--if the value has not been used, or the array/object is still open.
36571
   */
36572
  simdjson_inline bool is_open() const noexcept;
36573
36574
  /**
36575
   * Tell whether the value is at an object's first field (just after the {).
36576
   */
36577
  simdjson_inline bool at_first_field() const noexcept;
36578
36579
  /**
36580
   * Abandon all iteration.
36581
   */
36582
  simdjson_inline void abandon() noexcept;
36583
36584
  /**
36585
   * Get the child value as a value_iterator.
36586
   */
36587
  simdjson_inline value_iterator child_value() const noexcept;
36588
36589
  /**
36590
   * Get the depth of this value.
36591
   */
36592
  simdjson_inline int32_t depth() const noexcept;
36593
36594
  /**
36595
   * Get the JSON type of this value.
36596
   *
36597
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
36598
   */
36599
  simdjson_inline simdjson_result<json_type> type() const noexcept;
36600
36601
  /**
36602
   * @addtogroup object Object iteration
36603
   *
36604
   * Methods to iterate and find object fields. These methods generally *assume* the value is
36605
   * actually an object; the caller is responsible for keeping track of that fact.
36606
   *
36607
   * @{
36608
   */
36609
36610
  /**
36611
   * Start an object iteration.
36612
   *
36613
   * @returns Whether the object had any fields (returns false for empty).
36614
   * @error INCORRECT_TYPE if there is no opening {
36615
   */
36616
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_object() noexcept;
36617
  /**
36618
   * Start an object iteration from the root.
36619
   *
36620
   * @returns Whether the object had any fields (returns false for empty).
36621
   * @error INCORRECT_TYPE if there is no opening {
36622
   * @error TAPE_ERROR if there is no matching } at end of document
36623
   */
36624
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_object() noexcept;
36625
  /**
36626
   * Checks whether an object could be started from the root. May be called by start_root_object.
36627
   *
36628
   * @returns SUCCESS if it is possible to safely start an object from the root (document level).
36629
   * @error INCORRECT_TYPE if there is no opening {
36630
   * @error TAPE_ERROR if there is no matching } at end of document
36631
   */
36632
  simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept;
36633
  /**
36634
   * Start an object iteration after the user has already checked and moved past the {.
36635
   *
36636
   * Does not move the iterator unless the object is empty ({}).
36637
   *
36638
   * @returns Whether the object had any fields (returns false for empty).
36639
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
36640
   *        array or object is incomplete).
36641
   */
36642
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_object() noexcept;
36643
  /**
36644
   * Start an object iteration from the root, after the user has already checked and moved past the {.
36645
   *
36646
   * Does not move the iterator unless the object is empty ({}).
36647
   *
36648
   * @returns Whether the object had any fields (returns false for empty).
36649
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
36650
   *        array or object is incomplete).
36651
   */
36652
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_object() noexcept;
36653
36654
  /**
36655
   * Moves to the next field in an object.
36656
   *
36657
   * Looks for , and }. If } is found, the object is finished and the iterator advances past it.
36658
   * Otherwise, it advances to the next value.
36659
   *
36660
   * @return whether there is another field in the object.
36661
   * @error TAPE_ERROR If there is a comma missing between fields.
36662
   * @error TAPE_ERROR If there is a comma, but not enough tokens remaining to have a key, :, and value.
36663
   */
36664
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_field() noexcept;
36665
36666
  /**
36667
   * Get the current field's key.
36668
   */
36669
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> field_key() noexcept;
36670
36671
  /**
36672
   * Pass the : in the field and move to its value.
36673
   */
36674
  simdjson_warn_unused simdjson_inline error_code field_value() noexcept;
36675
36676
  /**
36677
   * Find the next field with the given key.
36678
   *
36679
   * Assumes you have called next_field() or otherwise matched the previous value.
36680
   *
36681
   * This means the iterator must be sitting at the next key:
36682
   *
36683
   * ```
36684
   * { "a": 1, "b": 2 }
36685
   *           ^
36686
   * ```
36687
   *
36688
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
36689
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
36690
   * fail to match some keys with escapes (\u, \n, etc.).
36691
   */
36692
  simdjson_warn_unused simdjson_inline error_code find_field(const std::string_view key) noexcept;
36693
36694
  /**
36695
   * Find the next field with the given key, *without* unescaping. This assumes object order: it
36696
   * will not find the field if it was already passed when looking for some *other* field.
36697
   *
36698
   * Assumes you have called next_field() or otherwise matched the previous value.
36699
   *
36700
   * This means the iterator must be sitting at the next key:
36701
   *
36702
   * ```
36703
   * { "a": 1, "b": 2 }
36704
   *           ^
36705
   * ```
36706
   *
36707
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
36708
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
36709
   * fail to match some keys with escapes (\u, \n, etc.).
36710
   */
36711
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
36712
36713
  /**
36714
   * Find the field with the given key without regard to order, and *without* unescaping.
36715
   *
36716
   * This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
36717
   *
36718
   * Assumes you have called next_field() or otherwise matched the previous value.
36719
   *
36720
   * This means the iterator must be sitting at the next key:
36721
   *
36722
   * ```
36723
   * { "a": 1, "b": 2 }
36724
   *           ^
36725
   * ```
36726
   *
36727
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
36728
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
36729
   * fail to match some keys with escapes (\u, \n, etc.).
36730
   */
36731
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
36732
36733
  /** @} */
36734
36735
  /**
36736
   * @addtogroup array Array iteration
36737
   * Methods to iterate over array elements. These methods generally *assume* the value is actually
36738
   * an object; the caller is responsible for keeping track of that fact.
36739
   * @{
36740
   */
36741
36742
  /**
36743
   * Check for an opening [ and start an array iteration.
36744
   *
36745
   * @returns Whether the array had any elements (returns false for empty).
36746
   * @error INCORRECT_TYPE If there is no [.
36747
   */
36748
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_array() noexcept;
36749
  /**
36750
   * Check for an opening [ and start an array iteration while at the root.
36751
   *
36752
   * @returns Whether the array had any elements (returns false for empty).
36753
   * @error INCORRECT_TYPE If there is no [.
36754
   * @error TAPE_ERROR if there is no matching ] at end of document
36755
   */
36756
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_array() noexcept;
36757
  /**
36758
   * Checks whether an array could be started from the root. May be called by start_root_array.
36759
   *
36760
   * @returns SUCCESS if it is possible to safely start an array from the root (document level).
36761
   * @error INCORRECT_TYPE If there is no [.
36762
   * @error TAPE_ERROR if there is no matching ] at end of document
36763
   */
36764
  simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept;
36765
  /**
36766
   * Start an array iteration, after the user has already checked and moved past the [.
36767
   *
36768
   * Does not move the iterator unless the array is empty ([]).
36769
   *
36770
   * @returns Whether the array had any elements (returns false for empty).
36771
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
36772
   *        array or object is incomplete).
36773
   */
36774
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_array() noexcept;
36775
  /**
36776
   * Start an array iteration from the root, after the user has already checked and moved past the [.
36777
   *
36778
   * Does not move the iterator unless the array is empty ([]).
36779
   *
36780
   * @returns Whether the array had any elements (returns false for empty).
36781
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
36782
   *        array or object is incomplete).
36783
   */
36784
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_array() noexcept;
36785
36786
  /**
36787
   * Moves to the next element in an array.
36788
   *
36789
   * Looks for , and ]. If ] is found, the array is finished and the iterator advances past it.
36790
   * Otherwise, it advances to the next value.
36791
   *
36792
   * @return Whether there is another element in the array.
36793
   * @error TAPE_ERROR If there is a comma missing between elements.
36794
   */
36795
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_element() noexcept;
36796
36797
  /**
36798
   * Get a child value iterator.
36799
   */
36800
  simdjson_warn_unused simdjson_inline value_iterator child() const noexcept;
36801
36802
  /** @} */
36803
36804
  /**
36805
   * @defgroup scalar Scalar values
36806
   * @addtogroup scalar
36807
   * @{
36808
   */
36809
36810
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
36811
  template <typename string_type>
36812
  simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
36813
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
36814
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
36815
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
36816
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
36817
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
36818
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
36819
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
36820
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
36821
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
36822
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
36823
  simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
36824
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
36825
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
36826
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
36827
36828
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
36829
  template <typename string_type>
36830
  simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
36831
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
36832
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
36833
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
36834
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
36835
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
36836
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
36837
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
36838
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
36839
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
36840
  simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
36841
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
36842
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
36843
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
36844
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
36845
36846
  simdjson_inline error_code error() const noexcept;
36847
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
36848
  simdjson_inline const json_iterator &json_iter() const noexcept;
36849
  simdjson_inline json_iterator &json_iter() noexcept;
36850
36851
  simdjson_inline void assert_is_valid() const noexcept;
36852
  simdjson_inline bool is_valid() const noexcept;
36853
36854
  /** @} */
36855
protected:
36856
  /**
36857
   * Restarts an array iteration.
36858
   * @returns Whether the array has any elements (returns false for empty).
36859
   */
36860
  simdjson_inline simdjson_result<bool> reset_array() noexcept;
36861
  /**
36862
   * Restarts an object iteration.
36863
   * @returns Whether the object has any fields (returns false for empty).
36864
   */
36865
  simdjson_inline simdjson_result<bool> reset_object() noexcept;
36866
  /**
36867
   * move_at_start(): moves us so that we are pointing at the beginning of
36868
   * the container. It updates the index so that at_start() is true and it
36869
   * syncs the depth. The user can then create a new container instance.
36870
   *
36871
   * Usage: used with value::count_elements().
36872
   **/
36873
  simdjson_inline void move_at_start() noexcept;
36874
36875
  /**
36876
   * move_at_container_start(): moves us so that we are pointing at the beginning of
36877
   * the container so that assert_at_container_start() passes.
36878
   *
36879
   * Usage: used with reset_array() and reset_object().
36880
   **/
36881
   simdjson_inline void move_at_container_start() noexcept;
36882
  /* Useful for debugging and logging purposes. */
36883
  inline std::string to_string() const noexcept;
36884
  simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
36885
36886
  simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
36887
  simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
36888
  simdjson_inline const uint8_t *peek_start() const noexcept;
36889
  simdjson_inline uint32_t peek_start_length() const noexcept;
36890
  simdjson_inline uint32_t peek_root_length() const noexcept;
36891
36892
  /**
36893
   * The general idea of the advance_... methods and the peek_* methods
36894
   * is that you first peek and check that you have desired type. If you do,
36895
   * and only if you do, then you advance.
36896
   *
36897
   * We used to unconditionally advance. But this made reasoning about our
36898
   * current state difficult.
36899
   * Suppose you always advance. Look at the 'value' matching the key
36900
   * "shadowable" in the following example...
36901
   *
36902
   * ({"globals":{"a":{"shadowable":[}}}})
36903
   *
36904
   * If the user thinks it is a Boolean and asks for it, then we check the '[',
36905
   * decide it is not a Boolean, but still move into the next character ('}'). Now
36906
   * we are left pointing at '}' right after a '['. And we have not yet reported
36907
   * an error, only that we do not have a Boolean.
36908
   *
36909
   * If, instead, you just stand your ground until it is content that you know, then
36910
   * you will only even move beyond the '[' if the user tells you that you have an
36911
   * array. So you will be at the '}' character inside the array and, hopefully, you
36912
   * will then catch the error because an array cannot start with '}', but the code
36913
   * processing Boolean values does not know this.
36914
   *
36915
   * So the contract is: first call 'peek_...' and then call 'advance_...' only
36916
   * if you have determined that it is a type you can handle.
36917
   *
36918
   * Unfortunately, it makes the code more verbose, longer and maybe more error prone.
36919
   */
36920
36921
  simdjson_inline void advance_scalar(const char *type) noexcept;
36922
  simdjson_inline void advance_root_scalar(const char *type) noexcept;
36923
  simdjson_inline void advance_non_root_scalar(const char *type) noexcept;
36924
36925
  simdjson_inline const uint8_t *peek_scalar(const char *type) noexcept;
36926
  simdjson_inline const uint8_t *peek_root_scalar(const char *type) noexcept;
36927
  simdjson_inline const uint8_t *peek_non_root_scalar(const char *type) noexcept;
36928
36929
36930
  simdjson_inline error_code start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept;
36931
  simdjson_inline error_code end_container() noexcept;
36932
36933
  /**
36934
   * Advance to a place expecting a value (increasing depth).
36935
   *
36936
   * @return The current token (the one left behind).
36937
   * @error TAPE_ERROR If the document ended early.
36938
   */
36939
  simdjson_inline simdjson_result<const uint8_t *> advance_to_value() noexcept;
36940
36941
  simdjson_inline error_code incorrect_type_error(const char *message) const noexcept;
36942
  simdjson_inline error_code error_unless_more_tokens(uint32_t tokens=1) const noexcept;
36943
36944
  simdjson_inline bool is_at_start() const noexcept;
36945
  /**
36946
   * is_at_iterator_start() returns true on an array or object after it has just been
36947
   * created, whether the instance is empty or not.
36948
   *
36949
   * Usage: used by array::begin() in debug mode (SIMDJSON_DEVELOPMENT_CHECKS)
36950
   */
36951
  simdjson_inline bool is_at_iterator_start() const noexcept;
36952
36953
  /**
36954
   * Assuming that we are within an object, this returns true if we
36955
   * are pointing at a key.
36956
   *
36957
   * Usage: the skip_child() method should never be used while we are pointing
36958
   * at a key inside an object.
36959
   */
36960
  simdjson_inline bool is_at_key() const noexcept;
36961
36962
  inline void assert_at_start() const noexcept;
36963
  inline void assert_at_container_start() const noexcept;
36964
  inline void assert_at_root() const noexcept;
36965
  inline void assert_at_child() const noexcept;
36966
  inline void assert_at_next() const noexcept;
36967
  inline void assert_at_non_root_start() const noexcept;
36968
36969
  /** Get the starting position of this value */
36970
  simdjson_inline token_position start_position() const noexcept;
36971
36972
  /** @copydoc error_code json_iterator::position() const noexcept; */
36973
  simdjson_inline token_position position() const noexcept;
36974
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
36975
  simdjson_inline token_position last_position() const noexcept;
36976
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
36977
  simdjson_inline token_position end_position() const noexcept;
36978
  /** @copydoc error_code json_iterator::report_error(error_code error, const char *message) noexcept; */
36979
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
36980
36981
  friend class document;
36982
  friend class object;
36983
  friend class array;
36984
  friend class value;
36985
  friend class field;
36986
}; // value_iterator
36987
36988
} // namespace ondemand
36989
} // namespace fallback
36990
} // namespace simdjson
36991
36992
namespace simdjson {
36993
36994
template<>
36995
struct simdjson_result<fallback::ondemand::value_iterator> : public fallback::implementation_simdjson_result_base<fallback::ondemand::value_iterator> {
36996
public:
36997
  simdjson_inline simdjson_result(fallback::ondemand::value_iterator &&value) noexcept; ///< @private
36998
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
36999
  simdjson_inline simdjson_result() noexcept = default;
37000
};
37001
37002
} // namespace simdjson
37003
37004
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
37005
/* end file simdjson/generic/ondemand/value_iterator.h for fallback */
37006
/* including simdjson/generic/ondemand/value.h for fallback: #include "simdjson/generic/ondemand/value.h" */
37007
/* begin file simdjson/generic/ondemand/value.h for fallback */
37008
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H
37009
37010
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
37011
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_H */
37012
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
37013
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
37014
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
37015
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
37016
37017
namespace simdjson {
37018
namespace fallback {
37019
namespace ondemand {
37020
37021
/**
37022
 * An ephemeral JSON value returned during iteration. It is only valid for as long as you do
37023
 * not access more data in the JSON document.
37024
 */
37025
class value {
37026
public:
37027
  /**
37028
   * Create a new invalid value.
37029
   *
37030
   * Exists so you can declare a variable and later assign to it before use.
37031
   */
37032
0
  simdjson_inline value() noexcept = default;
37033
37034
  /**
37035
   * Get this value as the given type.
37036
   *
37037
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
37038
   *
37039
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
37040
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
37041
   *
37042
   * @returns A value of the given type, parsed from the JSON.
37043
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
37044
   */
37045
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
37046
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
37047
    // immediately fail.
37048
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
37049
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
37050
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
37051
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
37052
      " You may also add support for custom types, see our documentation.");
37053
  }
37054
37055
  /**
37056
   * Get this value as the given type.
37057
   *
37058
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
37059
   *
37060
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
37061
   * @returns INCORRECT_TYPE If the JSON value is not an object.
37062
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
37063
   */
37064
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
37065
37066
  /**
37067
   * Cast this JSON value to an array.
37068
   *
37069
   * @returns An object that can be used to iterate the array.
37070
   * @returns INCORRECT_TYPE If the JSON value is not an array.
37071
   */
37072
  simdjson_inline simdjson_result<array> get_array() noexcept;
37073
37074
  /**
37075
   * Cast this JSON value to an object.
37076
   *
37077
   * @returns An object that can be used to look up or iterate fields.
37078
   * @returns INCORRECT_TYPE If the JSON value is not an object.
37079
   */
37080
  simdjson_inline simdjson_result<object> get_object() noexcept;
37081
37082
  /**
37083
   * Cast this JSON value to an unsigned integer.
37084
   *
37085
   * @returns A unsigned 64-bit integer.
37086
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
37087
   */
37088
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
37089
37090
  /**
37091
   * Cast this JSON value (inside string) to a unsigned integer.
37092
   *
37093
   * @returns A unsigned 64-bit integer.
37094
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
37095
   */
37096
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
37097
37098
  /**
37099
   * Cast this JSON value to a signed integer.
37100
   *
37101
   * @returns A signed 64-bit integer.
37102
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
37103
   */
37104
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
37105
37106
  /**
37107
   * Cast this JSON value (inside string) to a signed integer.
37108
   *
37109
   * @returns A signed 64-bit integer.
37110
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
37111
   */
37112
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
37113
37114
  /**
37115
   * Cast this JSON value to a double.
37116
   *
37117
   * @returns A double.
37118
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
37119
   */
37120
  simdjson_inline simdjson_result<double> get_double() noexcept;
37121
37122
  /**
37123
   * Cast this JSON value (inside string) to a double
37124
   *
37125
   * @returns A double.
37126
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
37127
   */
37128
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
37129
37130
  /**
37131
   * Cast this JSON value to a string.
37132
   *
37133
   * The string is guaranteed to be valid UTF-8.
37134
   *
37135
   * Equivalent to get<std::string_view>().
37136
   *
37137
   * Important: a value should be consumed once. Calling get_string() twice on the same value
37138
   * is an error.
37139
   *
37140
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
37141
   *          time it parses a document or when it is destroyed.
37142
   * @returns INCORRECT_TYPE if the JSON value is not a string.
37143
   */
37144
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
37145
37146
  /**
37147
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
37148
   *
37149
   * The string is guaranteed to be valid UTF-8.
37150
   *
37151
   * Important: a value should be consumed once. Calling get_string() twice on the same value
37152
   * is an error.
37153
   *
37154
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
37155
   * We recommend you avoid allocating an std::string unless you need to.
37156
   *
37157
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
37158
   */
37159
  template <typename string_type>
37160
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
37161
37162
  /**
37163
   * Cast this JSON value to a "wobbly" string.
37164
   *
37165
   * The string is may not be a valid UTF-8 string.
37166
   * See https://simonsapin.github.io/wtf-8/
37167
   *
37168
   * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value
37169
   * is an error.
37170
   *
37171
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
37172
   *          time it parses a document or when it is destroyed.
37173
   * @returns INCORRECT_TYPE if the JSON value is not a string.
37174
   */
37175
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
37176
  /**
37177
   * Cast this JSON value to a raw_json_string.
37178
   *
37179
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
37180
   *
37181
   * @returns A pointer to the raw JSON for the given string.
37182
   * @returns INCORRECT_TYPE if the JSON value is not a string.
37183
   */
37184
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
37185
37186
  /**
37187
   * Cast this JSON value to a bool.
37188
   *
37189
   * @returns A bool value.
37190
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
37191
   */
37192
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
37193
37194
  /**
37195
   * Checks if this JSON value is null. If and only if the value is
37196
   * null, then it is consumed (we advance). If we find a token that
37197
   * begins with 'n' but is not 'null', then an error is returned.
37198
   *
37199
   * @returns Whether the value is null.
37200
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
37201
   */
37202
  simdjson_inline simdjson_result<bool> is_null() noexcept;
37203
37204
#if SIMDJSON_EXCEPTIONS
37205
  /**
37206
   * Cast this JSON value to an instance of type T. The programmer is responsible for
37207
   * providing an implementation of get<T> for the type T, if T is not one of the types
37208
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.).
37209
   *
37210
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
37211
   *
37212
   * @returns An instance of type T
37213
   */
37214
  template <class T>
37215
  explicit simdjson_inline operator T() noexcept(false);
37216
  /**
37217
   * Cast this JSON value to an array.
37218
   *
37219
   * @returns An object that can be used to iterate the array.
37220
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
37221
   */
37222
  simdjson_inline operator array() noexcept(false);
37223
  /**
37224
   * Cast this JSON value to an object.
37225
   *
37226
   * @returns An object that can be used to look up or iterate fields.
37227
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
37228
   */
37229
  simdjson_inline operator object() noexcept(false);
37230
  /**
37231
   * Cast this JSON value to an unsigned integer.
37232
   *
37233
   * @returns A signed 64-bit integer.
37234
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
37235
   */
37236
  simdjson_inline operator uint64_t() noexcept(false);
37237
  /**
37238
   * Cast this JSON value to a signed integer.
37239
   *
37240
   * @returns A signed 64-bit integer.
37241
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
37242
   */
37243
  simdjson_inline operator int64_t() noexcept(false);
37244
  /**
37245
   * Cast this JSON value to a double.
37246
   *
37247
   * @returns A double.
37248
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
37249
   */
37250
  simdjson_inline operator double() noexcept(false);
37251
  /**
37252
   * Cast this JSON value to a string.
37253
   *
37254
   * The string is guaranteed to be valid UTF-8.
37255
   *
37256
   * Equivalent to get<std::string_view>().
37257
   *
37258
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
37259
   *          time it parses a document or when it is destroyed.
37260
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
37261
   */
37262
  simdjson_inline operator std::string_view() noexcept(false);
37263
  /**
37264
   * Cast this JSON value to a raw_json_string.
37265
   *
37266
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
37267
   *
37268
   * @returns A pointer to the raw JSON for the given string.
37269
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
37270
   */
37271
  simdjson_inline operator raw_json_string() noexcept(false);
37272
  /**
37273
   * Cast this JSON value to a bool.
37274
   *
37275
   * @returns A bool value.
37276
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
37277
   */
37278
  simdjson_inline operator bool() noexcept(false);
37279
#endif
37280
37281
  /**
37282
   * Begin array iteration.
37283
   *
37284
   * Part of the std::iterable interface.
37285
   *
37286
   * @returns INCORRECT_TYPE If the JSON value is not an array.
37287
   */
37288
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
37289
  /**
37290
   * Sentinel representing the end of the array.
37291
   *
37292
   * Part of the std::iterable interface.
37293
   */
37294
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
37295
  /**
37296
   * This method scans the array and counts the number of elements.
37297
   * The count_elements method should always be called before you have begun
37298
   * iterating through the array: it is expected that you are pointing at
37299
   * the beginning of the array.
37300
   * The runtime complexity is linear in the size of the array. After
37301
   * calling this function, if successful, the array is 'rewinded' at its
37302
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
37303
   * there is a missing comma), then an error is returned and it is no longer
37304
   * safe to continue.
37305
   *
37306
   * Performance hint: You should only call count_elements() as a last
37307
   * resort as it may require scanning the document twice or more.
37308
   */
37309
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
37310
  /**
37311
   * This method scans the object and counts the number of key-value pairs.
37312
   * The count_fields method should always be called before you have begun
37313
   * iterating through the object: it is expected that you are pointing at
37314
   * the beginning of the object.
37315
   * The runtime complexity is linear in the size of the object. After
37316
   * calling this function, if successful, the object is 'rewinded' at its
37317
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
37318
   * there is a missing comma), then an error is returned and it is no longer
37319
   * safe to continue.
37320
   *
37321
   * To check that an object is empty, it is more performant to use
37322
   * the is_empty() method on the object instance.
37323
   *
37324
   * Performance hint: You should only call count_fields() as a last
37325
   * resort as it may require scanning the document twice or more.
37326
   */
37327
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
37328
  /**
37329
   * Get the value at the given index in the array. This function has linear-time complexity.
37330
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
37331
   *
37332
   * @return The value at the given index, or:
37333
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
37334
   */
37335
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
37336
  /**
37337
   * Look up a field by name on an object (order-sensitive).
37338
   *
37339
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
37340
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
37341
   *
37342
   * ```c++
37343
   * simdjson::ondemand::parser parser;
37344
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
37345
   * double z = obj.find_field("z");
37346
   * double y = obj.find_field("y");
37347
   * double x = obj.find_field("x");
37348
   * ```
37349
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
37350
   * that only one field is returned.
37351
37352
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
37353
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
37354
   *
37355
   * @param key The key to look up.
37356
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
37357
   */
37358
  simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept;
37359
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
37360
  simdjson_inline simdjson_result<value> find_field(const char *key) noexcept;
37361
37362
  /**
37363
   * Look up a field by name on an object, without regard to key order.
37364
   *
37365
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
37366
   * and often appears negligible. It starts out normally, starting out at the last field; but if
37367
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
37368
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
37369
   * in question is large. The fact that the extra code is there also bumps the executable size.
37370
   *
37371
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
37372
   * default behavior failed to look up a field just because it was in the wrong order--and many
37373
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
37374
   *
37375
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
37376
   * that only one field is returned.
37377
   *
37378
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
37379
   * field as not there when they are not in order).
37380
   *
37381
   * @param key The key to look up.
37382
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
37383
   */
37384
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
37385
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
37386
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
37387
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
37388
  simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept;
37389
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
37390
  simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
37391
37392
  /**
37393
   * Get the type of this JSON value. It does not validate or consume the value.
37394
   * E.g., you must still call "is_null()" to check that a value is null even if
37395
   * "type()" returns json_type::null.
37396
   *
37397
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
37398
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
37399
   * let it throw an exception).
37400
   *
37401
   * @return The type of JSON value (json_type::array, json_type::object, json_type::string,
37402
   *     json_type::number, json_type::boolean, or json_type::null).
37403
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
37404
   */
37405
  simdjson_inline simdjson_result<json_type> type() noexcept;
37406
37407
  /**
37408
   * Checks whether the value is a scalar (string, number, null, Boolean).
37409
   * Returns false when there it is an array or object.
37410
   *
37411
   * @returns true if the type is string, number, null, Boolean
37412
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
37413
   */
37414
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
37415
  /**
37416
   * Checks whether the value is a string.
37417
   *
37418
   * @returns true if the type is string
37419
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
37420
   */
37421
  simdjson_inline simdjson_result<bool> is_string() noexcept;
37422
37423
  /**
37424
   * Checks whether the value is a negative number.
37425
   *
37426
   * @returns true if the number if negative.
37427
   */
37428
  simdjson_inline bool is_negative() noexcept;
37429
  /**
37430
   * Checks whether the value is an integer number. Note that
37431
   * this requires to partially parse the number string. If
37432
   * the value is determined to be an integer, it may still
37433
   * not parse properly as an integer in subsequent steps
37434
   * (e.g., it might overflow).
37435
   *
37436
   * Performance note: if you call this function systematically
37437
   * before parsing a number, you may have fallen for a performance
37438
   * anti-pattern.
37439
   *
37440
   * @returns true if the number if negative.
37441
   */
37442
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
37443
  /**
37444
   * Determine the number type (integer or floating-point number) as quickly
37445
   * as possible. This function does not fully validate the input. It is
37446
   * useful when you only need to classify the numbers, without parsing them.
37447
   *
37448
   * If you are planning to retrieve the value or you need full validation,
37449
   * consider using the get_number() method instead: it will fully parse
37450
   * and validate the input, and give you access to the type:
37451
   * get_number().get_number_type().
37452
   *
37453
   * get_number_type() is number_type::unsigned_integer if we have
37454
   * an integer greater or equal to 9223372036854775808.
37455
   * get_number_type() is number_type::signed_integer if we have an
37456
   * integer that is less than 9223372036854775808.
37457
   * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits,
37458
   * in which case the digit_count is set to the length of the big integer string.
37459
   * Otherwise, get_number_type() has value number_type::floating_point_number.
37460
   *
37461
   * This function requires processing the number string, but it is expected
37462
   * to be faster than get_number().get_number_type() because it is does not
37463
   * parse the number value.
37464
   *
37465
   * @returns the type of the number
37466
   */
37467
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
37468
37469
  /**
37470
   * Attempt to parse an ondemand::number. An ondemand::number may
37471
   * contain an integer value or a floating-point value, the simdjson
37472
   * library will autodetect the type. Thus it is a dynamically typed
37473
   * number. Before accessing the value, you must determine the detected
37474
   * type.
37475
   *
37476
   * number.get_number_type() is number_type::signed_integer if we have
37477
   * an integer in [-9223372036854775808,9223372036854775808)
37478
   * You can recover the value by calling number.get_int64() and you
37479
   * have that number.is_int64() is true.
37480
   *
37481
   * number.get_number_type() is number_type::unsigned_integer if we have
37482
   * an integer in [9223372036854775808,18446744073709551616)
37483
   * You can recover the value by calling number.get_uint64() and you
37484
   * have that number.is_uint64() is true.
37485
   *
37486
   * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code.
37487
   *
37488
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
37489
   * and we have a binary64 number.
37490
   * You can recover the value by calling number.get_double() and you
37491
   * have that number.is_double() is true.
37492
   *
37493
   * You must check the type before accessing the value: it is an error
37494
   * to call "get_int64()" when number.get_number_type() is not
37495
   * number_type::signed_integer and when number.is_int64() is false.
37496
   *
37497
   * Performance note: this is designed with performance in mind. When
37498
   * calling 'get_number()', you scan the number string only once, determining
37499
   * efficiently the type and storing it in an efficient manner.
37500
   */
37501
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
37502
37503
  /**
37504
   * Get the raw JSON for this token.
37505
   *
37506
   * The string_view will always point into the input buffer.
37507
   *
37508
   * The string_view will start at the beginning of the token, and include the entire token
37509
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
37510
   * string token always begins with a " and is always terminated by the final ", possibly
37511
   * followed by a number of spaces.
37512
   *
37513
   * The string_view is *not* null-terminated. However, if this is a scalar (string, number,
37514
   * boolean, or null), the character after the end of the string_view is guaranteed to be
37515
   * a non-space token.
37516
   *
37517
   * Tokens include:
37518
   * - {
37519
   * - [
37520
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
37521
   * - -1.2e-100
37522
   * - true
37523
   * - false
37524
   * - null
37525
   *
37526
   * See also value::raw_json().
37527
   */
37528
  simdjson_inline std::string_view raw_json_token() noexcept;
37529
37530
  /**
37531
   * Get a string_view pointing at this value in the JSON document.
37532
   * If this element is an array or an object, it consumes the array or the object
37533
   * and returns a string_view instance corresponding to the
37534
   * array as represented in JSON. It points inside the original document.
37535
   * If this element is a scalar (string, number, Boolean, null), it returns what
37536
   * raw_json_token() would return.
37537
   */
37538
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
37539
37540
  /**
37541
   * Returns the current location in the document if in bounds.
37542
   */
37543
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
37544
37545
  /**
37546
   * Returns the current depth in the document if in bounds.
37547
   *
37548
   * E.g.,
37549
   *  0 = finished with document
37550
   *  1 = document root value (could be [ or {, not yet known)
37551
   *  2 = , or } inside root array/object
37552
   *  3 = key or value inside root array/object.
37553
   */
37554
  simdjson_inline int32_t current_depth() const noexcept;
37555
37556
  /**
37557
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
37558
   * https://tools.ietf.org/html/rfc6901 standard.
37559
   *
37560
   *   ondemand::parser parser;
37561
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
37562
   *   auto doc = parser.iterate(json);
37563
   *   doc.at_pointer("/foo/a/1") == 20
37564
   *
37565
   * It is allowed for a key to be the empty string:
37566
   *
37567
   *   ondemand::parser parser;
37568
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
37569
   *   auto doc = parser.iterate(json);
37570
   *   doc.at_pointer("//a/1") == 20
37571
   *
37572
   * Note that at_pointer() called on the document automatically calls the document's rewind
37573
   * method between each call. It invalidates all previously accessed arrays, objects and values
37574
   * that have not been consumed.
37575
   *
37576
   * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not
37577
   * standardized (by RFC 6901). We provide some experimental support for JSON pointers
37578
   * on non-document instances.  Yet it is not the case when calling at_pointer on an array
37579
   * or an object instance: there is no rewind and no invalidation.
37580
   *
37581
   * You may only call at_pointer on an array after it has been created, but before it has
37582
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
37583
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
37584
   * to call at_pointer on the same array.
37585
   *
37586
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
37587
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
37588
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
37589
   *
37590
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
37591
   *
37592
   * @return The value associated with the given JSON pointer, or:
37593
   *         - NO_SUCH_FIELD if a field does not exist in an object
37594
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
37595
   *         - INCORRECT_TYPE if a non-integer is used to access an array
37596
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
37597
   */
37598
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
37599
37600
  /**
37601
   * Get the value associated with the given JSONPath expression. We only support
37602
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
37603
   * names and array indices.
37604
   *
37605
   * @return The value associated with the given JSONPath expression, or:
37606
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
37607
   *         - NO_SUCH_FIELD if a field does not exist in an object
37608
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
37609
   *         - INCORRECT_TYPE if a non-integer is used to access an array
37610
   */
37611
  simdjson_inline simdjson_result<value> at_path(std::string_view at_path) noexcept;
37612
37613
37614
protected:
37615
  /**
37616
   * Create a value.
37617
   */
37618
  simdjson_inline value(const value_iterator &iter) noexcept;
37619
37620
  /**
37621
   * Skip this value, allowing iteration to continue.
37622
   */
37623
  simdjson_inline void skip() noexcept;
37624
37625
  /**
37626
   * Start a value at the current position.
37627
   *
37628
   * (It should already be started; this is just a self-documentation method.)
37629
   */
37630
  static simdjson_inline value start(const value_iterator &iter) noexcept;
37631
37632
  /**
37633
   * Resume a value.
37634
   */
37635
  static simdjson_inline value resume(const value_iterator &iter) noexcept;
37636
37637
  /**
37638
   * Get the object, starting or resuming it as necessary
37639
   */
37640
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
37641
37642
  // simdjson_inline void log_value(const char *type) const noexcept;
37643
  // simdjson_inline void log_error(const char *message) const noexcept;
37644
37645
  value_iterator iter{};
37646
37647
  friend class document;
37648
  friend class array_iterator;
37649
  friend class field;
37650
  friend class object;
37651
  friend struct simdjson_result<value>;
37652
  friend struct simdjson_result<field>;
37653
  friend class field;
37654
};
37655
37656
} // namespace ondemand
37657
} // namespace fallback
37658
} // namespace simdjson
37659
37660
namespace simdjson {
37661
37662
template<>
37663
struct simdjson_result<fallback::ondemand::value> : public fallback::implementation_simdjson_result_base<fallback::ondemand::value> {
37664
public:
37665
  simdjson_inline simdjson_result(fallback::ondemand::value &&value) noexcept; ///< @private
37666
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
37667
  simdjson_inline simdjson_result() noexcept = default;
37668
37669
  simdjson_inline simdjson_result<fallback::ondemand::array> get_array() noexcept;
37670
  simdjson_inline simdjson_result<fallback::ondemand::object> get_object() noexcept;
37671
37672
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
37673
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
37674
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
37675
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
37676
  simdjson_inline simdjson_result<double> get_double() noexcept;
37677
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
37678
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
37679
  template <typename string_type>
37680
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
37681
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
37682
  simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> get_raw_json_string() noexcept;
37683
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
37684
  simdjson_inline simdjson_result<bool> is_null() noexcept;
37685
37686
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
37687
37688
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
37689
37690
#if SIMDJSON_EXCEPTIONS
37691
  template <class T>
37692
  explicit simdjson_inline operator T() noexcept(false);
37693
  simdjson_inline operator fallback::ondemand::array() noexcept(false);
37694
  simdjson_inline operator fallback::ondemand::object() noexcept(false);
37695
  simdjson_inline operator uint64_t() noexcept(false);
37696
  simdjson_inline operator int64_t() noexcept(false);
37697
  simdjson_inline operator double() noexcept(false);
37698
  simdjson_inline operator std::string_view() noexcept(false);
37699
  simdjson_inline operator fallback::ondemand::raw_json_string() noexcept(false);
37700
  simdjson_inline operator bool() noexcept(false);
37701
#endif
37702
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
37703
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
37704
  simdjson_inline simdjson_result<fallback::ondemand::value> at(size_t index) noexcept;
37705
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> begin() & noexcept;
37706
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> end() & noexcept;
37707
37708
  /**
37709
   * Look up a field by name on an object (order-sensitive).
37710
   *
37711
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
37712
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
37713
   *
37714
   * ```c++
37715
   * simdjson::ondemand::parser parser;
37716
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
37717
   * double z = obj.find_field("z");
37718
   * double y = obj.find_field("y");
37719
   * double x = obj.find_field("x");
37720
   * ```
37721
   *
37722
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
37723
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
37724
   *
37725
   * @param key The key to look up.
37726
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
37727
   */
37728
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(std::string_view key) noexcept;
37729
  /** @overload simdjson_inline simdjson_result<fallback::ondemand::value> find_field(std::string_view key) noexcept; */
37730
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(const char *key) noexcept;
37731
37732
  /**
37733
   * Look up a field by name on an object, without regard to key order.
37734
   *
37735
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
37736
   * and often appears negligible. It starts out normally, starting out at the last field; but if
37737
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
37738
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
37739
   * in question is large. The fact that the extra code is there also bumps the executable size.
37740
   *
37741
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
37742
   * default behavior failed to look up a field just because it was in the wrong order--and many
37743
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
37744
   *
37745
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
37746
   * field as not there when they are not in order).
37747
   *
37748
   * @param key The key to look up.
37749
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
37750
   */
37751
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) noexcept;
37752
  /** @overload simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
37753
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(const char *key) noexcept;
37754
  /** @overload simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
37755
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](std::string_view key) noexcept;
37756
  /** @overload simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
37757
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](const char *key) noexcept;
37758
37759
  /**
37760
   * Get the type of this JSON value.
37761
   *
37762
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
37763
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
37764
   * let it throw an exception).
37765
   */
37766
  simdjson_inline simdjson_result<fallback::ondemand::json_type> type() noexcept;
37767
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
37768
  simdjson_inline simdjson_result<bool> is_string() noexcept;
37769
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
37770
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
37771
  simdjson_inline simdjson_result<fallback::number_type> get_number_type() noexcept;
37772
  simdjson_inline simdjson_result<fallback::ondemand::number> get_number() noexcept;
37773
37774
  /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
37775
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
37776
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
37777
37778
  /** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
37779
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
37780
  /** @copydoc simdjson_inline int32_t current_depth() const noexcept */
37781
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
37782
  simdjson_inline simdjson_result<fallback::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
37783
  simdjson_inline simdjson_result<fallback::ondemand::value> at_path(std::string_view json_path) noexcept;
37784
};
37785
37786
} // namespace simdjson
37787
37788
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H
37789
/* end file simdjson/generic/ondemand/value.h for fallback */
37790
/* including simdjson/generic/ondemand/logger.h for fallback: #include "simdjson/generic/ondemand/logger.h" */
37791
/* begin file simdjson/generic/ondemand/logger.h for fallback */
37792
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
37793
37794
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
37795
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_H */
37796
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
37797
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
37798
37799
namespace simdjson {
37800
namespace fallback {
37801
namespace ondemand {
37802
37803
// Logging should be free unless SIMDJSON_VERBOSE_LOGGING is set. Importantly, it is critical
37804
// that the call to the log functions be side-effect free. Thus, for example, you should not
37805
// create temporary std::string instances.
37806
namespace logger {
37807
37808
enum class log_level : int32_t {
37809
  info = 0,
37810
  error = 1
37811
};
37812
37813
#if SIMDJSON_VERBOSE_LOGGING
37814
  static constexpr const bool LOG_ENABLED = true;
37815
#else
37816
  static constexpr const bool LOG_ENABLED = false;
37817
#endif
37818
37819
// We do not want these functions to be 'really inlined' since real inlining is
37820
// for performance purposes and if you are using the loggers, you do not care about
37821
// performance (or should not).
37822
static inline void log_headers() noexcept;
37823
// If args are provided, title will be treated as format string
37824
template <typename... Args>
37825
static inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
37826
template <typename... Args>
37827
static inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
37828
static inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
37829
static inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
37830
static inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
37831
static inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
37832
static inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
37833
static inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
37834
37835
static inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail="") noexcept;
37836
static inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
37837
37838
static inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
37839
static inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
37840
static inline void log_start_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
37841
static inline void log_end_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
37842
static inline void log_error(const value_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
37843
37844
} // namespace logger
37845
} // namespace ondemand
37846
} // namespace fallback
37847
} // namespace simdjson
37848
37849
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
37850
/* end file simdjson/generic/ondemand/logger.h for fallback */
37851
/* including simdjson/generic/ondemand/token_iterator.h for fallback: #include "simdjson/generic/ondemand/token_iterator.h" */
37852
/* begin file simdjson/generic/ondemand/token_iterator.h for fallback */
37853
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
37854
37855
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
37856
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H */
37857
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
37858
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
37859
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
37860
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
37861
37862
namespace simdjson {
37863
namespace fallback {
37864
namespace ondemand {
37865
37866
/**
37867
 * Iterates through JSON tokens (`{` `}` `[` `]` `,` `:` `"<string>"` `123` `true` `false` `null`)
37868
 * detected by stage 1.
37869
 *
37870
 * @private This is not intended for external use.
37871
 */
37872
class token_iterator {
37873
public:
37874
  /**
37875
   * Create a new invalid token_iterator.
37876
   *
37877
   * Exists so you can declare a variable and later assign to it before use.
37878
   */
37879
0
  simdjson_inline token_iterator() noexcept = default;
37880
  simdjson_inline token_iterator(token_iterator &&other) noexcept = default;
37881
  simdjson_inline token_iterator &operator=(token_iterator &&other) noexcept = default;
37882
  simdjson_inline token_iterator(const token_iterator &other) noexcept = default;
37883
  simdjson_inline token_iterator &operator=(const token_iterator &other) noexcept = default;
37884
37885
  /**
37886
   * Advance to the next token (returning the current one).
37887
   */
37888
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
37889
  /**
37890
   * Reports the current offset in bytes from the start of the underlying buffer.
37891
   */
37892
  simdjson_inline uint32_t current_offset() const noexcept;
37893
  /**
37894
   * Get the JSON text for a given token (relative).
37895
   *
37896
   * This is not null-terminated; it is a view into the JSON.
37897
   *
37898
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
37899
   *              1 = next token, -1 = prev token.
37900
   *
37901
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
37902
   * it is not used...
37903
   */
37904
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
37905
  /**
37906
   * Get the maximum length of the JSON text for a given token.
37907
   *
37908
   * The length will include any whitespace at the end of the token.
37909
   *
37910
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
37911
   *              1 = next token, -1 = prev token.
37912
   */
37913
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
37914
37915
  /**
37916
   * Get the JSON text for a given token.
37917
   *
37918
   * This is not null-terminated; it is a view into the JSON.
37919
   *
37920
   * @param position The position of the token.
37921
   *
37922
   */
37923
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
37924
  /**
37925
   * Get the maximum length of the JSON text for a given token.
37926
   *
37927
   * The length will include any whitespace at the end of the token.
37928
   *
37929
   * @param position The position of the token.
37930
   */
37931
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
37932
  /**
37933
   * Get the maximum length of the JSON text for a root token.
37934
   *
37935
   * The length will include any whitespace at the end of the token.
37936
   *
37937
   * @param position The position of the token (start of the document).
37938
   */
37939
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
37940
  /**
37941
   * Return the current index.
37942
   */
37943
  simdjson_inline token_position position() const noexcept;
37944
  /**
37945
   * Reset to a previously saved index.
37946
   */
37947
  simdjson_inline void set_position(token_position target_position) noexcept;
37948
37949
  // NOTE: we don't support a full C++ iterator interface, because we expect people to make
37950
  // different calls to advance the iterator based on *their own* state.
37951
37952
  simdjson_inline bool operator==(const token_iterator &other) const noexcept;
37953
  simdjson_inline bool operator!=(const token_iterator &other) const noexcept;
37954
  simdjson_inline bool operator>(const token_iterator &other) const noexcept;
37955
  simdjson_inline bool operator>=(const token_iterator &other) const noexcept;
37956
  simdjson_inline bool operator<(const token_iterator &other) const noexcept;
37957
  simdjson_inline bool operator<=(const token_iterator &other) const noexcept;
37958
37959
protected:
37960
  simdjson_inline token_iterator(const uint8_t *buf, token_position position) noexcept;
37961
37962
  /**
37963
   * Get the index of the JSON text for a given token (relative).
37964
   *
37965
   * This is not null-terminated; it is a view into the JSON.
37966
   *
37967
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
37968
   *              1 = next token, -1 = prev token.
37969
   */
37970
  simdjson_inline uint32_t peek_index(int32_t delta=0) const noexcept;
37971
  /**
37972
   * Get the index of the JSON text for a given token.
37973
   *
37974
   * This is not null-terminated; it is a view into the JSON.
37975
   *
37976
   * @param position The position of the token.
37977
   *
37978
   */
37979
  simdjson_inline uint32_t peek_index(token_position position) const noexcept;
37980
37981
  const uint8_t *buf{};
37982
  token_position _position{};
37983
37984
  friend class json_iterator;
37985
  friend class value_iterator;
37986
  friend class object;
37987
  template <typename... Args>
37988
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
37989
  template <typename... Args>
37990
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
37991
};
37992
37993
} // namespace ondemand
37994
} // namespace fallback
37995
} // namespace simdjson
37996
37997
namespace simdjson {
37998
37999
template<>
38000
struct simdjson_result<fallback::ondemand::token_iterator> : public fallback::implementation_simdjson_result_base<fallback::ondemand::token_iterator> {
38001
public:
38002
  simdjson_inline simdjson_result(fallback::ondemand::token_iterator &&value) noexcept; ///< @private
38003
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
38004
  simdjson_inline simdjson_result() noexcept = default;
38005
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
38006
};
38007
38008
} // namespace simdjson
38009
38010
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
38011
/* end file simdjson/generic/ondemand/token_iterator.h for fallback */
38012
/* including simdjson/generic/ondemand/json_iterator.h for fallback: #include "simdjson/generic/ondemand/json_iterator.h" */
38013
/* begin file simdjson/generic/ondemand/json_iterator.h for fallback */
38014
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
38015
38016
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
38017
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H */
38018
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
38019
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
38020
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
38021
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
38022
38023
namespace simdjson {
38024
namespace fallback {
38025
namespace ondemand {
38026
38027
/**
38028
 * Iterates through JSON tokens, keeping track of depth and string buffer.
38029
 *
38030
 * @private This is not intended for external use.
38031
 */
38032
class json_iterator {
38033
protected:
38034
  token_iterator token{};
38035
  ondemand::parser *parser{};
38036
  /**
38037
   * Next free location in the string buffer.
38038
   *
38039
   * Used by raw_json_string::unescape() to have a place to unescape strings to.
38040
   */
38041
  uint8_t *_string_buf_loc{};
38042
  /**
38043
   * JSON error, if there is one.
38044
   *
38045
   * INCORRECT_TYPE and NO_SUCH_FIELD are *not* stored here, ever.
38046
   *
38047
   * PERF NOTE: we *hope* this will be elided into control flow, as it is only used (a) in the first
38048
   * iteration of the loop, or (b) for the final iteration after a missing comma is found in ++. If
38049
   * this is not elided, we should make sure it's at least not using up a register. Failing that,
38050
   * we should store it in document so there's only one of them.
38051
   */
38052
  error_code error{SUCCESS};
38053
  /**
38054
   * Depth of the current token in the JSON.
38055
   *
38056
   * - 0 = finished with document
38057
   * - 1 = document root value (could be [ or {, not yet known)
38058
   * - 2 = , or } inside root array/object
38059
   * - 3 = key or value inside root array/object.
38060
   */
38061
  depth_t _depth{};
38062
  /**
38063
   * Beginning of the document indexes.
38064
   * Normally we have root == parser->implementation->structural_indexes.get()
38065
   * but this may differ, especially in streaming mode (where we have several
38066
   * documents);
38067
   */
38068
  token_position _root{};
38069
  /**
38070
   * Normally, a json_iterator operates over a single document, but in
38071
   * some cases, we may have a stream of documents. This attribute is meant
38072
   * as meta-data: the json_iterator works the same irrespective of the
38073
   * value of this attribute.
38074
   */
38075
  bool _streaming{false};
38076
38077
public:
38078
0
  simdjson_inline json_iterator() noexcept = default;
38079
  simdjson_inline json_iterator(json_iterator &&other) noexcept;
38080
  simdjson_inline json_iterator &operator=(json_iterator &&other) noexcept;
38081
  simdjson_inline explicit json_iterator(const json_iterator &other) noexcept = default;
38082
  simdjson_inline json_iterator &operator=(const json_iterator &other) noexcept = default;
38083
  /**
38084
   * Skips a JSON value, whether it is a scalar, array or object.
38085
   */
38086
  simdjson_warn_unused simdjson_inline error_code skip_child(depth_t parent_depth) noexcept;
38087
38088
  /**
38089
   * Tell whether the iterator is still at the start
38090
   */
38091
  simdjson_inline bool at_root() const noexcept;
38092
38093
  /**
38094
   * Tell whether we should be expected to run in streaming
38095
   * mode (iterating over many documents). It is pure metadata
38096
   * that does not affect how the iterator works. It is used by
38097
   * start_root_array() and start_root_object().
38098
   */
38099
  simdjson_inline bool streaming() const noexcept;
38100
38101
  /**
38102
   * Get the root value iterator
38103
   */
38104
  simdjson_inline token_position root_position() const noexcept;
38105
  /**
38106
   * Assert that we are at the document depth (== 1)
38107
   */
38108
  simdjson_inline void assert_at_document_depth() const noexcept;
38109
  /**
38110
   * Assert that we are at the root of the document
38111
   */
38112
  simdjson_inline void assert_at_root() const noexcept;
38113
38114
  /**
38115
   * Tell whether the iterator is at the EOF mark
38116
   */
38117
  simdjson_inline bool at_end() const noexcept;
38118
38119
  /**
38120
   * Tell whether the iterator is live (has not been moved).
38121
   */
38122
  simdjson_inline bool is_alive() const noexcept;
38123
38124
  /**
38125
   * Abandon this iterator, setting depth to 0 (as if the document is finished).
38126
   */
38127
  simdjson_inline void abandon() noexcept;
38128
38129
  /**
38130
   * Advance the current token without modifying depth.
38131
   */
38132
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
38133
38134
  /**
38135
   * Returns true if there is a single token in the index (i.e., it is
38136
   * a JSON with a scalar value such as a single number).
38137
   *
38138
   * @return whether there is a single token
38139
   */
38140
  simdjson_inline bool is_single_token() const noexcept;
38141
38142
  /**
38143
   * Assert that there are at least the given number of tokens left.
38144
   *
38145
   * Has no effect in release builds.
38146
   */
38147
  simdjson_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
38148
  /**
38149
   * Assert that the given position addresses an actual token (is within bounds).
38150
   *
38151
   * Has no effect in release builds.
38152
   */
38153
  simdjson_inline void assert_valid_position(token_position position) const noexcept;
38154
  /**
38155
   * Get the JSON text for a given token (relative).
38156
   *
38157
   * This is not null-terminated; it is a view into the JSON.
38158
   *
38159
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
38160
   *
38161
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
38162
   * it is not used ...
38163
   */
38164
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
38165
  /**
38166
   * Get the maximum length of the JSON text for the current token (or relative).
38167
   *
38168
   * The length will include any whitespace at the end of the token.
38169
   *
38170
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
38171
   */
38172
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
38173
  /**
38174
   * Get a pointer to the current location in the input buffer.
38175
   *
38176
   * This is not null-terminated; it is a view into the JSON.
38177
   *
38178
   * You may be pointing outside of the input buffer: it is not generally
38179
   * safe to dereference this pointer.
38180
   */
38181
  simdjson_inline const uint8_t *unsafe_pointer() const noexcept;
38182
  /**
38183
   * Get the JSON text for a given token.
38184
   *
38185
   * This is not null-terminated; it is a view into the JSON.
38186
   *
38187
   * @param position The position of the token to retrieve.
38188
   *
38189
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
38190
   * it is not used ...
38191
   */
38192
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
38193
  /**
38194
   * Get the maximum length of the JSON text for the current token (or relative).
38195
   *
38196
   * The length will include any whitespace at the end of the token.
38197
   *
38198
   * @param position The position of the token to retrieve.
38199
   */
38200
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
38201
  /**
38202
   * Get the maximum length of the JSON text for the current root token.
38203
   *
38204
   * The length will include any whitespace at the end of the token.
38205
   *
38206
   * @param position The position of the token to retrieve.
38207
   */
38208
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
38209
  /**
38210
   * Get the JSON text for the last token in the document.
38211
   *
38212
   * This is not null-terminated; it is a view into the JSON.
38213
   *
38214
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
38215
   * it is not used ...
38216
   */
38217
  simdjson_inline const uint8_t *peek_last() const noexcept;
38218
38219
  /**
38220
   * Ascend one level.
38221
   *
38222
   * Validates that the depth - 1 == parent_depth.
38223
   *
38224
   * @param parent_depth the expected parent depth.
38225
   */
38226
  simdjson_inline void ascend_to(depth_t parent_depth) noexcept;
38227
38228
  /**
38229
   * Descend one level.
38230
   *
38231
   * Validates that the new depth == child_depth.
38232
   *
38233
   * @param child_depth the expected child depth.
38234
   */
38235
  simdjson_inline void descend_to(depth_t child_depth) noexcept;
38236
  simdjson_inline void descend_to(depth_t child_depth, int32_t delta) noexcept;
38237
38238
  /**
38239
   * Get current depth.
38240
   */
38241
  simdjson_inline depth_t depth() const noexcept;
38242
38243
  /**
38244
   * Get current (writeable) location in the string buffer.
38245
   */
38246
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
38247
38248
  /**
38249
   * Report an unrecoverable error, preventing further iteration.
38250
   *
38251
   * @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
38252
   * @param message An error message to report with the error.
38253
   */
38254
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
38255
38256
  /**
38257
   * Log error, but don't stop iteration.
38258
   * @param error The error to report. Must be INCORRECT_TYPE, or NO_SUCH_FIELD.
38259
   * @param message An error message to report with the error.
38260
   */
38261
  simdjson_inline error_code optional_error(error_code error, const char *message) noexcept;
38262
38263
  /**
38264
   * Take an input in json containing max_len characters and attempt to copy it over to tmpbuf, a buffer with
38265
   * N bytes of capacity. It will return false if N is too small (smaller than max_len) of if it is zero.
38266
   * The buffer (tmpbuf) is padded with space characters.
38267
   */
38268
  simdjson_warn_unused simdjson_inline bool copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept;
38269
38270
  simdjson_inline token_position position() const noexcept;
38271
  /**
38272
   * Write the raw_json_string to the string buffer and return a string_view.
38273
   * Each raw_json_string should be unescaped once, or else the string buffer might
38274
   * overflow.
38275
   */
38276
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
38277
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
38278
38279
  simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
38280
38281
  simdjson_inline error_code consume_character(char c) noexcept;
38282
#if SIMDJSON_DEVELOPMENT_CHECKS
38283
  simdjson_inline token_position start_position(depth_t depth) const noexcept;
38284
  simdjson_inline void set_start_position(depth_t depth, token_position position) noexcept;
38285
#endif
38286
38287
  /* Useful for debugging and logging purposes. */
38288
  inline std::string to_string() const noexcept;
38289
38290
  /**
38291
   * Returns the current location in the document if in bounds.
38292
   */
38293
  inline simdjson_result<const char *> current_location() const noexcept;
38294
38295
  /**
38296
   * Updates this json iterator so that it is back at the beginning of the document,
38297
   * as if it had just been created.
38298
   */
38299
  inline void rewind() noexcept;
38300
  /**
38301
   * This checks whether the {,},[,] are balanced so that the document
38302
   * ends with proper zero depth. This requires scanning the whole document
38303
   * and it may be expensive. It is expected that it will be rarely called.
38304
   * It does not attempt to match { with } and [ with ].
38305
   */
38306
  inline bool balanced() const noexcept;
38307
protected:
38308
  simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
38309
  /// The last token before the end
38310
  simdjson_inline token_position last_position() const noexcept;
38311
  /// The token *at* the end. This points at gibberish and should only be used for comparison.
38312
  simdjson_inline token_position end_position() const noexcept;
38313
  /// The end of the buffer.
38314
  simdjson_inline token_position end() const noexcept;
38315
38316
  friend class document;
38317
  friend class document_stream;
38318
  friend class object;
38319
  friend class array;
38320
  friend class value;
38321
  friend class raw_json_string;
38322
  friend class parser;
38323
  friend class value_iterator;
38324
  friend class field;
38325
  template <typename... Args>
38326
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
38327
  template <typename... Args>
38328
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
38329
}; // json_iterator
38330
38331
} // namespace ondemand
38332
} // namespace fallback
38333
} // namespace simdjson
38334
38335
namespace simdjson {
38336
38337
template<>
38338
struct simdjson_result<fallback::ondemand::json_iterator> : public fallback::implementation_simdjson_result_base<fallback::ondemand::json_iterator> {
38339
public:
38340
  simdjson_inline simdjson_result(fallback::ondemand::json_iterator &&value) noexcept; ///< @private
38341
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
38342
38343
  simdjson_inline simdjson_result() noexcept = default;
38344
};
38345
38346
} // namespace simdjson
38347
38348
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
38349
/* end file simdjson/generic/ondemand/json_iterator.h for fallback */
38350
/* including simdjson/generic/ondemand/json_type.h for fallback: #include "simdjson/generic/ondemand/json_type.h" */
38351
/* begin file simdjson/generic/ondemand/json_type.h for fallback */
38352
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
38353
38354
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
38355
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H */
38356
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
38357
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
38358
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
38359
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
38360
38361
namespace simdjson {
38362
namespace fallback {
38363
namespace ondemand {
38364
38365
/**
38366
 * The type of a JSON value.
38367
 */
38368
enum class json_type {
38369
    // Start at 1 to catch uninitialized / default values more easily
38370
    array=1, ///< A JSON array   ( [ 1, 2, 3 ... ] )
38371
    object,  ///< A JSON object  ( { "a": 1, "b" 2, ... } )
38372
    number,  ///< A JSON number  ( 1 or -2.3 or 4.5e6 ...)
38373
    string,  ///< A JSON string  ( "a" or "hello world\n" ...)
38374
    boolean, ///< A JSON boolean (true or false)
38375
    null     ///< A JSON null    (null)
38376
};
38377
38378
/**
38379
 * A type representing a JSON number.
38380
 * The design of the struct is deliberately straight-forward. All
38381
 * functions return standard values with no error check.
38382
 */
38383
struct number {
38384
38385
  /**
38386
   * return the automatically determined type of
38387
   * the number: number_type::floating_point_number,
38388
   * number_type::signed_integer or number_type::unsigned_integer.
38389
   *
38390
   *    enum class number_type {
38391
   *        floating_point_number=1, /// a binary64 number
38392
   *        signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
38393
   *        unsigned_integer         /// a positive integer larger or equal to 1<<63
38394
   *    };
38395
   */
38396
  simdjson_inline ondemand::number_type get_number_type() const noexcept;
38397
  /**
38398
   * return true if the automatically determined type of
38399
   * the number is number_type::unsigned_integer.
38400
   */
38401
  simdjson_inline bool is_uint64() const noexcept;
38402
  /**
38403
   * return the value as a uint64_t, only valid if is_uint64() is true.
38404
   */
38405
  simdjson_inline uint64_t get_uint64() const noexcept;
38406
  simdjson_inline operator uint64_t() const noexcept;
38407
38408
  /**
38409
   * return true if the automatically determined type of
38410
   * the number is number_type::signed_integer.
38411
   */
38412
  simdjson_inline bool is_int64() const noexcept;
38413
  /**
38414
   * return the value as a int64_t, only valid if is_int64() is true.
38415
   */
38416
  simdjson_inline int64_t get_int64() const noexcept;
38417
  simdjson_inline operator int64_t() const noexcept;
38418
38419
38420
  /**
38421
   * return true if the automatically determined type of
38422
   * the number is number_type::floating_point_number.
38423
   */
38424
  simdjson_inline bool is_double() const noexcept;
38425
  /**
38426
   * return the value as a double, only valid if is_double() is true.
38427
   */
38428
  simdjson_inline double get_double() const noexcept;
38429
  simdjson_inline operator double() const noexcept;
38430
38431
  /**
38432
   * Convert the number to a double. Though it always succeed, the conversion
38433
   * may be lossy if the number cannot be represented exactly.
38434
   */
38435
  simdjson_inline double as_double() const noexcept;
38436
38437
38438
protected:
38439
  /**
38440
   * The next block of declaration is designed so that we can call the number parsing
38441
   * functions on a number type. They are protected and should never be used outside
38442
   * of the core simdjson library.
38443
   */
38444
  friend class value_iterator;
38445
  template<typename W>
38446
  friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
38447
  template<typename W>
38448
  friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
38449
  /** Store a signed 64-bit value to the number. */
38450
  simdjson_inline void append_s64(int64_t value) noexcept;
38451
  /** Store an unsigned 64-bit value to the number. */
38452
  simdjson_inline void append_u64(uint64_t value) noexcept;
38453
  /** Store a double value to the number. */
38454
  simdjson_inline void append_double(double value) noexcept;
38455
  /** Specifies that the value is a double, but leave it undefined. */
38456
  simdjson_inline void skip_double() noexcept;
38457
  /**
38458
   * End of friend declarations.
38459
   */
38460
38461
  /**
38462
   * Our attributes are a union type (size = 64 bits)
38463
   * followed by a type indicator.
38464
   */
38465
  union {
38466
    double floating_point_number;
38467
    int64_t signed_integer;
38468
    uint64_t unsigned_integer;
38469
  } payload{0};
38470
  number_type type{number_type::signed_integer};
38471
};
38472
38473
/**
38474
 * Write the JSON type to the output stream
38475
 *
38476
 * @param out The output stream.
38477
 * @param type The json_type.
38478
 */
38479
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
38480
38481
#if SIMDJSON_EXCEPTIONS
38482
/**
38483
 * Send JSON type to an output stream.
38484
 *
38485
 * @param out The output stream.
38486
 * @param type The json_type.
38487
 * @throw simdjson_error if the result being printed has an error. If there is an error with the
38488
 *        underlying output stream, that error will be propagated (simdjson_error will not be
38489
 *        thrown).
38490
 */
38491
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false);
38492
#endif
38493
38494
} // namespace ondemand
38495
} // namespace fallback
38496
} // namespace simdjson
38497
38498
namespace simdjson {
38499
38500
template<>
38501
struct simdjson_result<fallback::ondemand::json_type> : public fallback::implementation_simdjson_result_base<fallback::ondemand::json_type> {
38502
public:
38503
  simdjson_inline simdjson_result(fallback::ondemand::json_type &&value) noexcept; ///< @private
38504
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
38505
  simdjson_inline simdjson_result() noexcept = default;
38506
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
38507
};
38508
38509
} // namespace simdjson
38510
38511
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
38512
/* end file simdjson/generic/ondemand/json_type.h for fallback */
38513
/* including simdjson/generic/ondemand/raw_json_string.h for fallback: #include "simdjson/generic/ondemand/raw_json_string.h" */
38514
/* begin file simdjson/generic/ondemand/raw_json_string.h for fallback */
38515
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
38516
38517
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
38518
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H */
38519
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
38520
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
38521
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
38522
38523
namespace simdjson {
38524
namespace fallback {
38525
namespace ondemand {
38526
38527
/**
38528
 * A string escaped per JSON rules, terminated with quote ("). They are used to represent
38529
 * unescaped keys inside JSON documents.
38530
 *
38531
 * (In other words, a pointer to the beginning of a string, just after the start quote, inside a
38532
 * JSON file.)
38533
 *
38534
 * This class is deliberately simplistic and has little functionality. You can
38535
 * compare a raw_json_string instance with an unescaped C string, but
38536
 * that is nearly all you can do.
38537
 *
38538
 * The raw_json_string is unescaped. If you wish to write an unescaped version of it to your own
38539
 * buffer, you may do so using the parser.unescape(string, buff) method, using an ondemand::parser
38540
 * instance. Doing so requires you to have a sufficiently large buffer.
38541
 *
38542
 * The raw_json_string instances originate typically from field instance which in turn represent
38543
 * key-value pairs from object instances. From a field instance, you get the raw_json_string
38544
 * instance by calling key(). You can, if you want a more usable string_view instance, call
38545
 * the unescaped_key() method on the field instance. You may also create a raw_json_string from
38546
 * any other string value, with the value.get_raw_json_string() method. Again, you can get
38547
 * a more usable string_view instance by calling get_string().
38548
 *
38549
 */
38550
class raw_json_string {
38551
public:
38552
  /**
38553
   * Create a new invalid raw_json_string.
38554
   *
38555
   * Exists so you can declare a variable and later assign to it before use.
38556
   */
38557
0
  simdjson_inline raw_json_string() noexcept = default;
38558
38559
  /**
38560
   * Create a new invalid raw_json_string pointed at the given location in the JSON.
38561
   *
38562
   * The given location must be just *after* the beginning quote (") in the JSON file.
38563
   *
38564
   * It *must* be terminated by a ", and be a valid JSON string.
38565
   */
38566
  simdjson_inline raw_json_string(const uint8_t * _buf) noexcept;
38567
  /**
38568
   * Get the raw pointer to the beginning of the string in the JSON (just after the ").
38569
   *
38570
   * It is possible for this function to return a null pointer if the instance
38571
   * has outlived its existence.
38572
   */
38573
  simdjson_inline const char * raw() const noexcept;
38574
38575
  /**
38576
   * This compares the current instance to the std::string_view target: returns true if
38577
   * they are byte-by-byte equal (no escaping is done) on target.size() characters,
38578
   * and if the raw_json_string instance has a quote character at byte index target.size().
38579
   * We never read more than length + 1 bytes in the raw_json_string instance.
38580
   * If length is smaller than target.size(), this will return false.
38581
   *
38582
   * The std::string_view instance may contain any characters. However, the caller
38583
   * is responsible for setting length so that length bytes may be read in the
38584
   * raw_json_string.
38585
   *
38586
   * Performance: the comparison may be done using memcmp which may be efficient
38587
   * for long strings.
38588
   */
38589
  simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept;
38590
38591
  /**
38592
   * This compares the current instance to the std::string_view target: returns true if
38593
   * they are byte-by-byte equal (no escaping is done).
38594
   * The std::string_view instance should not contain unescaped quote characters:
38595
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
38596
   *
38597
   * Performance: the comparison is done byte-by-byte which might be inefficient for
38598
   * long strings.
38599
   *
38600
   * If target is a compile-time constant, and your compiler likes you,
38601
   * you should be able to do the following without performance penalty...
38602
   *
38603
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
38604
   *   s.unsafe_is_equal(target);
38605
   */
38606
  simdjson_inline bool unsafe_is_equal(std::string_view target) const noexcept;
38607
38608
  /**
38609
   * This compares the current instance to the C string target: returns true if
38610
   * they are byte-by-byte equal (no escaping is done).
38611
   * The provided C string should not contain an unescaped quote character:
38612
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
38613
   *
38614
   * If target is a compile-time constant, and your compiler likes you,
38615
   * you should be able to do the following without performance penalty...
38616
   *
38617
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
38618
   *   s.unsafe_is_equal(target);
38619
   */
38620
  simdjson_inline bool unsafe_is_equal(const char* target) const noexcept;
38621
38622
  /**
38623
   * This compares the current instance to the std::string_view target: returns true if
38624
   * they are byte-by-byte equal (no escaping is done).
38625
   */
38626
  simdjson_inline bool is_equal(std::string_view target) const noexcept;
38627
38628
  /**
38629
   * This compares the current instance to the C string target: returns true if
38630
   * they are byte-by-byte equal (no escaping is done).
38631
   */
38632
  simdjson_inline bool is_equal(const char* target) const noexcept;
38633
38634
  /**
38635
   * Returns true if target is free from unescaped quote. If target is known at
38636
   * compile-time, we might expect the computation to happen at compile time with
38637
   * many compilers (not all!).
38638
   */
38639
  static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
38640
  static simdjson_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
38641
38642
private:
38643
38644
38645
  /**
38646
   * This will set the inner pointer to zero, effectively making
38647
   * this instance unusable.
38648
   */
38649
0
  simdjson_inline void consume() noexcept { buf = nullptr; }
38650
38651
  /**
38652
   * Checks whether the inner pointer is non-null and thus usable.
38653
   */
38654
0
  simdjson_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
38655
38656
  /**
38657
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
38658
   * The result will be a valid UTF-8.
38659
   *
38660
   * ## IMPORTANT: string_view lifetime
38661
   *
38662
   * The string_view is only valid until the next parse() call on the parser.
38663
   *
38664
   * @param iter A json_iterator, which contains a buffer where the string will be written.
38665
   * @param allow_replacement Whether we allow replacement of invalid surrogate pairs.
38666
   */
38667
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(json_iterator &iter, bool allow_replacement) const noexcept;
38668
38669
  /**
38670
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
38671
   * The result may not be a valid UTF-8. https://simonsapin.github.io/wtf-8/
38672
   *
38673
   * ## IMPORTANT: string_view lifetime
38674
   *
38675
   * The string_view is only valid until the next parse() call on the parser.
38676
   *
38677
   * @param iter A json_iterator, which contains a buffer where the string will be written.
38678
   */
38679
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(json_iterator &iter) const noexcept;
38680
  const uint8_t * buf{};
38681
  friend class object;
38682
  friend class field;
38683
  friend class parser;
38684
  friend struct simdjson_result<raw_json_string>;
38685
};
38686
38687
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &, const raw_json_string &) noexcept;
38688
38689
/**
38690
 * Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user is responsible
38691
 * for providing a string with no unescaped quote. Note that unescaped quotes cannot be present in valid JSON strings.
38692
 */
38693
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept;
38694
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept;
38695
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept;
38696
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept;
38697
38698
38699
} // namespace ondemand
38700
} // namespace fallback
38701
} // namespace simdjson
38702
38703
namespace simdjson {
38704
38705
template<>
38706
struct simdjson_result<fallback::ondemand::raw_json_string> : public fallback::implementation_simdjson_result_base<fallback::ondemand::raw_json_string> {
38707
public:
38708
  simdjson_inline simdjson_result(fallback::ondemand::raw_json_string &&value) noexcept; ///< @private
38709
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
38710
  simdjson_inline simdjson_result() noexcept = default;
38711
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
38712
38713
  simdjson_inline simdjson_result<const char *> raw() const noexcept;
38714
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(fallback::ondemand::json_iterator &iter, bool allow_replacement) const noexcept;
38715
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(fallback::ondemand::json_iterator &iter) const noexcept;
38716
};
38717
38718
} // namespace simdjson
38719
38720
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
38721
/* end file simdjson/generic/ondemand/raw_json_string.h for fallback */
38722
/* including simdjson/generic/ondemand/parser.h for fallback: #include "simdjson/generic/ondemand/parser.h" */
38723
/* begin file simdjson/generic/ondemand/parser.h for fallback */
38724
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_H
38725
38726
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
38727
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_H */
38728
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
38729
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
38730
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
38731
38732
#include <memory>
38733
38734
namespace simdjson {
38735
namespace fallback {
38736
namespace ondemand {
38737
38738
/**
38739
 * The default batch size for document_stream instances for this On Demand kernel.
38740
 * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value
38741
 * in the future.
38742
 */
38743
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
38744
/**
38745
 * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
38746
 * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
38747
 * most users will want a much larger batch size.
38748
 *
38749
 * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
38750
 * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
38751
 */
38752
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
38753
38754
/**
38755
 * A JSON fragment iterator.
38756
 *
38757
 * This holds the actual iterator as well as the buffer for writing strings.
38758
 */
38759
class parser {
38760
public:
38761
  /**
38762
   * Create a JSON parser.
38763
   *
38764
   * The new parser will have zero capacity.
38765
   */
38766
  inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
38767
38768
  inline parser(parser &&other) noexcept = default;
38769
  simdjson_inline parser(const parser &other) = delete;
38770
  simdjson_inline parser &operator=(const parser &other) = delete;
38771
  simdjson_inline parser &operator=(parser &&other) noexcept = default;
38772
38773
  /** Deallocate the JSON parser. */
38774
134k
  inline ~parser() noexcept = default;
38775
38776
  /**
38777
   * Start iterating an on-demand JSON document.
38778
   *
38779
   *   ondemand::parser parser;
38780
   *   document doc = parser.iterate(json);
38781
   *
38782
   * It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
38783
   * Otherwise the iterate method may return an error. In particular, the whole input should be
38784
   * valid: we do not attempt to tolerate incorrect content either before or after a JSON
38785
   * document. If there is a UTF-8 BOM, the parser skips it.
38786
   *
38787
   * ### IMPORTANT: Validate what you use
38788
   *
38789
   * Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
38790
   * iterate does not parse and validate the whole document.
38791
   *
38792
   * ### IMPORTANT: Buffer Lifetime
38793
   *
38794
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
38795
   * long as the document iteration.
38796
   *
38797
   * ### IMPORTANT: Document Lifetime
38798
   *
38799
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
38800
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
38801
   * you call parse() again or destroy the parser.
38802
   *
38803
   * ### REQUIRED: Buffer Padding
38804
   *
38805
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
38806
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
38807
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
38808
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
38809
   *
38810
   * @param json The JSON to parse.
38811
   * @param len The length of the JSON.
38812
   * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
38813
   *
38814
   * @return The document, or an error:
38815
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
38816
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
38817
   *           allocation fails.
38818
   *         - EMPTY if the document is all whitespace.
38819
   *         - UTF8_ERROR if the document is not valid UTF-8.
38820
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
38821
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
38822
   */
38823
  simdjson_warn_unused simdjson_result<document> iterate(padded_string_view json) & noexcept;
38824
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38825
  simdjson_warn_unused simdjson_result<document> iterate(const char *json, size_t len, size_t capacity) & noexcept;
38826
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38827
  simdjson_warn_unused simdjson_result<document> iterate(const uint8_t *json, size_t len, size_t capacity) & noexcept;
38828
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38829
  simdjson_warn_unused simdjson_result<document> iterate(std::string_view json, size_t capacity) & noexcept;
38830
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38831
  simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
38832
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38833
  simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
38834
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38835
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
38836
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38837
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
38838
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
38839
  simdjson_warn_unused simdjson_result<document> iterate(padded_string &&json) & noexcept = delete;
38840
38841
  /**
38842
   * @private
38843
   *
38844
   * Start iterating an on-demand JSON document.
38845
   *
38846
   *   ondemand::parser parser;
38847
   *   json_iterator doc = parser.iterate(json);
38848
   *
38849
   * ### IMPORTANT: Buffer Lifetime
38850
   *
38851
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
38852
   * long as the document iteration.
38853
   *
38854
   * ### IMPORTANT: Document Lifetime
38855
   *
38856
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
38857
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
38858
   * you call parse() again or destroy the parser.
38859
   *
38860
   * The ondemand::document instance holds the iterator. The document must remain in scope
38861
   * while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
38862
   *
38863
   * ### REQUIRED: Buffer Padding
38864
   *
38865
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
38866
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
38867
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
38868
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
38869
   *
38870
   * @param json The JSON to parse.
38871
   *
38872
   * @return The iterator, or an error:
38873
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
38874
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
38875
   *           allocation fails.
38876
   *         - EMPTY if the document is all whitespace.
38877
   *         - UTF8_ERROR if the document is not valid UTF-8.
38878
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
38879
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
38880
   */
38881
  simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
38882
38883
38884
  /**
38885
   * Parse a buffer containing many JSON documents.
38886
   *
38887
   *   auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
38888
   *   ondemand::parser parser;
38889
   *   ondemand::document_stream docs = parser.iterate_many(json);
38890
   *   for (auto & doc : docs) {
38891
   *     std::cout << doc["foo"] << std::endl;
38892
   *   }
38893
   *   // Prints 1 2 3
38894
   *
38895
   * No copy of the input buffer is made.
38896
   *
38897
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
38898
   *
38899
   * The caller is responsabile to ensure that the input string data remains unchanged and is
38900
   * not deleted during the loop.
38901
   *
38902
   * ### Format
38903
   *
38904
   * The buffer must contain a series of one or more JSON documents, concatenated into a single
38905
   * buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
38906
   * then starts parsing the next document at that point. (It does this with more parallelism and
38907
   * lookahead than you might think, though.)
38908
   *
38909
   * documents that consist of an object or array may omit the whitespace between them, concatenating
38910
   * with no separator. Documents that consist of a single primitive (i.e. documents that are not
38911
   * arrays or objects) MUST be separated with ASCII whitespace.
38912
   *
38913
   * The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
38914
   * If there is a UTF-8 BOM, the parser skips it.
38915
   *
38916
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
38917
   * Setting batch_size to excessively large or excessively small values may impact negatively the
38918
   * performance.
38919
   *
38920
   * ### REQUIRED: Buffer Padding
38921
   *
38922
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
38923
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
38924
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
38925
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
38926
   *
38927
   * ### Threads
38928
   *
38929
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
38930
   * hood to do some lookahead.
38931
   *
38932
   * ### Parser Capacity
38933
   *
38934
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
38935
   * to handle it (up to max_capacity).
38936
   *
38937
   * @param buf The concatenated JSON to parse.
38938
   * @param len The length of the concatenated JSON.
38939
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
38940
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
38941
   *                   parse as many documents as possible in one tight loop.
38942
   *                   Defaults to 10MB, which has been a reasonable sweet spot in our tests.
38943
   * @param allow_comma_separated (defaults on false) This allows a mode where the documents are
38944
   *                   separated by commas instead of whitespace. It comes with a performance
38945
   *                   penalty because the entire document is indexed at once (and the document must be
38946
   *                   less than 4 GB), and there is no multithreading. In this mode, the batch_size parameter
38947
   *                   is effectively ignored, as it is set to at least the document size.
38948
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
38949
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails
38950
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
38951
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
38952
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
38953
   */
38954
  inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
38955
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
38956
  inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
38957
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
38958
  inline simdjson_result<document_stream> iterate_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
38959
  inline simdjson_result<document_stream> iterate_many(const std::string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
38960
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
38961
  inline simdjson_result<document_stream> iterate_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
38962
  inline simdjson_result<document_stream> iterate_many(const padded_string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
38963
38964
  /** @private We do not want to allow implicit conversion from C string to std::string. */
38965
  simdjson_result<document_stream> iterate_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
38966
38967
  /** The capacity of this parser (the largest document it can process). */
38968
  simdjson_inline size_t capacity() const noexcept;
38969
  /** The maximum capacity of this parser (the largest document it is allowed to process). */
38970
  simdjson_inline size_t max_capacity() const noexcept;
38971
  simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
38972
  /**
38973
   * The maximum depth of this parser (the most deeply nested objects and arrays it can process).
38974
   * This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
38975
   * The document's instance current_depth() method should be used to monitor the parsing
38976
   * depth and limit it if desired.
38977
   */
38978
  simdjson_inline size_t max_depth() const noexcept;
38979
38980
  /**
38981
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
38982
   * and `max_depth` depth.
38983
   *
38984
   * The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
38985
   * The document's instance current_depth() method should be used to monitor the parsing
38986
   * depth and limit it if desired.
38987
   *
38988
   * @param capacity The new capacity.
38989
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
38990
   * @return The error, if there is one.
38991
   */
38992
  simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
38993
38994
  #ifdef SIMDJSON_THREADS_ENABLED
38995
  /**
38996
   * The parser instance can use threads when they are available to speed up some
38997
   * operations. It is enabled by default. Changing this attribute will change the
38998
   * behavior of the parser for future operations.
38999
   */
39000
  bool threaded{true};
39001
  #endif
39002
39003
  /**
39004
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
39005
   * The result must be valid UTF-8.
39006
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
39007
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
39008
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
39009
   *
39010
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
39011
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
39012
   * instead of get_raw_json_string()).
39013
   *
39014
   * ## IMPORTANT: string_view lifetime
39015
   *
39016
   * The string_view is only valid as long as the bytes in dst.
39017
   *
39018
   * @param raw_json_string input
39019
   * @param dst A pointer to a buffer at least large enough to write this string as well as
39020
   *            an additional SIMDJSON_PADDING bytes.
39021
   * @param allow_replacement Whether we allow a replacement if the input string contains unmatched surrogate pairs.
39022
   * @return A string_view pointing at the unescaped string in dst
39023
   * @error STRING_ERROR if escapes are incorrect.
39024
   */
39025
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement = false) const noexcept;
39026
39027
  /**
39028
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
39029
   * The result may not be valid UTF-8. See https://simonsapin.github.io/wtf-8/
39030
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
39031
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
39032
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
39033
   *
39034
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
39035
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
39036
   * instead of get_raw_json_string()).
39037
   *
39038
   * ## IMPORTANT: string_view lifetime
39039
   *
39040
   * The string_view is only valid as long as the bytes in dst.
39041
   *
39042
   * @param raw_json_string input
39043
   * @param dst A pointer to a buffer at least large enough to write this string as well as
39044
   *            an additional SIMDJSON_PADDING bytes.
39045
   * @return A string_view pointing at the unescaped string in dst
39046
   * @error STRING_ERROR if escapes are incorrect.
39047
   */
39048
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept;
39049
39050
private:
39051
  /** @private [for benchmarking access] The implementation to use */
39052
  std::unique_ptr<internal::dom_parser_implementation> implementation{};
39053
  size_t _capacity{0};
39054
  size_t _max_capacity;
39055
  size_t _max_depth{DEFAULT_MAX_DEPTH};
39056
  std::unique_ptr<uint8_t[]> string_buf{};
39057
#if SIMDJSON_DEVELOPMENT_CHECKS
39058
  std::unique_ptr<token_position[]> start_positions{};
39059
#endif
39060
39061
  friend class json_iterator;
39062
  friend class document_stream;
39063
};
39064
39065
} // namespace ondemand
39066
} // namespace fallback
39067
} // namespace simdjson
39068
39069
namespace simdjson {
39070
39071
template<>
39072
struct simdjson_result<fallback::ondemand::parser> : public fallback::implementation_simdjson_result_base<fallback::ondemand::parser> {
39073
public:
39074
  simdjson_inline simdjson_result(fallback::ondemand::parser &&value) noexcept; ///< @private
39075
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
39076
  simdjson_inline simdjson_result() noexcept = default;
39077
};
39078
39079
} // namespace simdjson
39080
39081
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_H
39082
/* end file simdjson/generic/ondemand/parser.h for fallback */
39083
39084
// All other declarations
39085
/* including simdjson/generic/ondemand/array.h for fallback: #include "simdjson/generic/ondemand/array.h" */
39086
/* begin file simdjson/generic/ondemand/array.h for fallback */
39087
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
39088
39089
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
39090
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H */
39091
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
39092
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
39093
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
39094
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
39095
39096
namespace simdjson {
39097
namespace fallback {
39098
namespace ondemand {
39099
39100
/**
39101
 * A forward-only JSON array.
39102
 */
39103
class array {
39104
public:
39105
  /**
39106
   * Create a new invalid array.
39107
   *
39108
   * Exists so you can declare a variable and later assign to it before use.
39109
   */
39110
0
  simdjson_inline array() noexcept = default;
39111
39112
  /**
39113
   * Begin array iteration.
39114
   *
39115
   * Part of the std::iterable interface.
39116
   */
39117
  simdjson_inline simdjson_result<array_iterator> begin() noexcept;
39118
  /**
39119
   * Sentinel representing the end of the array.
39120
   *
39121
   * Part of the std::iterable interface.
39122
   */
39123
  simdjson_inline simdjson_result<array_iterator> end() noexcept;
39124
  /**
39125
   * This method scans the array and counts the number of elements.
39126
   * The count_elements method should always be called before you have begun
39127
   * iterating through the array: it is expected that you are pointing at
39128
   * the beginning of the array.
39129
   * The runtime complexity is linear in the size of the array. After
39130
   * calling this function, if successful, the array is 'rewinded' at its
39131
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
39132
   * there is a missing comma), then an error is returned and it is no longer
39133
   * safe to continue.
39134
   *
39135
   * To check that an array is empty, it is more performant to use
39136
   * the is_empty() method.
39137
   */
39138
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
39139
  /**
39140
   * This method scans the beginning of the array and checks whether the
39141
   * array is empty.
39142
   * The runtime complexity is constant time. After
39143
   * calling this function, if successful, the array is 'rewinded' at its
39144
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
39145
   * there is a missing comma), then an error is returned and it is no longer
39146
   * safe to continue.
39147
   */
39148
  simdjson_inline simdjson_result<bool> is_empty() & noexcept;
39149
  /**
39150
   * Reset the iterator so that we are pointing back at the
39151
   * beginning of the array. You should still consume values only once even if you
39152
   * can iterate through the array more than once. If you unescape a string
39153
   * within the array more than once, you have unsafe code. Note that rewinding
39154
   * an array means that you may need to reparse it anew: it is not a free
39155
   * operation.
39156
   *
39157
   * @returns true if the array contains some elements (not empty)
39158
   */
39159
  inline simdjson_result<bool> reset() & noexcept;
39160
  /**
39161
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
39162
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
39163
   * as the root of its own JSON document.
39164
   *
39165
   *   ondemand::parser parser;
39166
   *   auto json = R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded;
39167
   *   auto doc = parser.iterate(json);
39168
   *   doc.at_pointer("/0/foo/a/1") == 20
39169
   *
39170
   * Note that at_pointer() called on the document automatically calls the document's rewind
39171
   * method between each call. It invalidates all previously accessed arrays, objects and values
39172
   * that have not been consumed. Yet it is not the case when calling at_pointer on an array
39173
   * instance: there is no rewind and no invalidation.
39174
   *
39175
   * You may only call at_pointer on an array after it has been created, but before it has
39176
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
39177
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
39178
   * to call at_pointer on the same array.
39179
   *
39180
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
39181
   *
39182
   * @return The value associated with the given JSON pointer, or:
39183
   *         - NO_SUCH_FIELD if a field does not exist in an object
39184
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
39185
   *         - INCORRECT_TYPE if a non-integer is used to access an array
39186
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
39187
   */
39188
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
39189
39190
  /**
39191
   * Get the value associated with the given JSONPath expression. We only support
39192
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
39193
   * names and array indices.
39194
   *
39195
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
39196
   *
39197
   * @return The value associated with the given JSONPath expression, or:
39198
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
39199
   *         - NO_SUCH_FIELD if a field does not exist in an object
39200
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
39201
   *         - INCORRECT_TYPE if a non-integer is used to access an array
39202
  */
39203
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
39204
39205
  /**
39206
   * Consumes the array and returns a string_view instance corresponding to the
39207
   * array as represented in JSON. It points inside the original document.
39208
   */
39209
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
39210
39211
  /**
39212
   * Get the value at the given index. This function has linear-time complexity.
39213
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
39214
   *
39215
   * @return The value at the given index, or:
39216
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
39217
   */
39218
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
39219
protected:
39220
  /**
39221
   * Go to the end of the array, no matter where you are right now.
39222
   */
39223
  simdjson_inline error_code consume() noexcept;
39224
39225
  /**
39226
   * Begin array iteration.
39227
   *
39228
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
39229
   *        resulting array.
39230
   * @error INCORRECT_TYPE if the iterator is not at [.
39231
   */
39232
  static simdjson_inline simdjson_result<array> start(value_iterator &iter) noexcept;
39233
  /**
39234
   * Begin array iteration from the root.
39235
   *
39236
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
39237
   *        resulting array.
39238
   * @error INCORRECT_TYPE if the iterator is not at [.
39239
   * @error TAPE_ERROR if there is no closing ] at the end of the document.
39240
   */
39241
  static simdjson_inline simdjson_result<array> start_root(value_iterator &iter) noexcept;
39242
  /**
39243
   * Begin array iteration.
39244
   *
39245
   * This version of the method should be called after the initial [ has been verified, and is
39246
   * intended for use by switch statements that check the type of a value.
39247
   *
39248
   * @param iter The iterator. Must be after the initial [. Will be *moved* into the resulting array.
39249
   */
39250
  static simdjson_inline simdjson_result<array> started(value_iterator &iter) noexcept;
39251
39252
  /**
39253
   * Create an array at the given Internal array creation. Call array::start() or array::started() instead of this.
39254
   *
39255
   * @param iter The iterator. Must either be at the start of the first element with iter.is_alive()
39256
   *        == true, or past the [] with is_alive() == false if the array is empty. Will be *moved*
39257
   *        into the resulting array.
39258
   */
39259
  simdjson_inline array(const value_iterator &iter) noexcept;
39260
39261
  /**
39262
   * Iterator marking current position.
39263
   *
39264
   * iter.is_alive() == false indicates iteration is complete.
39265
   */
39266
  value_iterator iter{};
39267
39268
  friend class value;
39269
  friend class document;
39270
  friend struct simdjson_result<value>;
39271
  friend struct simdjson_result<array>;
39272
  friend class array_iterator;
39273
};
39274
39275
} // namespace ondemand
39276
} // namespace fallback
39277
} // namespace simdjson
39278
39279
namespace simdjson {
39280
39281
template<>
39282
struct simdjson_result<fallback::ondemand::array> : public fallback::implementation_simdjson_result_base<fallback::ondemand::array> {
39283
public:
39284
  simdjson_inline simdjson_result(fallback::ondemand::array &&value) noexcept; ///< @private
39285
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
39286
  simdjson_inline simdjson_result() noexcept = default;
39287
39288
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> begin() noexcept;
39289
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> end() noexcept;
39290
  inline simdjson_result<size_t> count_elements() & noexcept;
39291
  inline simdjson_result<bool> is_empty() & noexcept;
39292
  inline simdjson_result<bool> reset() & noexcept;
39293
  simdjson_inline simdjson_result<fallback::ondemand::value> at(size_t index) noexcept;
39294
  simdjson_inline simdjson_result<fallback::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
39295
  simdjson_inline simdjson_result<fallback::ondemand::value> at_path(std::string_view json_path) noexcept;
39296
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
39297
39298
};
39299
39300
} // namespace simdjson
39301
39302
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
39303
/* end file simdjson/generic/ondemand/array.h for fallback */
39304
/* including simdjson/generic/ondemand/array_iterator.h for fallback: #include "simdjson/generic/ondemand/array_iterator.h" */
39305
/* begin file simdjson/generic/ondemand/array_iterator.h for fallback */
39306
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
39307
39308
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
39309
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H */
39310
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
39311
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
39312
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
39313
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
39314
39315
39316
namespace simdjson {
39317
namespace fallback {
39318
namespace ondemand {
39319
39320
/**
39321
 * A forward-only JSON array.
39322
 *
39323
 * This is an input_iterator, meaning:
39324
 * - It is forward-only
39325
 * - * must be called exactly once per element.
39326
 * - ++ must be called exactly once in between each * (*, ++, *, ++, * ...)
39327
 */
39328
class array_iterator {
39329
public:
39330
  /** Create a new, invalid array iterator. */
39331
  simdjson_inline array_iterator() noexcept = default;
39332
39333
  //
39334
  // Iterator interface
39335
  //
39336
39337
  /**
39338
   * Get the current element.
39339
   *
39340
   * Part of the std::iterator interface.
39341
   */
39342
  simdjson_inline simdjson_result<value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
39343
  /**
39344
   * Check if we are at the end of the JSON.
39345
   *
39346
   * Part of the std::iterator interface.
39347
   *
39348
   * @return true if there are no more elements in the JSON array.
39349
   */
39350
  simdjson_inline bool operator==(const array_iterator &) const noexcept;
39351
  /**
39352
   * Check if there are more elements in the JSON array.
39353
   *
39354
   * Part of the std::iterator interface.
39355
   *
39356
   * @return true if there are more elements in the JSON array.
39357
   */
39358
  simdjson_inline bool operator!=(const array_iterator &) const noexcept;
39359
  /**
39360
   * Move to the next element.
39361
   *
39362
   * Part of the std::iterator interface.
39363
   */
39364
  simdjson_inline array_iterator &operator++() noexcept;
39365
39366
private:
39367
  value_iterator iter{};
39368
39369
  simdjson_inline array_iterator(const value_iterator &iter) noexcept;
39370
39371
  friend class array;
39372
  friend class value;
39373
  friend struct simdjson_result<array_iterator>;
39374
};
39375
39376
} // namespace ondemand
39377
} // namespace fallback
39378
} // namespace simdjson
39379
39380
namespace simdjson {
39381
39382
template<>
39383
struct simdjson_result<fallback::ondemand::array_iterator> : public fallback::implementation_simdjson_result_base<fallback::ondemand::array_iterator> {
39384
public:
39385
  simdjson_inline simdjson_result(fallback::ondemand::array_iterator &&value) noexcept; ///< @private
39386
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
39387
  simdjson_inline simdjson_result() noexcept = default;
39388
39389
  //
39390
  // Iterator interface
39391
  //
39392
39393
  simdjson_inline simdjson_result<fallback::ondemand::value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
39394
  simdjson_inline bool operator==(const simdjson_result<fallback::ondemand::array_iterator> &) const noexcept;
39395
  simdjson_inline bool operator!=(const simdjson_result<fallback::ondemand::array_iterator> &) const noexcept;
39396
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> &operator++() noexcept;
39397
};
39398
39399
} // namespace simdjson
39400
39401
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
39402
/* end file simdjson/generic/ondemand/array_iterator.h for fallback */
39403
/* including simdjson/generic/ondemand/document.h for fallback: #include "simdjson/generic/ondemand/document.h" */
39404
/* begin file simdjson/generic/ondemand/document.h for fallback */
39405
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
39406
39407
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
39408
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */
39409
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
39410
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
39411
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
39412
39413
namespace simdjson {
39414
namespace fallback {
39415
namespace ondemand {
39416
39417
/**
39418
 * A JSON document. It holds a json_iterator instance.
39419
 *
39420
 * Used by tokens to get text, and string buffer location.
39421
 *
39422
 * You must keep the document around during iteration.
39423
 */
39424
class document {
39425
public:
39426
  /**
39427
   * Create a new invalid document.
39428
   *
39429
   * Exists so you can declare a variable and later assign to it before use.
39430
   */
39431
0
  simdjson_inline document() noexcept = default;
39432
  simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
39433
0
  simdjson_inline document(document &&other) noexcept = default;
39434
  simdjson_inline document &operator=(const document &other) noexcept = delete;
39435
0
  simdjson_inline document &operator=(document &&other) noexcept = default;
39436
39437
  /**
39438
   * Cast this JSON value to an array.
39439
   *
39440
   * @returns An object that can be used to iterate the array.
39441
   * @returns INCORRECT_TYPE If the JSON value is not an array.
39442
   */
39443
  simdjson_inline simdjson_result<array> get_array() & noexcept;
39444
  /**
39445
   * Cast this JSON value to an object.
39446
   *
39447
   * @returns An object that can be used to look up or iterate fields.
39448
   * @returns INCORRECT_TYPE If the JSON value is not an object.
39449
   */
39450
  simdjson_inline simdjson_result<object> get_object() & noexcept;
39451
  /**
39452
   * Cast this JSON value to an unsigned integer.
39453
   *
39454
   * @returns A signed 64-bit integer.
39455
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
39456
   */
39457
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
39458
  /**
39459
   * Cast this JSON value (inside string) to an unsigned integer.
39460
   *
39461
   * @returns A signed 64-bit integer.
39462
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
39463
   */
39464
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
39465
  /**
39466
   * Cast this JSON value to a signed integer.
39467
   *
39468
   * @returns A signed 64-bit integer.
39469
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
39470
   */
39471
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
39472
  /**
39473
   * Cast this JSON value (inside string) to a signed integer.
39474
   *
39475
   * @returns A signed 64-bit integer.
39476
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
39477
   */
39478
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
39479
  /**
39480
   * Cast this JSON value to a double.
39481
   *
39482
   * @returns A double.
39483
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
39484
   */
39485
  simdjson_inline simdjson_result<double> get_double() noexcept;
39486
39487
  /**
39488
   * Cast this JSON value (inside string) to a double.
39489
   *
39490
   * @returns A double.
39491
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
39492
   */
39493
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
39494
  /**
39495
   * Cast this JSON value to a string.
39496
   *
39497
   * The string is guaranteed to be valid UTF-8.
39498
   *
39499
   * Important: Calling get_string() twice on the same document is an error.
39500
   *
39501
   * @param Whether to allow a replacement character for unmatched surrogate pairs.
39502
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
39503
   *          time it parses a document or when it is destroyed.
39504
   * @returns INCORRECT_TYPE if the JSON value is not a string.
39505
   */
39506
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
39507
  /**
39508
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
39509
   *
39510
   * The string is guaranteed to be valid UTF-8.
39511
   *
39512
   * Important: a value should be consumed once. Calling get_string() twice on the same value
39513
   * is an error.
39514
   *
39515
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
39516
   * We recommend you avoid allocating an std::string unless you need to.
39517
   *
39518
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
39519
   */
39520
  template <typename string_type>
39521
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
39522
  /**
39523
   * Cast this JSON value to a string.
39524
   *
39525
   * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/
39526
   *
39527
   * Important: Calling get_wobbly_string() twice on the same document is an error.
39528
   *
39529
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
39530
   *          time it parses a document or when it is destroyed.
39531
   * @returns INCORRECT_TYPE if the JSON value is not a string.
39532
   */
39533
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
39534
  /**
39535
   * Cast this JSON value to a raw_json_string.
39536
   *
39537
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
39538
   *
39539
   * @returns A pointer to the raw JSON for the given string.
39540
   * @returns INCORRECT_TYPE if the JSON value is not a string.
39541
   */
39542
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
39543
  /**
39544
   * Cast this JSON value to a bool.
39545
   *
39546
   * @returns A bool value.
39547
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
39548
   */
39549
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
39550
  /**
39551
   * Cast this JSON value to a value when the document is an object or an array.
39552
   *
39553
   * You must not have begun iterating through the object or array. When
39554
   * SIMDJSON_DEVELOPMENT_CHECKS is set to 1 (which is the case when building in Debug mode
39555
   * by default), and you have already begun iterating,
39556
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
39557
   * rewind() to reset the document to its initial state before calling this method.
39558
   *
39559
   * @returns A value if a JSON array or object cannot be found.
39560
   * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
39561
   */
39562
  simdjson_inline simdjson_result<value> get_value() noexcept;
39563
39564
  /**
39565
   * Checks if this JSON value is null.  If and only if the value is
39566
   * null, then it is consumed (we advance). If we find a token that
39567
   * begins with 'n' but is not 'null', then an error is returned.
39568
   *
39569
   * @returns Whether the value is null.
39570
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
39571
   */
39572
  simdjson_inline simdjson_result<bool> is_null() noexcept;
39573
39574
  /**
39575
   * Get this value as the given type.
39576
   *
39577
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
39578
   *
39579
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
39580
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
39581
   *
39582
   * @returns A value of the given type, parsed from the JSON.
39583
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
39584
   */
39585
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
39586
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
39587
    // immediately fail.
39588
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
39589
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
39590
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
39591
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
39592
      " You may also add support for custom types, see our documentation.");
39593
  }
39594
  /** @overload template<typename T> simdjson_result<T> get() & noexcept */
39595
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
39596
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
39597
    // immediately fail.
39598
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
39599
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
39600
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
39601
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
39602
      " You may also add support for custom types, see our documentation.");
39603
  }
39604
39605
  /**
39606
   * Get this value as the given type.
39607
   *
39608
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
39609
   *
39610
   * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
39611
   *
39612
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
39613
   * @returns INCORRECT_TYPE If the JSON value is not an object.
39614
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
39615
   */
39616
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
39617
  /** @overload template<typename T> error_code get(T &out) & noexcept */
39618
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
39619
39620
#if SIMDJSON_EXCEPTIONS
39621
  /**
39622
   * Cast this JSON value to an instance of type T. The programmer is responsible for
39623
   * providing an implementation of get<T> for the type T, if T is not one of the types
39624
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.)
39625
   *
39626
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
39627
   *
39628
   * @returns An instance of type T
39629
   */
39630
  template <class T>
39631
  explicit simdjson_inline operator T() noexcept(false);
39632
  /**
39633
   * Cast this JSON value to an array.
39634
   *
39635
   * @returns An object that can be used to iterate the array.
39636
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
39637
   */
39638
  simdjson_inline operator array() & noexcept(false);
39639
  /**
39640
   * Cast this JSON value to an object.
39641
   *
39642
   * @returns An object that can be used to look up or iterate fields.
39643
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
39644
   */
39645
  simdjson_inline operator object() & noexcept(false);
39646
  /**
39647
   * Cast this JSON value to an unsigned integer.
39648
   *
39649
   * @returns A signed 64-bit integer.
39650
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
39651
   */
39652
  simdjson_inline operator uint64_t() noexcept(false);
39653
  /**
39654
   * Cast this JSON value to a signed integer.
39655
   *
39656
   * @returns A signed 64-bit integer.
39657
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
39658
   */
39659
  simdjson_inline operator int64_t() noexcept(false);
39660
  /**
39661
   * Cast this JSON value to a double.
39662
   *
39663
   * @returns A double.
39664
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
39665
   */
39666
  simdjson_inline operator double() noexcept(false);
39667
  /**
39668
   * Cast this JSON value to a string.
39669
   *
39670
   * The string is guaranteed to be valid UTF-8.
39671
   *
39672
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
39673
   *          time it parses a document or when it is destroyed.
39674
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
39675
   */
39676
  simdjson_inline operator std::string_view() noexcept(false);
39677
  /**
39678
   * Cast this JSON value to a raw_json_string.
39679
   *
39680
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
39681
   *
39682
   * @returns A pointer to the raw JSON for the given string.
39683
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
39684
   */
39685
  simdjson_inline operator raw_json_string() noexcept(false);
39686
  /**
39687
   * Cast this JSON value to a bool.
39688
   *
39689
   * @returns A bool value.
39690
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
39691
   */
39692
  simdjson_inline operator bool() noexcept(false);
39693
  /**
39694
   * Cast this JSON value to a value when the document is an object or an array.
39695
   *
39696
   * You must not have begun iterating through the object or array. When
39697
   * SIMDJSON_DEVELOPMENT_CHECKS is defined, and you have already begun iterating,
39698
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
39699
   * rewind() to reset the document to its initial state before calling this method.
39700
   *
39701
   * @returns A value value if a JSON array or object cannot be found.
39702
   * @exception SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
39703
   */
39704
  simdjson_inline operator value() noexcept(false);
39705
#endif
39706
  /**
39707
   * This method scans the array and counts the number of elements.
39708
   * The count_elements method should always be called before you have begun
39709
   * iterating through the array: it is expected that you are pointing at
39710
   * the beginning of the array.
39711
   * The runtime complexity is linear in the size of the array. After
39712
   * calling this function, if successful, the array is 'rewinded' at its
39713
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
39714
   * there is a missing comma), then an error is returned and it is no longer
39715
   * safe to continue.
39716
   */
39717
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
39718
   /**
39719
   * This method scans the object and counts the number of key-value pairs.
39720
   * The count_fields method should always be called before you have begun
39721
   * iterating through the object: it is expected that you are pointing at
39722
   * the beginning of the object.
39723
   * The runtime complexity is linear in the size of the object. After
39724
   * calling this function, if successful, the object is 'rewinded' at its
39725
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
39726
   * there is a missing comma), then an error is returned and it is no longer
39727
   * safe to continue.
39728
   *
39729
   * To check that an object is empty, it is more performant to use
39730
   * the is_empty() method.
39731
   */
39732
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
39733
  /**
39734
   * Get the value at the given index in the array. This function has linear-time complexity.
39735
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
39736
   *
39737
   * @return The value at the given index, or:
39738
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
39739
   */
39740
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
39741
  /**
39742
   * Begin array iteration.
39743
   *
39744
   * Part of the std::iterable interface.
39745
   */
39746
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
39747
  /**
39748
   * Sentinel representing the end of the array.
39749
   *
39750
   * Part of the std::iterable interface.
39751
   */
39752
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
39753
39754
  /**
39755
   * Look up a field by name on an object (order-sensitive).
39756
   *
39757
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
39758
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
39759
   *
39760
   * ```c++
39761
   * simdjson::ondemand::parser parser;
39762
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
39763
   * double z = obj.find_field("z");
39764
   * double y = obj.find_field("y");
39765
   * double x = obj.find_field("x");
39766
   * ```
39767
   *
39768
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
39769
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
39770
   *
39771
   *
39772
   * You must consume the fields on an object one at a time. A request for a new key
39773
   * invalidates previous field values: it makes them unsafe. E.g., the array
39774
   * given by content["bids"].get_array() should not be accessed after you have called
39775
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
39776
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
39777
   * OUT_OF_ORDER_ITERATION error is generated.
39778
   *
39779
   * You are expected to access keys only once. You should access the value corresponding to
39780
   * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
39781
   * is an error.
39782
   *
39783
   * @param key The key to look up.
39784
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
39785
   */
39786
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
39787
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
39788
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
39789
39790
  /**
39791
   * Look up a field by name on an object, without regard to key order.
39792
   *
39793
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
39794
   * and often appears negligible. It starts out normally, starting out at the last field; but if
39795
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
39796
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
39797
   * in question is large. The fact that the extra code is there also bumps the executable size.
39798
   *
39799
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
39800
   * default behavior failed to look up a field just because it was in the wrong order--and many
39801
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
39802
   *
39803
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
39804
   * field was not there when they are not in order).
39805
   *
39806
   * You must consume the fields on an object one at a time. A request for a new key
39807
   * invalidates previous field values: it makes them unsafe. E.g., the array
39808
   * given by content["bids"].get_array() should not be accessed after you have called
39809
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
39810
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
39811
   * OUT_OF_ORDER_ITERATION error is generated.
39812
   *
39813
   * You are expected to access keys only once. You should access the value corresponding to a key
39814
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
39815
   * is an error.
39816
   *
39817
   * @param key The key to look up.
39818
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
39819
   */
39820
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
39821
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
39822
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
39823
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
39824
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
39825
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
39826
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
39827
39828
  /**
39829
   * Get the type of this JSON value. It does not validate or consume the value.
39830
   * E.g., you must still call "is_null()" to check that a value is null even if
39831
   * "type()" returns json_type::null.
39832
   *
39833
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
39834
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
39835
   * let it throw an exception).
39836
   *
39837
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
39838
   */
39839
  simdjson_inline simdjson_result<json_type> type() noexcept;
39840
39841
  /**
39842
   * Checks whether the document is a scalar (string, number, null, Boolean).
39843
   * Returns false when there it is an array or object.
39844
   *
39845
   * @returns true if the type is string, number, null, Boolean
39846
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
39847
   */
39848
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
39849
39850
  /**
39851
   * Checks whether the document is a string.
39852
   *
39853
   * @returns true if the type is string
39854
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
39855
   */
39856
  simdjson_inline simdjson_result<bool> is_string() noexcept;
39857
39858
  /**
39859
   * Checks whether the document is a negative number.
39860
   *
39861
   * @returns true if the number if negative.
39862
   */
39863
  simdjson_inline bool is_negative() noexcept;
39864
  /**
39865
   * Checks whether the document is an integer number. Note that
39866
   * this requires to partially parse the number string. If
39867
   * the value is determined to be an integer, it may still
39868
   * not parse properly as an integer in subsequent steps
39869
   * (e.g., it might overflow).
39870
   *
39871
   * @returns true if the number if negative.
39872
   */
39873
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
39874
  /**
39875
   * Determine the number type (integer or floating-point number) as quickly
39876
   * as possible. This function does not fully validate the input. It is
39877
   * useful when you only need to classify the numbers, without parsing them.
39878
   *
39879
   * If you are planning to retrieve the value or you need full validation,
39880
   * consider using the get_number() method instead: it will fully parse
39881
   * and validate the input, and give you access to the type:
39882
   * get_number().get_number_type().
39883
   *
39884
   * get_number_type() is number_type::unsigned_integer if we have
39885
   * an integer greater or equal to 9223372036854775808 and no larger than 18446744073709551615.
39886
   * get_number_type() is number_type::signed_integer if we have an
39887
   * integer that is less than 9223372036854775808 and greater or equal to -9223372036854775808.
39888
   * get_number_type() is number_type::big_integer if we have an integer outside
39889
   * of those ranges (either larger than 18446744073709551615 or smaller than -9223372036854775808).
39890
   * Otherwise, get_number_type() has value number_type::floating_point_number
39891
   *
39892
   * This function requires processing the number string, but it is expected
39893
   * to be faster than get_number().get_number_type() because it is does not
39894
   * parse the number value.
39895
   *
39896
   * @returns the type of the number
39897
   */
39898
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
39899
39900
  /**
39901
   * Attempt to parse an ondemand::number. An ondemand::number may
39902
   * contain an integer value or a floating-point value, the simdjson
39903
   * library will autodetect the type. Thus it is a dynamically typed
39904
   * number. Before accessing the value, you must determine the detected
39905
   * type.
39906
   *
39907
   * number.get_number_type() is number_type::signed_integer if we have
39908
   * an integer in [-9223372036854775808,9223372036854775808)
39909
   * You can recover the value by calling number.get_int64() and you
39910
   * have that number.is_int64() is true.
39911
   *
39912
   * number.get_number_type() is number_type::unsigned_integer if we have
39913
   * an integer in [9223372036854775808,18446744073709551616)
39914
   * You can recover the value by calling number.get_uint64() and you
39915
   * have that number.is_uint64() is true.
39916
   *
39917
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
39918
   * and we have a binary64 number.
39919
   * You can recover the value by calling number.get_double() and you
39920
   * have that number.is_double() is true.
39921
   *
39922
   * You must check the type before accessing the value: it is an error
39923
   * to call "get_int64()" when number.get_number_type() is not
39924
   * number_type::signed_integer and when number.is_int64() is false.
39925
   */
39926
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
39927
39928
  /**
39929
   * Get the raw JSON for this token.
39930
   *
39931
   * The string_view will always point into the input buffer.
39932
   *
39933
   * The string_view will start at the beginning of the token, and include the entire token
39934
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
39935
   * string token always begins with a " and is always terminated by the final ", possibly
39936
   * followed by a number of spaces.
39937
   *
39938
   * The string_view is *not* null-terminated. If this is a scalar (string, number,
39939
   * boolean, or null), the character after the end of the string_view may be the padded buffer.
39940
   *
39941
   * Tokens include:
39942
   * - {
39943
   * - [
39944
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
39945
   * - -1.2e-100
39946
   * - true
39947
   * - false
39948
   * - null
39949
   */
39950
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
39951
39952
  /**
39953
   * Reset the iterator inside the document instance so we are pointing back at the
39954
   * beginning of the document, as if it had just been created. It invalidates all
39955
   * values, objects and arrays that you have created so far (including unescaped strings).
39956
   */
39957
  inline void rewind() noexcept;
39958
  /**
39959
   * Returns debugging information.
39960
   */
39961
  inline std::string to_debug_string() noexcept;
39962
  /**
39963
   * Some unrecoverable error conditions may render the document instance unusable.
39964
   * The is_alive() method returns true when the document is still suitable.
39965
   */
39966
  inline bool is_alive() noexcept;
39967
39968
  /**
39969
   * Returns the current location in the document if in bounds.
39970
   */
39971
  inline simdjson_result<const char *> current_location() const noexcept;
39972
39973
  /**
39974
   * Returns true if this document has been fully parsed.
39975
   * If you have consumed the whole document and at_end() returns
39976
   * false, then there may be trailing content.
39977
   */
39978
  inline bool at_end() const noexcept;
39979
39980
  /**
39981
   * Returns the current depth in the document if in bounds.
39982
   *
39983
   * E.g.,
39984
   *  0 = finished with document
39985
   *  1 = document root value (could be [ or {, not yet known)
39986
   *  2 = , or } inside root array/object
39987
   *  3 = key or value inside root array/object.
39988
   */
39989
  simdjson_inline int32_t current_depth() const noexcept;
39990
39991
  /**
39992
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
39993
   * https://tools.ietf.org/html/rfc6901 standard.
39994
   *
39995
   *   ondemand::parser parser;
39996
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
39997
   *   auto doc = parser.iterate(json);
39998
   *   doc.at_pointer("/foo/a/1") == 20
39999
   *
40000
   * It is allowed for a key to be the empty string:
40001
   *
40002
   *   ondemand::parser parser;
40003
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
40004
   *   auto doc = parser.iterate(json);
40005
   *   doc.at_pointer("//a/1") == 20
40006
   *
40007
   * Key values are matched exactly, without unescaping or Unicode normalization.
40008
   * We do a byte-by-byte comparison. E.g.
40009
   *
40010
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
40011
   *   auto doc = parser.iterate(json);
40012
   *   doc.at_pointer("/\\u00E9") == 123
40013
   *   doc.at_pointer((const char*)u8"/\u00E9") returns an error (NO_SUCH_FIELD)
40014
   *
40015
   * Note that at_pointer() automatically calls rewind between each call. Thus
40016
   * all values, objects and arrays that you have created so far (including unescaped strings)
40017
   * are invalidated. After calling at_pointer, you need to consume the result: string values
40018
   * should be stored in your own variables, arrays should be decoded and stored in your own array-like
40019
   * structures and so forth.
40020
   *
40021
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
40022
   *
40023
   * @return The value associated with the given JSON pointer, or:
40024
   *         - NO_SUCH_FIELD if a field does not exist in an object
40025
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
40026
   *         - INCORRECT_TYPE if a non-integer is used to access an array
40027
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
40028
   *         - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
40029
   */
40030
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
40031
40032
  /**
40033
   * Get the value associated with the given JSONPath expression. We only support
40034
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
40035
   * names and array indices.
40036
   *
40037
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
40038
   *
40039
   * Key values are matched exactly, without unescaping or Unicode normalization.
40040
   * We do a byte-by-byte comparison. E.g.
40041
   *
40042
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
40043
   *   auto doc = parser.iterate(json);
40044
   *   doc.at_path(".\\u00E9") == 123
40045
   *   doc.at_path((const char*)u8".\u00E9") returns an error (NO_SUCH_FIELD)
40046
   *
40047
   * @return The value associated with the given JSONPath expression, or:
40048
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
40049
   *         - NO_SUCH_FIELD if a field does not exist in an object
40050
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
40051
   *         - INCORRECT_TYPE if a non-integer is used to access an array
40052
   */
40053
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
40054
40055
  /**
40056
   * Consumes the document and returns a string_view instance corresponding to the
40057
   * document as represented in JSON. It points inside the original byte array containing
40058
   * the JSON document.
40059
   */
40060
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
40061
protected:
40062
  /**
40063
   * Consumes the document.
40064
   */
40065
  simdjson_inline error_code consume() noexcept;
40066
40067
  simdjson_inline document(ondemand::json_iterator &&iter) noexcept;
40068
  simdjson_inline const uint8_t *text(uint32_t idx) const noexcept;
40069
40070
  simdjson_inline value_iterator resume_value_iterator() noexcept;
40071
  simdjson_inline value_iterator get_root_value_iterator() noexcept;
40072
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
40073
  static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept;
40074
40075
  //
40076
  // Fields
40077
  //
40078
  json_iterator iter{}; ///< Current position in the document
40079
  static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0
40080
40081
  friend class array_iterator;
40082
  friend class value;
40083
  friend class ondemand::parser;
40084
  friend class object;
40085
  friend class array;
40086
  friend class field;
40087
  friend class token;
40088
  friend class document_stream;
40089
  friend class document_reference;
40090
};
40091
40092
40093
/**
40094
 * A document_reference is a thin wrapper around a document reference instance.
40095
 */
40096
class document_reference {
40097
public:
40098
  simdjson_inline document_reference() noexcept;
40099
  simdjson_inline document_reference(document &d) noexcept;
40100
  simdjson_inline document_reference(const document_reference &other) noexcept = default;
40101
  simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default;
40102
  simdjson_inline void rewind() noexcept;
40103
  simdjson_inline simdjson_result<array> get_array() & noexcept;
40104
  simdjson_inline simdjson_result<object> get_object() & noexcept;
40105
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
40106
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
40107
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
40108
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
40109
  simdjson_inline simdjson_result<double> get_double() noexcept;
40110
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
40111
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
40112
  template <typename string_type>
40113
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
40114
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
40115
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
40116
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
40117
  simdjson_inline simdjson_result<value> get_value() noexcept;
40118
40119
  simdjson_inline simdjson_result<bool> is_null() noexcept;
40120
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
40121
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
40122
  simdjson_inline operator document&() const noexcept;
40123
#if SIMDJSON_EXCEPTIONS
40124
  template <class T>
40125
  explicit simdjson_inline operator T() noexcept(false);
40126
  simdjson_inline operator array() & noexcept(false);
40127
  simdjson_inline operator object() & noexcept(false);
40128
  simdjson_inline operator uint64_t() noexcept(false);
40129
  simdjson_inline operator int64_t() noexcept(false);
40130
  simdjson_inline operator double() noexcept(false);
40131
  simdjson_inline operator std::string_view() noexcept(false);
40132
  simdjson_inline operator raw_json_string() noexcept(false);
40133
  simdjson_inline operator bool() noexcept(false);
40134
  simdjson_inline operator value() noexcept(false);
40135
#endif
40136
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
40137
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
40138
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
40139
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
40140
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
40141
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
40142
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
40143
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
40144
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
40145
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
40146
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
40147
40148
  simdjson_inline simdjson_result<json_type> type() noexcept;
40149
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
40150
  simdjson_inline simdjson_result<bool> is_string() noexcept;
40151
40152
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
40153
  simdjson_inline int32_t current_depth() const noexcept;
40154
  simdjson_inline bool is_negative() noexcept;
40155
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
40156
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
40157
  simdjson_inline simdjson_result<number> get_number() noexcept;
40158
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
40159
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
40160
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
40161
40162
private:
40163
  document *doc{nullptr};
40164
};
40165
} // namespace ondemand
40166
} // namespace fallback
40167
} // namespace simdjson
40168
40169
namespace simdjson {
40170
40171
template<>
40172
struct simdjson_result<fallback::ondemand::document> : public fallback::implementation_simdjson_result_base<fallback::ondemand::document> {
40173
public:
40174
  simdjson_inline simdjson_result(fallback::ondemand::document &&value) noexcept; ///< @private
40175
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
40176
  simdjson_inline simdjson_result() noexcept = default;
40177
  simdjson_inline error_code rewind() noexcept;
40178
40179
  simdjson_inline simdjson_result<fallback::ondemand::array> get_array() & noexcept;
40180
  simdjson_inline simdjson_result<fallback::ondemand::object> get_object() & noexcept;
40181
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
40182
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
40183
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
40184
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
40185
  simdjson_inline simdjson_result<double> get_double() noexcept;
40186
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
40187
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
40188
  template <typename string_type>
40189
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
40190
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
40191
  simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> get_raw_json_string() noexcept;
40192
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
40193
  simdjson_inline simdjson_result<fallback::ondemand::value> get_value() noexcept;
40194
  simdjson_inline simdjson_result<bool> is_null() noexcept;
40195
40196
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
40197
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept;
40198
40199
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
40200
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
40201
#if SIMDJSON_EXCEPTIONS
40202
  template <class T, typename std::enable_if<std::is_same<T, fallback::ondemand::document>::value == false>::type>
40203
  explicit simdjson_inline operator T() noexcept(false);
40204
  simdjson_inline operator fallback::ondemand::array() & noexcept(false);
40205
  simdjson_inline operator fallback::ondemand::object() & noexcept(false);
40206
  simdjson_inline operator uint64_t() noexcept(false);
40207
  simdjson_inline operator int64_t() noexcept(false);
40208
  simdjson_inline operator double() noexcept(false);
40209
  simdjson_inline operator std::string_view() noexcept(false);
40210
  simdjson_inline operator fallback::ondemand::raw_json_string() noexcept(false);
40211
  simdjson_inline operator bool() noexcept(false);
40212
  simdjson_inline operator fallback::ondemand::value() noexcept(false);
40213
#endif
40214
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
40215
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
40216
  simdjson_inline simdjson_result<fallback::ondemand::value> at(size_t index) & noexcept;
40217
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> begin() & noexcept;
40218
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> end() & noexcept;
40219
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(std::string_view key) & noexcept;
40220
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(const char *key) & noexcept;
40221
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](std::string_view key) & noexcept;
40222
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](const char *key) & noexcept;
40223
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
40224
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(const char *key) & noexcept;
40225
  simdjson_inline simdjson_result<fallback::ondemand::json_type> type() noexcept;
40226
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
40227
  simdjson_inline simdjson_result<bool> is_string() noexcept;
40228
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
40229
  simdjson_inline int32_t current_depth() const noexcept;
40230
  simdjson_inline bool at_end() const noexcept;
40231
  simdjson_inline bool is_negative() noexcept;
40232
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
40233
  simdjson_inline simdjson_result<fallback::number_type> get_number_type() noexcept;
40234
  simdjson_inline simdjson_result<fallback::ondemand::number> get_number() noexcept;
40235
  /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */
40236
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
40237
40238
  simdjson_inline simdjson_result<fallback::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
40239
  simdjson_inline simdjson_result<fallback::ondemand::value> at_path(std::string_view json_path) noexcept;
40240
};
40241
40242
40243
} // namespace simdjson
40244
40245
40246
40247
namespace simdjson {
40248
40249
template<>
40250
struct simdjson_result<fallback::ondemand::document_reference> : public fallback::implementation_simdjson_result_base<fallback::ondemand::document_reference> {
40251
public:
40252
  simdjson_inline simdjson_result(fallback::ondemand::document_reference value, error_code error) noexcept;
40253
  simdjson_inline simdjson_result() noexcept = default;
40254
  simdjson_inline error_code rewind() noexcept;
40255
40256
  simdjson_inline simdjson_result<fallback::ondemand::array> get_array() & noexcept;
40257
  simdjson_inline simdjson_result<fallback::ondemand::object> get_object() & noexcept;
40258
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
40259
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
40260
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
40261
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
40262
  simdjson_inline simdjson_result<double> get_double() noexcept;
40263
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
40264
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
40265
  template <typename string_type>
40266
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
40267
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
40268
  simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> get_raw_json_string() noexcept;
40269
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
40270
  simdjson_inline simdjson_result<fallback::ondemand::value> get_value() noexcept;
40271
  simdjson_inline simdjson_result<bool> is_null() noexcept;
40272
#if SIMDJSON_EXCEPTIONS
40273
  template <class T, typename std::enable_if<std::is_same<T, fallback::ondemand::document_reference>::value == false>::type>
40274
  explicit simdjson_inline operator T() noexcept(false);
40275
  simdjson_inline operator fallback::ondemand::array() & noexcept(false);
40276
  simdjson_inline operator fallback::ondemand::object() & noexcept(false);
40277
  simdjson_inline operator uint64_t() noexcept(false);
40278
  simdjson_inline operator int64_t() noexcept(false);
40279
  simdjson_inline operator double() noexcept(false);
40280
  simdjson_inline operator std::string_view() noexcept(false);
40281
  simdjson_inline operator fallback::ondemand::raw_json_string() noexcept(false);
40282
  simdjson_inline operator bool() noexcept(false);
40283
  simdjson_inline operator fallback::ondemand::value() noexcept(false);
40284
#endif
40285
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
40286
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
40287
  simdjson_inline simdjson_result<fallback::ondemand::value> at(size_t index) & noexcept;
40288
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> begin() & noexcept;
40289
  simdjson_inline simdjson_result<fallback::ondemand::array_iterator> end() & noexcept;
40290
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(std::string_view key) & noexcept;
40291
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(const char *key) & noexcept;
40292
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](std::string_view key) & noexcept;
40293
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](const char *key) & noexcept;
40294
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
40295
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(const char *key) & noexcept;
40296
  simdjson_inline simdjson_result<fallback::ondemand::json_type> type() noexcept;
40297
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
40298
  simdjson_inline simdjson_result<bool> is_string() noexcept;
40299
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
40300
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
40301
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
40302
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
40303
  simdjson_inline simdjson_result<fallback::number_type> get_number_type() noexcept;
40304
  simdjson_inline simdjson_result<fallback::ondemand::number> get_number() noexcept;
40305
  /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */
40306
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
40307
40308
  simdjson_inline simdjson_result<fallback::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
40309
  simdjson_inline simdjson_result<fallback::ondemand::value> at_path(std::string_view json_path) noexcept;
40310
};
40311
40312
40313
} // namespace simdjson
40314
40315
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
40316
/* end file simdjson/generic/ondemand/document.h for fallback */
40317
/* including simdjson/generic/ondemand/document_stream.h for fallback: #include "simdjson/generic/ondemand/document_stream.h" */
40318
/* begin file simdjson/generic/ondemand/document_stream.h for fallback */
40319
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
40320
40321
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
40322
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H */
40323
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
40324
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
40325
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
40326
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
40327
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
40328
40329
#ifdef SIMDJSON_THREADS_ENABLED
40330
#include <thread>
40331
#include <mutex>
40332
#include <condition_variable>
40333
#endif
40334
40335
namespace simdjson {
40336
namespace fallback {
40337
namespace ondemand {
40338
40339
#ifdef SIMDJSON_THREADS_ENABLED
40340
/** @private Custom worker class **/
40341
struct stage1_worker {
40342
  stage1_worker() noexcept = default;
40343
  stage1_worker(const stage1_worker&) = delete;
40344
  stage1_worker(stage1_worker&&) = delete;
40345
  stage1_worker operator=(const stage1_worker&) = delete;
40346
  ~stage1_worker();
40347
  /**
40348
   * We only start the thread when it is needed, not at object construction, this may throw.
40349
   * You should only call this once.
40350
   **/
40351
  void start_thread();
40352
  /**
40353
   * Start a stage 1 job. You should first call 'run', then 'finish'.
40354
   * You must call start_thread once before.
40355
   */
40356
  void run(document_stream * ds, parser * stage1, size_t next_batch_start);
40357
  /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
40358
  void finish();
40359
40360
private:
40361
40362
  /**
40363
   * Normally, we would never stop the thread. But we do in the destructor.
40364
   * This function is only safe assuming that you are not waiting for results. You
40365
   * should have called run, then finish, and be done.
40366
   **/
40367
  void stop_thread();
40368
40369
  std::thread thread{};
40370
  /** These three variables define the work done by the thread. **/
40371
  ondemand::parser * stage1_thread_parser{};
40372
  size_t _next_batch_start{};
40373
  document_stream * owner{};
40374
  /**
40375
   * We have two state variables. This could be streamlined to one variable in the future but
40376
   * we use two for clarity.
40377
   */
40378
  bool has_work{false};
40379
  bool can_work{true};
40380
40381
  /**
40382
   * We lock using a mutex.
40383
   */
40384
  std::mutex locking_mutex{};
40385
  std::condition_variable cond_var{};
40386
40387
  friend class document_stream;
40388
};
40389
#endif  // SIMDJSON_THREADS_ENABLED
40390
40391
/**
40392
 * A forward-only stream of documents.
40393
 *
40394
 * Produced by parser::iterate_many.
40395
 *
40396
 */
40397
class document_stream {
40398
public:
40399
  /**
40400
   * Construct an uninitialized document_stream.
40401
   *
40402
   *  ```c++
40403
   *  document_stream docs;
40404
   *  auto error = parser.iterate_many(json).get(docs);
40405
   *  ```
40406
   */
40407
  simdjson_inline document_stream() noexcept;
40408
  /** Move one document_stream to another. */
40409
  simdjson_inline document_stream(document_stream &&other) noexcept = default;
40410
  /** Move one document_stream to another. */
40411
  simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
40412
40413
  simdjson_inline ~document_stream() noexcept;
40414
40415
  /**
40416
   * Returns the input size in bytes.
40417
   */
40418
  inline size_t size_in_bytes() const noexcept;
40419
40420
  /**
40421
   * After iterating through the stream, this method
40422
   * returns the number of bytes that were not parsed at the end
40423
   * of the stream. If truncated_bytes() differs from zero,
40424
   * then the input was truncated maybe because incomplete JSON
40425
   * documents were found at the end of the stream. You
40426
   * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
40427
   *
40428
   * You should only call truncated_bytes() after streaming through all
40429
   * documents, like so:
40430
   *
40431
   *   document_stream stream = parser.iterate_many(json,window);
40432
   *   for(auto & doc : stream) {
40433
   *      // do something with doc
40434
   *   }
40435
   *   size_t truncated = stream.truncated_bytes();
40436
   *
40437
   */
40438
  inline size_t truncated_bytes() const noexcept;
40439
40440
  class iterator {
40441
  public:
40442
    using value_type = simdjson_result<document>;
40443
    using reference  = simdjson_result<ondemand::document_reference>;
40444
    using pointer    = void;
40445
    using difference_type   = std::ptrdiff_t;
40446
    using iterator_category = std::input_iterator_tag;
40447
40448
    /**
40449
     * Default constructor.
40450
     */
40451
    simdjson_inline iterator() noexcept;
40452
    /**
40453
     * Get the current document (or error).
40454
     */
40455
    simdjson_inline reference operator*() noexcept;
40456
    /**
40457
     * Advance to the next document (prefix).
40458
     */
40459
    inline iterator& operator++() noexcept;
40460
    /**
40461
     * Check if we're at the end yet.
40462
     * @param other the end iterator to compare to.
40463
     */
40464
    simdjson_inline bool operator!=(const iterator &other) const noexcept;
40465
    /**
40466
     * @private
40467
     *
40468
     * Gives the current index in the input document in bytes.
40469
     *
40470
     *   document_stream stream = parser.parse_many(json,window);
40471
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
40472
     *      auto doc = *i;
40473
     *      size_t index = i.current_index();
40474
     *   }
40475
     *
40476
     * This function (current_index()) is experimental and the usage
40477
     * may change in future versions of simdjson: we find the API somewhat
40478
     * awkward and we would like to offer something friendlier.
40479
     */
40480
     simdjson_inline size_t current_index() const noexcept;
40481
40482
     /**
40483
     * @private
40484
     *
40485
     * Gives a view of the current document at the current position.
40486
     *
40487
     *   document_stream stream = parser.iterate_many(json,window);
40488
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
40489
     *      std::string_view v = i.source();
40490
     *   }
40491
     *
40492
     * The returned string_view instance is simply a map to the (unparsed)
40493
     * source string: it may thus include white-space characters and all manner
40494
     * of padding.
40495
     *
40496
     * This function (source()) is experimental and the usage
40497
     * may change in future versions of simdjson: we find the API somewhat
40498
     * awkward and we would like to offer something friendlier.
40499
     *
40500
     */
40501
     simdjson_inline std::string_view source() const noexcept;
40502
40503
    /**
40504
     * Returns error of the stream (if any).
40505
     */
40506
     inline error_code error() const noexcept;
40507
40508
  private:
40509
    simdjson_inline iterator(document_stream *s, bool finished) noexcept;
40510
    /** The document_stream we're iterating through. */
40511
    document_stream* stream;
40512
    /** Whether we're finished or not. */
40513
    bool finished;
40514
40515
    friend class document;
40516
    friend class document_stream;
40517
    friend class json_iterator;
40518
  };
40519
40520
  /**
40521
   * Start iterating the documents in the stream.
40522
   */
40523
  simdjson_inline iterator begin() noexcept;
40524
  /**
40525
   * The end of the stream, for iterator comparison purposes.
40526
   */
40527
  simdjson_inline iterator end() noexcept;
40528
40529
private:
40530
40531
  document_stream &operator=(const document_stream &) = delete; // Disallow copying
40532
  document_stream(const document_stream &other) = delete; // Disallow copying
40533
40534
  /**
40535
   * Construct a document_stream. Does not allocate or parse anything until the iterator is
40536
   * used.
40537
   *
40538
   * @param parser is a reference to the parser instance used to generate this document_stream
40539
   * @param buf is the raw byte buffer we need to process
40540
   * @param len is the length of the raw byte buffer in bytes
40541
   * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
40542
   */
40543
  simdjson_inline document_stream(
40544
    ondemand::parser &parser,
40545
    const uint8_t *buf,
40546
    size_t len,
40547
    size_t batch_size,
40548
    bool allow_comma_separated
40549
  ) noexcept;
40550
40551
  /**
40552
   * Parse the first document in the buffer. Used by begin(), to handle allocation and
40553
   * initialization.
40554
   */
40555
  inline void start() noexcept;
40556
40557
  /**
40558
   * Parse the next document found in the buffer previously given to document_stream.
40559
   *
40560
   * The content should be a valid JSON document encoded as UTF-8. If there is a
40561
   * UTF-8 BOM, the parser skips it.
40562
   *
40563
   * You do NOT need to pre-allocate a parser.  This function takes care of
40564
   * pre-allocating a capacity defined by the batch_size defined when creating the
40565
   * document_stream object.
40566
   *
40567
   * The function returns simdjson::EMPTY if there is no more data to be parsed.
40568
   *
40569
   * The function returns simdjson::SUCCESS (as integer = 0) in case of success
40570
   * and indicates that the buffer has successfully been parsed to the end.
40571
   * Every document it contained has been parsed without error.
40572
   *
40573
   * The function returns an error code from simdjson/simdjson.h in case of failure
40574
   * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
40575
   * the simdjson::error_message function converts these error codes into a string).
40576
   *
40577
   * You can also check validity by calling parser.is_valid(). The same parser can
40578
   * and should be reused for the other documents in the buffer.
40579
   */
40580
  inline void next() noexcept;
40581
40582
  /** Move the json_iterator of the document to the location of the next document in the stream. */
40583
  inline void next_document() noexcept;
40584
40585
  /** Get the next document index. */
40586
  inline size_t next_batch_start() const noexcept;
40587
40588
  /** Pass the next batch through stage 1 with the given parser. */
40589
  inline error_code run_stage1(ondemand::parser &p, size_t batch_start) noexcept;
40590
40591
  // Fields
40592
  ondemand::parser *parser;
40593
  const uint8_t *buf;
40594
  size_t len;
40595
  size_t batch_size;
40596
  bool allow_comma_separated;
40597
  /**
40598
   * We are going to use just one document instance. The document owns
40599
   * the json_iterator. It implies that we only ever pass a reference
40600
   * to the document to the users.
40601
   */
40602
  document doc{};
40603
  /** The error (or lack thereof) from the current document. */
40604
  error_code error;
40605
  size_t batch_start{0};
40606
  size_t doc_index{};
40607
40608
  #ifdef SIMDJSON_THREADS_ENABLED
40609
  /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
40610
  bool use_thread;
40611
40612
  inline void load_from_stage1_thread() noexcept;
40613
40614
  /** Start a thread to run stage 1 on the next batch. */
40615
  inline void start_stage1_thread() noexcept;
40616
40617
  /** Wait for the stage 1 thread to finish and capture the results. */
40618
  inline void finish_stage1_thread() noexcept;
40619
40620
  /** The error returned from the stage 1 thread. */
40621
  error_code stage1_thread_error{UNINITIALIZED};
40622
  /** The thread used to run stage 1 against the next batch in the background. */
40623
  std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
40624
  /**
40625
   * The parser used to run stage 1 in the background. Will be swapped
40626
   * with the regular parser when finished.
40627
   */
40628
  ondemand::parser stage1_thread_parser{};
40629
40630
  friend struct stage1_worker;
40631
  #endif // SIMDJSON_THREADS_ENABLED
40632
40633
  friend class parser;
40634
  friend class document;
40635
  friend class json_iterator;
40636
  friend struct simdjson_result<ondemand::document_stream>;
40637
  friend struct internal::simdjson_result_base<ondemand::document_stream>;
40638
};  // document_stream
40639
40640
} // namespace ondemand
40641
} // namespace fallback
40642
} // namespace simdjson
40643
40644
namespace simdjson {
40645
template<>
40646
struct simdjson_result<fallback::ondemand::document_stream> : public fallback::implementation_simdjson_result_base<fallback::ondemand::document_stream> {
40647
public:
40648
  simdjson_inline simdjson_result(fallback::ondemand::document_stream &&value) noexcept; ///< @private
40649
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
40650
  simdjson_inline simdjson_result() noexcept = default;
40651
};
40652
40653
} // namespace simdjson
40654
40655
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
40656
/* end file simdjson/generic/ondemand/document_stream.h for fallback */
40657
/* including simdjson/generic/ondemand/field.h for fallback: #include "simdjson/generic/ondemand/field.h" */
40658
/* begin file simdjson/generic/ondemand/field.h for fallback */
40659
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
40660
40661
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
40662
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_H */
40663
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
40664
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
40665
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
40666
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
40667
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
40668
40669
namespace simdjson {
40670
namespace fallback {
40671
namespace ondemand {
40672
40673
/**
40674
 * A JSON field (key/value pair) in an object.
40675
 *
40676
 * Returned from object iteration.
40677
 *
40678
 * Extends from std::pair<raw_json_string, value> so you can use C++ algorithms that rely on pairs.
40679
 */
40680
class field : public std::pair<raw_json_string, value> {
40681
public:
40682
  /**
40683
   * Create a new invalid field.
40684
   *
40685
   * Exists so you can declare a variable and later assign to it before use.
40686
   */
40687
  simdjson_inline field() noexcept;
40688
40689
  /**
40690
   * Get the key as a string_view (for higher speed, consider raw_key).
40691
   * We deliberately use a more cumbersome name (unescaped_key) to force users
40692
   * to think twice about using it.
40693
   *
40694
   * This consumes the key: once you have called unescaped_key(), you cannot
40695
   * call it again nor can you call key().
40696
   */
40697
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescaped_key(bool allow_replacement) noexcept;
40698
  /**
40699
   * Get the key as a raw_json_string. Can be used for direct comparison with
40700
   * an unescaped C string: e.g., key() == "test".
40701
   */
40702
  simdjson_inline raw_json_string key() const noexcept;
40703
  /**
40704
   * Get the unprocessed key as a string_view. This includes the quotes and may include
40705
   * some spaces after the last quote.
40706
   */
40707
  simdjson_inline std::string_view key_raw_json_token() const noexcept;
40708
  /**
40709
   * Get the field value.
40710
   */
40711
  simdjson_inline ondemand::value &value() & noexcept;
40712
  /**
40713
   * @overload ondemand::value &ondemand::value() & noexcept
40714
   */
40715
  simdjson_inline ondemand::value value() && noexcept;
40716
40717
protected:
40718
  simdjson_inline field(raw_json_string key, ondemand::value &&value) noexcept;
40719
  static simdjson_inline simdjson_result<field> start(value_iterator &parent_iter) noexcept;
40720
  static simdjson_inline simdjson_result<field> start(const value_iterator &parent_iter, raw_json_string key) noexcept;
40721
  friend struct simdjson_result<field>;
40722
  friend class object_iterator;
40723
};
40724
40725
} // namespace ondemand
40726
} // namespace fallback
40727
} // namespace simdjson
40728
40729
namespace simdjson {
40730
40731
template<>
40732
struct simdjson_result<fallback::ondemand::field> : public fallback::implementation_simdjson_result_base<fallback::ondemand::field> {
40733
public:
40734
  simdjson_inline simdjson_result(fallback::ondemand::field &&value) noexcept; ///< @private
40735
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
40736
  simdjson_inline simdjson_result() noexcept = default;
40737
40738
  simdjson_inline simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
40739
  simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> key() noexcept;
40740
  simdjson_inline simdjson_result<std::string_view> key_raw_json_token() noexcept;
40741
  simdjson_inline simdjson_result<fallback::ondemand::value> value() noexcept;
40742
};
40743
40744
} // namespace simdjson
40745
40746
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_H
40747
/* end file simdjson/generic/ondemand/field.h for fallback */
40748
/* including simdjson/generic/ondemand/object.h for fallback: #include "simdjson/generic/ondemand/object.h" */
40749
/* begin file simdjson/generic/ondemand/object.h for fallback */
40750
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
40751
40752
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
40753
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_H */
40754
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
40755
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
40756
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
40757
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
40758
40759
namespace simdjson {
40760
namespace fallback {
40761
namespace ondemand {
40762
40763
/**
40764
 * A forward-only JSON object field iterator.
40765
 */
40766
class object {
40767
public:
40768
  /**
40769
   * Create a new invalid object.
40770
   *
40771
   * Exists so you can declare a variable and later assign to it before use.
40772
   */
40773
0
  simdjson_inline object() noexcept = default;
40774
40775
  simdjson_inline simdjson_result<object_iterator> begin() noexcept;
40776
  simdjson_inline simdjson_result<object_iterator> end() noexcept;
40777
  /**
40778
   * Look up a field by name on an object (order-sensitive).
40779
   *
40780
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
40781
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
40782
   *
40783
   * ```c++
40784
   * simdjson::ondemand::parser parser;
40785
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
40786
   * double z = obj.find_field("z");
40787
   * double y = obj.find_field("y");
40788
   * double x = obj.find_field("x");
40789
   * ```
40790
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
40791
   * that only one field is returned.
40792
   *
40793
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
40794
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
40795
   *
40796
   * You must consume the fields on an object one at a time. A request for a new key
40797
   * invalidates previous field values: it makes them unsafe. The value instance you get
40798
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
40799
   * given by content["bids"].get_array() should not be accessed after you have called
40800
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
40801
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
40802
   * OUT_OF_ORDER_ITERATION error is generated.
40803
   *
40804
   * You are expected to access keys only once. You should access the value corresponding to a
40805
   * key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
40806
   * is an error.
40807
   *
40808
   * @param key The key to look up.
40809
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
40810
   */
40811
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
40812
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
40813
  simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
40814
40815
  /**
40816
   * Look up a field by name on an object, without regard to key order.
40817
   *
40818
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
40819
   * and often appears negligible. It starts out normally, starting out at the last field; but if
40820
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
40821
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
40822
   * in question is large. The fact that the extra code is there also bumps the executable size.
40823
   *
40824
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
40825
   * default behavior failed to look up a field just because it was in the wrong order--and many
40826
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
40827
   *
40828
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
40829
   * field was not there when they are not in order).
40830
   *
40831
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
40832
   * that only one field is returned.
40833
   *
40834
   * You must consume the fields on an object one at a time. A request for a new key
40835
   * invalidates previous field values: it makes them unsafe. The value instance you get
40836
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
40837
   * given by content["bids"].get_array() should not be accessed after you have called
40838
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
40839
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
40840
   * OUT_OF_ORDER_ITERATION error is generated.
40841
   *
40842
   * You are expected to access keys only once. You should access the value corresponding to a key
40843
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
40844
   *
40845
   * @param key The key to look up.
40846
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
40847
   */
40848
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
40849
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
40850
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
40851
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
40852
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
40853
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
40854
  simdjson_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
40855
40856
  /**
40857
   * Get the value associated with the given JSON pointer. We use the RFC 6901
40858
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
40859
   * as the root of its own JSON document.
40860
   *
40861
   *   ondemand::parser parser;
40862
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
40863
   *   auto doc = parser.iterate(json);
40864
   *   doc.at_pointer("/foo/a/1") == 20
40865
   *
40866
   * It is allowed for a key to be the empty string:
40867
   *
40868
   *   ondemand::parser parser;
40869
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
40870
   *   auto doc = parser.iterate(json);
40871
   *   doc.at_pointer("//a/1") == 20
40872
   *
40873
   * Note that at_pointer() called on the document automatically calls the document's rewind
40874
   * method between each call. It invalidates all previously accessed arrays, objects and values
40875
   * that have not been consumed. Yet it is not the case when calling at_pointer on an object
40876
   * instance: there is no rewind and no invalidation.
40877
   *
40878
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
40879
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
40880
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
40881
   *
40882
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
40883
   *
40884
   * @return The value associated with the given JSON pointer, or:
40885
   *         - NO_SUCH_FIELD if a field does not exist in an object
40886
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
40887
   *         - INCORRECT_TYPE if a non-integer is used to access an array
40888
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
40889
   */
40890
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
40891
40892
  /**
40893
   * Get the value associated with the given JSONPath expression. We only support
40894
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
40895
   * names and array indices.
40896
   *
40897
   * @return The value associated with the given JSONPath expression, or:
40898
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
40899
   *         - NO_SUCH_FIELD if a field does not exist in an object
40900
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
40901
   *         - INCORRECT_TYPE if a non-integer is used to access an array
40902
   */
40903
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
40904
40905
  /**
40906
   * Reset the iterator so that we are pointing back at the
40907
   * beginning of the object. You should still consume values only once even if you
40908
   * can iterate through the object more than once. If you unescape a string within
40909
   * the object more than once, you have unsafe code. Note that rewinding an object
40910
   * means that you may need to reparse it anew: it is not a free operation.
40911
   *
40912
   * @returns true if the object contains some elements (not empty)
40913
   */
40914
  inline simdjson_result<bool> reset() & noexcept;
40915
  /**
40916
   * This method scans the beginning of the object and checks whether the
40917
   * object is empty.
40918
   * The runtime complexity is constant time. After
40919
   * calling this function, if successful, the object is 'rewinded' at its
40920
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
40921
   * there is a missing comma), then an error is returned and it is no longer
40922
   * safe to continue.
40923
   */
40924
  inline simdjson_result<bool> is_empty() & noexcept;
40925
  /**
40926
   * This method scans the object and counts the number of key-value pairs.
40927
   * The count_fields method should always be called before you have begun
40928
   * iterating through the object: it is expected that you are pointing at
40929
   * the beginning of the object.
40930
   * The runtime complexity is linear in the size of the object. After
40931
   * calling this function, if successful, the object is 'rewinded' at its
40932
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
40933
   * there is a missing comma), then an error is returned and it is no longer
40934
   * safe to continue.
40935
   *
40936
   * To check that an object is empty, it is more performant to use
40937
   * the is_empty() method.
40938
   *
40939
   * Performance hint: You should only call count_fields() as a last
40940
   * resort as it may require scanning the document twice or more.
40941
   */
40942
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
40943
  /**
40944
   * Consumes the object and returns a string_view instance corresponding to the
40945
   * object as represented in JSON. It points inside the original byte array containing
40946
   * the JSON document.
40947
   */
40948
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
40949
40950
protected:
40951
  /**
40952
   * Go to the end of the object, no matter where you are right now.
40953
   */
40954
  simdjson_inline error_code consume() noexcept;
40955
  static simdjson_inline simdjson_result<object> start(value_iterator &iter) noexcept;
40956
  static simdjson_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
40957
  static simdjson_inline simdjson_result<object> started(value_iterator &iter) noexcept;
40958
  static simdjson_inline object resume(const value_iterator &iter) noexcept;
40959
  simdjson_inline object(const value_iterator &iter) noexcept;
40960
40961
  simdjson_warn_unused simdjson_inline error_code find_field_raw(const std::string_view key) noexcept;
40962
40963
  value_iterator iter{};
40964
40965
  friend class value;
40966
  friend class document;
40967
  friend struct simdjson_result<object>;
40968
};
40969
40970
} // namespace ondemand
40971
} // namespace fallback
40972
} // namespace simdjson
40973
40974
namespace simdjson {
40975
40976
template<>
40977
struct simdjson_result<fallback::ondemand::object> : public fallback::implementation_simdjson_result_base<fallback::ondemand::object> {
40978
public:
40979
  simdjson_inline simdjson_result(fallback::ondemand::object &&value) noexcept; ///< @private
40980
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
40981
  simdjson_inline simdjson_result() noexcept = default;
40982
40983
  simdjson_inline simdjson_result<fallback::ondemand::object_iterator> begin() noexcept;
40984
  simdjson_inline simdjson_result<fallback::ondemand::object_iterator> end() noexcept;
40985
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(std::string_view key) & noexcept;
40986
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field(std::string_view key) && noexcept;
40987
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
40988
  simdjson_inline simdjson_result<fallback::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
40989
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](std::string_view key) & noexcept;
40990
  simdjson_inline simdjson_result<fallback::ondemand::value> operator[](std::string_view key) && noexcept;
40991
  simdjson_inline simdjson_result<fallback::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
40992
  simdjson_inline simdjson_result<fallback::ondemand::value> at_path(std::string_view json_path) noexcept;
40993
40994
  inline simdjson_result<bool> reset() noexcept;
40995
  inline simdjson_result<bool> is_empty() noexcept;
40996
  inline simdjson_result<size_t> count_fields() & noexcept;
40997
  inline simdjson_result<std::string_view> raw_json() noexcept;
40998
40999
};
41000
41001
} // namespace simdjson
41002
41003
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
41004
/* end file simdjson/generic/ondemand/object.h for fallback */
41005
/* including simdjson/generic/ondemand/object_iterator.h for fallback: #include "simdjson/generic/ondemand/object_iterator.h" */
41006
/* begin file simdjson/generic/ondemand/object_iterator.h for fallback */
41007
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
41008
41009
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
41010
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H */
41011
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
41012
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
41013
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
41014
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
41015
41016
namespace simdjson {
41017
namespace fallback {
41018
namespace ondemand {
41019
41020
class object_iterator {
41021
public:
41022
  /**
41023
   * Create a new invalid object_iterator.
41024
   *
41025
   * Exists so you can declare a variable and later assign to it before use.
41026
   */
41027
  simdjson_inline object_iterator() noexcept = default;
41028
41029
  //
41030
  // Iterator interface
41031
  //
41032
41033
  // Reads key and value, yielding them to the user.
41034
  // MUST ONLY BE CALLED ONCE PER ITERATION.
41035
  simdjson_inline simdjson_result<field> operator*() noexcept;
41036
  // Assumes it's being compared with the end. true if depth < iter->depth.
41037
  simdjson_inline bool operator==(const object_iterator &) const noexcept;
41038
  // Assumes it's being compared with the end. true if depth >= iter->depth.
41039
  simdjson_inline bool operator!=(const object_iterator &) const noexcept;
41040
  // Checks for ']' and ','
41041
  simdjson_inline object_iterator &operator++() noexcept;
41042
41043
private:
41044
  /**
41045
   * The underlying JSON iterator.
41046
   *
41047
   * PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
41048
   * is first used, and never changes afterwards.
41049
   */
41050
  value_iterator iter{};
41051
41052
  simdjson_inline object_iterator(const value_iterator &iter) noexcept;
41053
  friend struct simdjson_result<object_iterator>;
41054
  friend class object;
41055
};
41056
41057
} // namespace ondemand
41058
} // namespace fallback
41059
} // namespace simdjson
41060
41061
namespace simdjson {
41062
41063
template<>
41064
struct simdjson_result<fallback::ondemand::object_iterator> : public fallback::implementation_simdjson_result_base<fallback::ondemand::object_iterator> {
41065
public:
41066
  simdjson_inline simdjson_result(fallback::ondemand::object_iterator &&value) noexcept; ///< @private
41067
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
41068
  simdjson_inline simdjson_result() noexcept = default;
41069
41070
  //
41071
  // Iterator interface
41072
  //
41073
41074
  // Reads key and value, yielding them to the user.
41075
  simdjson_inline simdjson_result<fallback::ondemand::field> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
41076
  // Assumes it's being compared with the end. true if depth < iter->depth.
41077
  simdjson_inline bool operator==(const simdjson_result<fallback::ondemand::object_iterator> &) const noexcept;
41078
  // Assumes it's being compared with the end. true if depth >= iter->depth.
41079
  simdjson_inline bool operator!=(const simdjson_result<fallback::ondemand::object_iterator> &) const noexcept;
41080
  // Checks for ']' and ','
41081
  simdjson_inline simdjson_result<fallback::ondemand::object_iterator> &operator++() noexcept;
41082
};
41083
41084
} // namespace simdjson
41085
41086
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
41087
/* end file simdjson/generic/ondemand/object_iterator.h for fallback */
41088
/* including simdjson/generic/ondemand/serialization.h for fallback: #include "simdjson/generic/ondemand/serialization.h" */
41089
/* begin file simdjson/generic/ondemand/serialization.h for fallback */
41090
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
41091
41092
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
41093
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H */
41094
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
41095
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
41096
41097
namespace simdjson {
41098
/**
41099
 * Create a string-view instance out of a document instance. The string-view instance
41100
 * contains JSON text that is suitable to be parsed as JSON again. It does not
41101
 * validate the content.
41102
 */
41103
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::document& x) noexcept;
41104
/**
41105
 * Create a string-view instance out of a value instance. The string-view instance
41106
 * contains JSON text that is suitable to be parsed as JSON again. The value must
41107
 * not have been accessed previously. It does not
41108
 * validate the content.
41109
 */
41110
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::value& x) noexcept;
41111
/**
41112
 * Create a string-view instance out of an object instance. The string-view instance
41113
 * contains JSON text that is suitable to be parsed as JSON again. It does not
41114
 * validate the content.
41115
 */
41116
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::object& x) noexcept;
41117
/**
41118
 * Create a string-view instance out of an array instance. The string-view instance
41119
 * contains JSON text that is suitable to be parsed as JSON again. It does not
41120
 * validate the content.
41121
 */
41122
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::array& x) noexcept;
41123
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::document> x);
41124
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::value> x);
41125
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::object> x);
41126
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::array> x);
41127
} // namespace simdjson
41128
41129
/**
41130
 * We want to support argument-dependent lookup (ADL).
41131
 * Hence we should define operator<< in the namespace
41132
 * where the argument (here value, object, etc.) resides.
41133
 * Credit: @madhur4127
41134
 * See https://github.com/simdjson/simdjson/issues/1768
41135
 */
41136
namespace simdjson { namespace fallback { namespace ondemand {
41137
41138
/**
41139
 * Print JSON to an output stream.  It does not
41140
 * validate the content.
41141
 *
41142
 * @param out The output stream.
41143
 * @param value The element.
41144
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
41145
 */
41146
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::value x);
41147
#if SIMDJSON_EXCEPTIONS
41148
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::value> x);
41149
#endif
41150
/**
41151
 * Print JSON to an output stream. It does not
41152
 * validate the content.
41153
 *
41154
 * @param out The output stream.
41155
 * @param value The array.
41156
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
41157
 */
41158
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::array value);
41159
#if SIMDJSON_EXCEPTIONS
41160
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::array> x);
41161
#endif
41162
/**
41163
 * Print JSON to an output stream. It does not
41164
 * validate the content.
41165
 *
41166
 * @param out The output stream.
41167
 * @param value The array.
41168
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
41169
 */
41170
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::document& value);
41171
#if SIMDJSON_EXCEPTIONS
41172
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::document>&& x);
41173
#endif
41174
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::document_reference& value);
41175
#if SIMDJSON_EXCEPTIONS
41176
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::document_reference>&& x);
41177
#endif
41178
/**
41179
 * Print JSON to an output stream. It does not
41180
 * validate the content.
41181
 *
41182
 * @param out The output stream.
41183
 * @param value The object.
41184
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
41185
 */
41186
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::object value);
41187
#if SIMDJSON_EXCEPTIONS
41188
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::object> x);
41189
#endif
41190
}}} // namespace simdjson::fallback::ondemand
41191
41192
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
41193
/* end file simdjson/generic/ondemand/serialization.h for fallback */
41194
41195
// Inline definitions
41196
/* including simdjson/generic/ondemand/array-inl.h for fallback: #include "simdjson/generic/ondemand/array-inl.h" */
41197
/* begin file simdjson/generic/ondemand/array-inl.h for fallback */
41198
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
41199
41200
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
41201
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H */
41202
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
41203
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
41204
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator-inl.h" */
41205
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
41206
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
41207
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
41208
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
41209
41210
namespace simdjson {
41211
namespace fallback {
41212
namespace ondemand {
41213
41214
//
41215
// ### Live States
41216
//
41217
// While iterating or looking up values, depth >= iter->depth. at_start may vary. Error is
41218
// always SUCCESS:
41219
//
41220
// - Start: This is the state when the array is first found and the iterator is just past the `{`.
41221
//   In this state, at_start == true.
41222
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
41223
//   iterate over, the iterator is at the `,` before the next value (or `]`). In this state,
41224
//   depth == iter->depth, at_start == false, and error == SUCCESS.
41225
// - Unfinished Business: When we hand an array/object to the user which they do not fully
41226
//   iterate over, we need to finish that iteration by skipping child values until we reach the
41227
//   Next state. In this state, depth > iter->depth, at_start == false, and error == SUCCESS.
41228
//
41229
// ## Error States
41230
//
41231
// In error states, we will yield exactly one more value before stopping. iter->depth == depth
41232
// and at_start is always false. We decrement after yielding the error, moving to the Finished
41233
// state.
41234
//
41235
// - Chained Error: When the array iterator is part of an error chain--for example, in
41236
//   `for (auto tweet : doc["tweets"])`, where the tweet element may be missing or not be an
41237
//   array--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
41238
//   iter->depth == depth, and at_start == false. We decrement depth when we yield the error.
41239
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between elements,
41240
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
41241
//   error == TAPE_ERROR, iter->depth == depth, and at_start == false.
41242
//
41243
// ## Terminal State
41244
//
41245
// The terminal state has iter->depth < depth. at_start is always false.
41246
//
41247
// - Finished: When we have reached a `]` or have reported an error, we are finished. We signal this
41248
//   by decrementing depth. In this state, iter->depth < depth, at_start == false, and
41249
//   error == SUCCESS.
41250
//
41251
41252
simdjson_inline array::array(const value_iterator &_iter) noexcept
41253
0
  : iter{_iter}
41254
0
{
41255
0
}
41256
41257
0
simdjson_inline simdjson_result<array> array::start(value_iterator &iter) noexcept {
41258
  // We don't need to know if the array is empty to start iteration, but we do want to know if there
41259
  // is an error--thus `simdjson_unused`.
41260
0
  simdjson_unused bool has_value;
41261
0
  SIMDJSON_TRY( iter.start_array().get(has_value) );
41262
0
  return array(iter);
41263
0
}
41264
0
simdjson_inline simdjson_result<array> array::start_root(value_iterator &iter) noexcept {
41265
0
  simdjson_unused bool has_value;
41266
0
  SIMDJSON_TRY( iter.start_root_array().get(has_value) );
41267
0
  return array(iter);
41268
0
}
41269
0
simdjson_inline simdjson_result<array> array::started(value_iterator &iter) noexcept {
41270
0
  bool has_value;
41271
0
  SIMDJSON_TRY(iter.started_array().get(has_value));
41272
0
  return array(iter);
41273
0
}
41274
41275
0
simdjson_inline simdjson_result<array_iterator> array::begin() noexcept {
41276
0
#if SIMDJSON_DEVELOPMENT_CHECKS
41277
0
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
41278
0
#endif
41279
0
  return array_iterator(iter);
41280
0
}
41281
0
simdjson_inline simdjson_result<array_iterator> array::end() noexcept {
41282
0
  return array_iterator(iter);
41283
0
}
41284
0
simdjson_inline error_code array::consume() noexcept {
41285
0
  auto error = iter.json_iter().skip_child(iter.depth()-1);
41286
0
  if(error) { iter.abandon(); }
41287
0
  return error;
41288
0
}
41289
41290
0
simdjson_inline simdjson_result<std::string_view> array::raw_json() noexcept {
41291
0
  const uint8_t * starting_point{iter.peek_start()};
41292
0
  auto error = consume();
41293
0
  if(error) { return error; }
41294
  // After 'consume()', we could be left pointing just beyond the document, but that
41295
  // is ok because we are not going to dereference the final pointer position, we just
41296
  // use it to compute the length in bytes.
41297
0
  const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
41298
0
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
41299
0
}
41300
41301
SIMDJSON_PUSH_DISABLE_WARNINGS
41302
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
41303
0
simdjson_inline simdjson_result<size_t> array::count_elements() & noexcept {
41304
0
  size_t count{0};
41305
0
  // Important: we do not consume any of the values.
41306
0
  for(simdjson_unused auto v : *this) { count++; }
41307
0
  // The above loop will always succeed, but we want to report errors.
41308
0
  if(iter.error()) { return iter.error(); }
41309
0
  // We need to move back at the start because we expect users to iterate through
41310
0
  // the array after counting the number of elements.
41311
0
  iter.reset_array();
41312
0
  return count;
41313
0
}
41314
SIMDJSON_POP_DISABLE_WARNINGS
41315
41316
0
simdjson_inline simdjson_result<bool> array::is_empty() & noexcept {
41317
0
  bool is_not_empty;
41318
0
  auto error = iter.reset_array().get(is_not_empty);
41319
0
  if(error) { return error; }
41320
0
  return !is_not_empty;
41321
0
}
41322
41323
0
inline simdjson_result<bool> array::reset() & noexcept {
41324
0
  return iter.reset_array();
41325
0
}
41326
41327
0
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
41328
0
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
41329
0
  json_pointer = json_pointer.substr(1);
41330
0
  // - means "the append position" or "the element after the end of the array"
41331
0
  // We don't support this, because we're returning a real element, not a position.
41332
0
  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
41333
0
41334
0
  // Read the array index
41335
0
  size_t array_index = 0;
41336
0
  size_t i;
41337
0
  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
41338
0
    uint8_t digit = uint8_t(json_pointer[i] - '0');
41339
0
    // Check for non-digit in array index. If it's there, we're trying to get a field in an object
41340
0
    if (digit > 9) { return INCORRECT_TYPE; }
41341
0
    array_index = array_index*10 + digit;
41342
0
  }
41343
0
41344
0
  // 0 followed by other digits is invalid
41345
0
  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
41346
0
41347
0
  // Empty string is invalid; so is a "/" with no digits before it
41348
0
  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
41349
0
  // Get the child
41350
0
  auto child = at(array_index);
41351
0
  // If there is an error, it ends here
41352
0
  if(child.error()) {
41353
0
    return child;
41354
0
  }
41355
0
41356
0
  // If there is a /, we're not done yet, call recursively.
41357
0
  if (i < json_pointer.length()) {
41358
0
    child = child.at_pointer(json_pointer.substr(i));
41359
0
  }
41360
0
  return child;
41361
0
}
41362
41363
0
inline std::string json_path_to_pointer_conversion(std::string_view json_path) {
41364
0
  if (json_path.empty() || (json_path.front() != '.' &&
41365
0
      json_path.front() != '[')) {
41366
0
    return "-1"; // This is just a sentinel value, the caller should check for this and return an error.
41367
0
  }
41368
0
41369
0
  std::string result;
41370
0
  // Reserve space to reduce allocations, adjusting for potential increases due
41371
0
  // to escaping.
41372
0
  result.reserve(json_path.size() * 2);
41373
0
41374
0
  size_t i = 0;
41375
0
41376
0
  while (i < json_path.length()) {
41377
0
    if (json_path[i] == '.') {
41378
0
      result += '/';
41379
0
    } else if (json_path[i] == '[') {
41380
0
      result += '/';
41381
0
      ++i; // Move past the '['
41382
0
      while (i < json_path.length() && json_path[i] != ']') {
41383
0
          if (json_path[i] == '~') {
41384
0
            result += "~0";
41385
0
          } else if (json_path[i] == '/') {
41386
0
            result += "~1";
41387
0
          } else {
41388
0
            result += json_path[i];
41389
0
          }
41390
0
          ++i;
41391
0
      }
41392
0
      if (i == json_path.length() || json_path[i] != ']') {
41393
0
          return "-1"; // Using sentinel value that will be handled as an error by the caller.
41394
0
      }
41395
0
    } else {
41396
0
      if (json_path[i] == '~') {
41397
0
          result += "~0";
41398
0
      } else if (json_path[i] == '/') {
41399
0
          result += "~1";
41400
0
      } else {
41401
0
          result += json_path[i];
41402
0
      }
41403
0
    }
41404
0
    ++i;
41405
0
  }
41406
0
41407
0
  return result;
41408
0
}
41409
41410
0
inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept {
41411
0
  auto json_pointer = json_path_to_pointer_conversion(json_path);
41412
0
  if (json_pointer == "-1") { return INVALID_JSON_POINTER; }
41413
0
  return at_pointer(json_pointer);
41414
0
}
41415
41416
0
simdjson_inline simdjson_result<value> array::at(size_t index) noexcept {
41417
0
  size_t i = 0;
41418
0
  for (auto value : *this) {
41419
0
    if (i == index) { return value; }
41420
0
    i++;
41421
0
  }
41422
0
  return INDEX_OUT_OF_BOUNDS;
41423
0
}
41424
41425
} // namespace ondemand
41426
} // namespace fallback
41427
} // namespace simdjson
41428
41429
namespace simdjson {
41430
41431
simdjson_inline simdjson_result<fallback::ondemand::array>::simdjson_result(
41432
  fallback::ondemand::array &&value
41433
) noexcept
41434
0
  : implementation_simdjson_result_base<fallback::ondemand::array>(
41435
0
      std::forward<fallback::ondemand::array>(value)
41436
0
    )
41437
0
{
41438
0
}
41439
simdjson_inline simdjson_result<fallback::ondemand::array>::simdjson_result(
41440
  error_code error
41441
) noexcept
41442
0
  : implementation_simdjson_result_base<fallback::ondemand::array>(error)
41443
0
{
41444
0
}
41445
41446
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::array>::begin() noexcept {
41447
0
  if (error()) { return error(); }
41448
0
  return first.begin();
41449
0
}
41450
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::array>::end() noexcept {
41451
0
  if (error()) { return error(); }
41452
0
  return first.end();
41453
0
}
41454
0
simdjson_inline  simdjson_result<size_t> simdjson_result<fallback::ondemand::array>::count_elements() & noexcept {
41455
0
  if (error()) { return error(); }
41456
0
  return first.count_elements();
41457
0
}
41458
0
simdjson_inline  simdjson_result<bool> simdjson_result<fallback::ondemand::array>::is_empty() & noexcept {
41459
0
  if (error()) { return error(); }
41460
0
  return first.is_empty();
41461
0
}
41462
0
simdjson_inline  simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::array>::at(size_t index) noexcept {
41463
0
  if (error()) { return error(); }
41464
0
  return first.at(index);
41465
0
}
41466
0
simdjson_inline  simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::array>::at_pointer(std::string_view json_pointer) noexcept {
41467
0
  if (error()) { return error(); }
41468
0
  return first.at_pointer(json_pointer);
41469
0
}
41470
0
simdjson_inline  simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::array>::at_path(std::string_view json_path) noexcept {
41471
0
  if (error()) { return error(); }
41472
0
  return first.at_path(json_path);
41473
0
}
41474
0
simdjson_inline  simdjson_result<std::string_view> simdjson_result<fallback::ondemand::array>::raw_json() noexcept {
41475
0
  if (error()) { return error(); }
41476
0
  return first.raw_json();
41477
0
}
41478
} // namespace simdjson
41479
41480
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
41481
/* end file simdjson/generic/ondemand/array-inl.h for fallback */
41482
/* including simdjson/generic/ondemand/array_iterator-inl.h for fallback: #include "simdjson/generic/ondemand/array_iterator-inl.h" */
41483
/* begin file simdjson/generic/ondemand/array_iterator-inl.h for fallback */
41484
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
41485
41486
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
41487
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H */
41488
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
41489
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
41490
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
41491
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
41492
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
41493
41494
namespace simdjson {
41495
namespace fallback {
41496
namespace ondemand {
41497
41498
simdjson_inline array_iterator::array_iterator(const value_iterator &_iter) noexcept
41499
  : iter{_iter}
41500
{}
41501
41502
0
simdjson_inline simdjson_result<value> array_iterator::operator*() noexcept {
41503
0
  if (iter.error()) { iter.abandon(); return iter.error(); }
41504
0
  return value(iter.child());
41505
0
}
41506
0
simdjson_inline bool array_iterator::operator==(const array_iterator &other) const noexcept {
41507
0
  return !(*this != other);
41508
0
}
41509
0
simdjson_inline bool array_iterator::operator!=(const array_iterator &) const noexcept {
41510
0
  return iter.is_open();
41511
0
}
41512
0
simdjson_inline array_iterator &array_iterator::operator++() noexcept {
41513
0
  error_code error;
41514
0
  // PERF NOTE this is a safety rail ... users should exit loops as soon as they receive an error, so we'll never get here.
41515
0
  // However, it does not seem to make a perf difference, so we add it out of an abundance of caution.
41516
0
  if (( error = iter.error() )) { return *this; }
41517
0
  if (( error = iter.skip_child() )) { return *this; }
41518
0
  if (( error = iter.has_next_element().error() )) { return *this; }
41519
0
  return *this;
41520
0
}
41521
41522
} // namespace ondemand
41523
} // namespace fallback
41524
} // namespace simdjson
41525
41526
namespace simdjson {
41527
41528
simdjson_inline simdjson_result<fallback::ondemand::array_iterator>::simdjson_result(
41529
  fallback::ondemand::array_iterator &&value
41530
) noexcept
41531
  : fallback::implementation_simdjson_result_base<fallback::ondemand::array_iterator>(std::forward<fallback::ondemand::array_iterator>(value))
41532
{
41533
  first.iter.assert_is_valid();
41534
}
41535
simdjson_inline simdjson_result<fallback::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
41536
  : fallback::implementation_simdjson_result_base<fallback::ondemand::array_iterator>({}, error)
41537
{
41538
}
41539
41540
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::array_iterator>::operator*() noexcept {
41541
0
  if (error()) { return error(); }
41542
0
  return *first;
41543
0
}
41544
0
simdjson_inline bool simdjson_result<fallback::ondemand::array_iterator>::operator==(const simdjson_result<fallback::ondemand::array_iterator> &other) const noexcept {
41545
0
  if (!first.iter.is_valid()) { return !error(); }
41546
0
  return first == other.first;
41547
0
}
41548
0
simdjson_inline bool simdjson_result<fallback::ondemand::array_iterator>::operator!=(const simdjson_result<fallback::ondemand::array_iterator> &other) const noexcept {
41549
0
  if (!first.iter.is_valid()) { return error(); }
41550
0
  return first != other.first;
41551
0
}
41552
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> &simdjson_result<fallback::ondemand::array_iterator>::operator++() noexcept {
41553
0
  // Clear the error if there is one, so we don't yield it twice
41554
0
  if (error()) { second = SUCCESS; return *this; }
41555
0
  ++(first);
41556
0
  return *this;
41557
0
}
41558
41559
} // namespace simdjson
41560
41561
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
41562
/* end file simdjson/generic/ondemand/array_iterator-inl.h for fallback */
41563
/* including simdjson/generic/ondemand/document-inl.h for fallback: #include "simdjson/generic/ondemand/document-inl.h" */
41564
/* begin file simdjson/generic/ondemand/document-inl.h for fallback */
41565
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
41566
41567
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
41568
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */
41569
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
41570
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */
41571
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
41572
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
41573
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
41574
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
41575
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
41576
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
41577
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */
41578
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
41579
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
41580
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
41581
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
41582
41583
namespace simdjson {
41584
namespace fallback {
41585
namespace ondemand {
41586
41587
simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept
41588
0
  : iter{std::forward<json_iterator>(_iter)}
41589
0
{
41590
0
  logger::log_start_value(iter, "document");
41591
0
}
41592
41593
0
simdjson_inline document document::start(json_iterator &&iter) noexcept {
41594
0
  return document(std::forward<json_iterator>(iter));
41595
0
}
41596
41597
0
inline void document::rewind() noexcept {
41598
0
  iter.rewind();
41599
0
}
41600
41601
0
inline std::string document::to_debug_string() noexcept {
41602
0
  return iter.to_string();
41603
0
}
41604
41605
0
inline simdjson_result<const char *> document::current_location() const noexcept {
41606
0
  return iter.current_location();
41607
0
}
41608
41609
0
inline int32_t document::current_depth() const noexcept {
41610
0
  return iter.depth();
41611
0
}
41612
41613
0
inline bool document::at_end() const noexcept {
41614
0
  return iter.at_end();
41615
0
}
41616
41617
41618
0
inline bool document::is_alive() noexcept {
41619
0
  return iter.is_alive();
41620
0
}
41621
0
simdjson_inline value_iterator document::resume_value_iterator() noexcept {
41622
0
  return value_iterator(&iter, 1, iter.root_position());
41623
0
}
41624
0
simdjson_inline value_iterator document::get_root_value_iterator() noexcept {
41625
0
  return resume_value_iterator();
41626
0
}
41627
0
simdjson_inline simdjson_result<object> document::start_or_resume_object() noexcept {
41628
0
  if (iter.at_root()) {
41629
0
    return get_object();
41630
0
  } else {
41631
0
    return object::resume(resume_value_iterator());
41632
0
  }
41633
0
}
41634
0
simdjson_inline simdjson_result<value> document::get_value() noexcept {
41635
0
  // Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
41636
0
  // gets called.
41637
0
41638
0
  // It is the convention throughout the code that  the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether
41639
0
  // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error.
41640
0
#if SIMDJSON_DEVELOPMENT_CHECKS
41641
0
  if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; }
41642
0
#endif
41643
0
  // assert_at_root() serves two purposes: in Debug mode, whether or not
41644
0
  // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of
41645
0
  // the document (this will typically be redundant). In release mode, it generates
41646
0
  // SIMDJSON_ASSUME statements to allow the compiler to make assumptions.
41647
0
  iter.assert_at_root();
41648
0
  switch (*iter.peek()) {
41649
0
    case '[': {
41650
0
      // The following lines check that the document ends with ].
41651
0
      auto value_iterator = get_root_value_iterator();
41652
0
      auto error = value_iterator.check_root_array();
41653
0
      if(error) { return error; }
41654
0
      return value(get_root_value_iterator());
41655
0
    }
41656
0
    case '{': {
41657
0
      // The following lines would check that the document ends with }.
41658
0
      auto value_iterator = get_root_value_iterator();
41659
0
      auto error = value_iterator.check_root_object();
41660
0
      if(error) { return error; }
41661
0
      return value(get_root_value_iterator());
41662
0
    }
41663
0
    default:
41664
0
      // Unfortunately, scalar documents are a special case in simdjson and they cannot
41665
0
      // be safely converted to value instances.
41666
0
      return SCALAR_DOCUMENT_AS_VALUE;
41667
0
  }
41668
0
}
41669
0
simdjson_inline simdjson_result<array> document::get_array() & noexcept {
41670
0
  auto value = get_root_value_iterator();
41671
0
  return array::start_root(value);
41672
0
}
41673
0
simdjson_inline simdjson_result<object> document::get_object() & noexcept {
41674
0
  auto value = get_root_value_iterator();
41675
0
  return object::start_root(value);
41676
0
}
41677
41678
/**
41679
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
41680
 * give an error, so we check for trailing content. We want to disallow trailing
41681
 * content.
41682
 * Thus, in several implementations below, we pass a 'true' parameter value to
41683
 * a get_root_value_iterator() method: this indicates that we disallow trailing content.
41684
 */
41685
41686
0
simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
41687
0
  return get_root_value_iterator().get_root_uint64(true);
41688
0
}
41689
0
simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
41690
0
  return get_root_value_iterator().get_root_uint64_in_string(true);
41691
0
}
41692
0
simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
41693
0
  return get_root_value_iterator().get_root_int64(true);
41694
0
}
41695
0
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
41696
0
  return get_root_value_iterator().get_root_int64_in_string(true);
41697
0
}
41698
0
simdjson_inline simdjson_result<double> document::get_double() noexcept {
41699
0
  return get_root_value_iterator().get_root_double(true);
41700
0
}
41701
0
simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
41702
0
  return get_root_value_iterator().get_root_double_in_string(true);
41703
0
}
41704
0
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
41705
0
  return get_root_value_iterator().get_root_string(true, allow_replacement);
41706
0
}
41707
template <typename string_type>
41708
simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
41709
  return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
41710
}
41711
0
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
41712
0
  return get_root_value_iterator().get_root_wobbly_string(true);
41713
0
}
41714
0
simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
41715
0
  return get_root_value_iterator().get_root_raw_json_string(true);
41716
0
}
41717
0
simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
41718
0
  return get_root_value_iterator().get_root_bool(true);
41719
0
}
41720
0
simdjson_inline simdjson_result<bool> document::is_null() noexcept {
41721
0
  return get_root_value_iterator().is_root_null(true);
41722
0
}
41723
41724
0
template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
41725
0
template<> simdjson_inline simdjson_result<object> document::get() & noexcept { return get_object(); }
41726
0
template<> simdjson_inline simdjson_result<raw_json_string> document::get() & noexcept { return get_raw_json_string(); }
41727
0
template<> simdjson_inline simdjson_result<std::string_view> document::get() & noexcept { return get_string(false); }
41728
0
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
41729
0
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
41730
0
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
41731
0
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
41732
0
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
41733
41734
0
template<> simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
41735
0
template<> simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
41736
0
template<> simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
41737
0
template<> simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
41738
0
template<> simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
41739
0
template<> simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
41740
0
template<> simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
41741
41742
template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
41743
  return get<T>().get(out);
41744
}
41745
template<typename T> simdjson_inline error_code document::get(T &out) && noexcept {
41746
  return std::forward<document>(*this).get<T>().get(out);
41747
}
41748
41749
#if SIMDJSON_EXCEPTIONS
41750
template <class T>
41751
simdjson_inline document::operator T() noexcept(false) { return get<T>(); }
41752
simdjson_inline document::operator array() & noexcept(false) { return get_array(); }
41753
simdjson_inline document::operator object() & noexcept(false) { return get_object(); }
41754
simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); }
41755
simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); }
41756
simdjson_inline document::operator double() noexcept(false) { return get_double(); }
41757
simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); }
41758
simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
41759
simdjson_inline document::operator bool() noexcept(false) { return get_bool(); }
41760
simdjson_inline document::operator value() noexcept(false) { return get_value(); }
41761
41762
#endif
41763
0
simdjson_inline simdjson_result<size_t> document::count_elements() & noexcept {
41764
0
  auto a = get_array();
41765
0
  simdjson_result<size_t> answer = a.count_elements();
41766
0
  /* If there was an array, we are now left pointing at its first element. */
41767
0
  if(answer.error() == SUCCESS) { rewind(); }
41768
0
  return answer;
41769
0
}
41770
0
simdjson_inline simdjson_result<size_t> document::count_fields() & noexcept {
41771
0
  auto a = get_object();
41772
0
  simdjson_result<size_t> answer = a.count_fields();
41773
0
  /* If there was an object, we are now left pointing at its first element. */
41774
0
  if(answer.error() == SUCCESS) { rewind(); }
41775
0
  return answer;
41776
0
}
41777
0
simdjson_inline simdjson_result<value> document::at(size_t index) & noexcept {
41778
0
  auto a = get_array();
41779
0
  return a.at(index);
41780
0
}
41781
0
simdjson_inline simdjson_result<array_iterator> document::begin() & noexcept {
41782
0
  return get_array().begin();
41783
0
}
41784
0
simdjson_inline simdjson_result<array_iterator> document::end() & noexcept {
41785
0
  return {};
41786
0
}
41787
41788
0
simdjson_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
41789
0
  return start_or_resume_object().find_field(key);
41790
0
}
41791
0
simdjson_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
41792
0
  return start_or_resume_object().find_field(key);
41793
0
}
41794
0
simdjson_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
41795
0
  return start_or_resume_object().find_field_unordered(key);
41796
0
}
41797
0
simdjson_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
41798
0
  return start_or_resume_object().find_field_unordered(key);
41799
0
}
41800
0
simdjson_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
41801
0
  return start_or_resume_object()[key];
41802
0
}
41803
0
simdjson_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
41804
0
  return start_or_resume_object()[key];
41805
0
}
41806
41807
0
simdjson_inline error_code document::consume() noexcept {
41808
0
  auto error = iter.skip_child(0);
41809
0
  if(error) { iter.abandon(); }
41810
0
  return error;
41811
0
}
41812
41813
0
simdjson_inline simdjson_result<std::string_view> document::raw_json() noexcept {
41814
0
  auto _iter = get_root_value_iterator();
41815
0
  const uint8_t * starting_point{_iter.peek_start()};
41816
0
  auto error = consume();
41817
0
  if(error) { return error; }
41818
0
  // After 'consume()', we could be left pointing just beyond the document, but that
41819
0
  // is ok because we are not going to dereference the final pointer position, we just
41820
0
  // use it to compute the length in bytes.
41821
0
  const uint8_t * final_point{iter.unsafe_pointer()};
41822
0
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
41823
0
}
41824
41825
0
simdjson_inline simdjson_result<json_type> document::type() noexcept {
41826
0
  return get_root_value_iterator().type();
41827
0
}
41828
41829
0
simdjson_inline simdjson_result<bool> document::is_scalar() noexcept {
41830
0
  json_type this_type;
41831
0
  auto error = type().get(this_type);
41832
0
  if(error) { return error; }
41833
0
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
41834
0
}
41835
41836
0
simdjson_inline simdjson_result<bool> document::is_string() noexcept {
41837
0
  json_type this_type;
41838
0
  auto error = type().get(this_type);
41839
0
  if(error) { return error; }
41840
0
  return (this_type == json_type::string);
41841
0
}
41842
41843
0
simdjson_inline bool document::is_negative() noexcept {
41844
0
  return get_root_value_iterator().is_root_negative();
41845
0
}
41846
41847
0
simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
41848
0
  return get_root_value_iterator().is_root_integer(true);
41849
0
}
41850
41851
0
simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
41852
0
  return get_root_value_iterator().get_root_number_type(true);
41853
0
}
41854
41855
0
simdjson_inline simdjson_result<number> document::get_number() noexcept {
41856
0
  return get_root_value_iterator().get_root_number(true);
41857
0
}
41858
41859
41860
0
simdjson_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
41861
0
  auto _iter = get_root_value_iterator();
41862
0
  return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_root_length());
41863
0
}
41864
41865
0
simdjson_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
41866
0
  rewind(); // Rewind the document each time at_pointer is called
41867
0
  if (json_pointer.empty()) {
41868
0
    return this->get_value();
41869
0
  }
41870
0
  json_type t;
41871
0
  SIMDJSON_TRY(type().get(t));
41872
0
  switch (t)
41873
0
  {
41874
0
    case json_type::array:
41875
0
      return (*this).get_array().at_pointer(json_pointer);
41876
0
    case json_type::object:
41877
0
      return (*this).get_object().at_pointer(json_pointer);
41878
0
    default:
41879
0
      return INVALID_JSON_POINTER;
41880
0
  }
41881
0
}
41882
41883
0
simdjson_inline simdjson_result<value> document::at_path(std::string_view json_path) noexcept {
41884
0
  rewind(); // Rewind the document each time at_pointer is called
41885
0
  if (json_path.empty()) {
41886
0
      return this->get_value();
41887
0
  }
41888
0
  json_type t;
41889
0
  SIMDJSON_TRY(type().get(t));
41890
0
  switch (t) {
41891
0
  case json_type::array:
41892
0
      return (*this).get_array().at_path(json_path);
41893
0
  case json_type::object:
41894
0
      return (*this).get_object().at_path(json_path);
41895
0
  default:
41896
0
      return INVALID_JSON_POINTER;
41897
0
  }
41898
0
}
41899
41900
} // namespace ondemand
41901
} // namespace fallback
41902
} // namespace simdjson
41903
41904
namespace simdjson {
41905
41906
simdjson_inline simdjson_result<fallback::ondemand::document>::simdjson_result(
41907
  fallback::ondemand::document &&value
41908
) noexcept :
41909
0
    implementation_simdjson_result_base<fallback::ondemand::document>(
41910
0
      std::forward<fallback::ondemand::document>(value)
41911
0
    )
41912
0
{
41913
0
}
41914
simdjson_inline simdjson_result<fallback::ondemand::document>::simdjson_result(
41915
  error_code error
41916
) noexcept :
41917
0
    implementation_simdjson_result_base<fallback::ondemand::document>(
41918
0
      error
41919
0
    )
41920
0
{
41921
0
}
41922
0
simdjson_inline simdjson_result<size_t> simdjson_result<fallback::ondemand::document>::count_elements() & noexcept {
41923
0
  if (error()) { return error(); }
41924
0
  return first.count_elements();
41925
0
}
41926
0
simdjson_inline simdjson_result<size_t> simdjson_result<fallback::ondemand::document>::count_fields() & noexcept {
41927
0
  if (error()) { return error(); }
41928
0
  return first.count_fields();
41929
0
}
41930
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::at(size_t index) & noexcept {
41931
0
  if (error()) { return error(); }
41932
0
  return first.at(index);
41933
0
}
41934
0
simdjson_inline error_code simdjson_result<fallback::ondemand::document>::rewind() noexcept {
41935
0
  if (error()) { return error(); }
41936
0
  first.rewind();
41937
0
  return SUCCESS;
41938
0
}
41939
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::document>::begin() & noexcept {
41940
0
  if (error()) { return error(); }
41941
0
  return first.begin();
41942
0
}
41943
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::document>::end() & noexcept {
41944
0
  return {};
41945
0
}
41946
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
41947
0
  if (error()) { return error(); }
41948
0
  return first.find_field_unordered(key);
41949
0
}
41950
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::find_field_unordered(const char *key) & noexcept {
41951
0
  if (error()) { return error(); }
41952
0
  return first.find_field_unordered(key);
41953
0
}
41954
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::operator[](std::string_view key) & noexcept {
41955
0
  if (error()) { return error(); }
41956
0
  return first[key];
41957
0
}
41958
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::operator[](const char *key) & noexcept {
41959
0
  if (error()) { return error(); }
41960
0
  return first[key];
41961
0
}
41962
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::find_field(std::string_view key) & noexcept {
41963
0
  if (error()) { return error(); }
41964
0
  return first.find_field(key);
41965
0
}
41966
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::find_field(const char *key) & noexcept {
41967
0
  if (error()) { return error(); }
41968
0
  return first.find_field(key);
41969
0
}
41970
0
simdjson_inline simdjson_result<fallback::ondemand::array> simdjson_result<fallback::ondemand::document>::get_array() & noexcept {
41971
0
  if (error()) { return error(); }
41972
0
  return first.get_array();
41973
0
}
41974
0
simdjson_inline simdjson_result<fallback::ondemand::object> simdjson_result<fallback::ondemand::document>::get_object() & noexcept {
41975
0
  if (error()) { return error(); }
41976
0
  return first.get_object();
41977
0
}
41978
0
simdjson_inline simdjson_result<uint64_t> simdjson_result<fallback::ondemand::document>::get_uint64() noexcept {
41979
0
  if (error()) { return error(); }
41980
0
  return first.get_uint64();
41981
0
}
41982
0
simdjson_inline simdjson_result<uint64_t> simdjson_result<fallback::ondemand::document>::get_uint64_in_string() noexcept {
41983
0
  if (error()) { return error(); }
41984
0
  return first.get_uint64_in_string();
41985
0
}
41986
0
simdjson_inline simdjson_result<int64_t> simdjson_result<fallback::ondemand::document>::get_int64() noexcept {
41987
0
  if (error()) { return error(); }
41988
0
  return first.get_int64();
41989
0
}
41990
0
simdjson_inline simdjson_result<int64_t> simdjson_result<fallback::ondemand::document>::get_int64_in_string() noexcept {
41991
0
  if (error()) { return error(); }
41992
0
  return first.get_int64_in_string();
41993
0
}
41994
0
simdjson_inline simdjson_result<double> simdjson_result<fallback::ondemand::document>::get_double() noexcept {
41995
0
  if (error()) { return error(); }
41996
0
  return first.get_double();
41997
0
}
41998
0
simdjson_inline simdjson_result<double> simdjson_result<fallback::ondemand::document>::get_double_in_string() noexcept {
41999
0
  if (error()) { return error(); }
42000
0
  return first.get_double_in_string();
42001
0
}
42002
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::document>::get_string(bool allow_replacement) noexcept {
42003
0
  if (error()) { return error(); }
42004
0
  return first.get_string(allow_replacement);
42005
0
}
42006
template <typename string_type>
42007
simdjson_inline error_code simdjson_result<fallback::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
42008
  if (error()) { return error(); }
42009
  return first.get_string(receiver, allow_replacement);
42010
}
42011
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::document>::get_wobbly_string() noexcept {
42012
0
  if (error()) { return error(); }
42013
0
  return first.get_wobbly_string();
42014
0
}
42015
0
simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> simdjson_result<fallback::ondemand::document>::get_raw_json_string() noexcept {
42016
0
  if (error()) { return error(); }
42017
0
  return first.get_raw_json_string();
42018
0
}
42019
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document>::get_bool() noexcept {
42020
0
  if (error()) { return error(); }
42021
0
  return first.get_bool();
42022
0
}
42023
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::get_value() noexcept {
42024
0
  if (error()) { return error(); }
42025
0
  return first.get_value();
42026
0
}
42027
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document>::is_null() noexcept {
42028
0
  if (error()) { return error(); }
42029
0
  return first.is_null();
42030
0
}
42031
42032
template<typename T>
42033
simdjson_inline simdjson_result<T> simdjson_result<fallback::ondemand::document>::get() & noexcept {
42034
  if (error()) { return error(); }
42035
  return first.get<T>();
42036
}
42037
template<typename T>
42038
simdjson_inline simdjson_result<T> simdjson_result<fallback::ondemand::document>::get() && noexcept {
42039
  if (error()) { return error(); }
42040
  return std::forward<fallback::ondemand::document>(first).get<T>();
42041
}
42042
template<typename T>
42043
simdjson_inline error_code simdjson_result<fallback::ondemand::document>::get(T &out) & noexcept {
42044
  if (error()) { return error(); }
42045
  return first.get<T>(out);
42046
}
42047
template<typename T>
42048
simdjson_inline error_code simdjson_result<fallback::ondemand::document>::get(T &out) && noexcept {
42049
  if (error()) { return error(); }
42050
  return std::forward<fallback::ondemand::document>(first).get<T>(out);
42051
}
42052
42053
template<> simdjson_inline simdjson_result<fallback::ondemand::document> simdjson_result<fallback::ondemand::document>::get<fallback::ondemand::document>() & noexcept = delete;
42054
0
template<> simdjson_inline simdjson_result<fallback::ondemand::document> simdjson_result<fallback::ondemand::document>::get<fallback::ondemand::document>() && noexcept {
42055
0
  if (error()) { return error(); }
42056
0
  return std::forward<fallback::ondemand::document>(first);
42057
0
}
42058
template<> simdjson_inline error_code simdjson_result<fallback::ondemand::document>::get<fallback::ondemand::document>(fallback::ondemand::document &out) & noexcept = delete;
42059
0
template<> simdjson_inline error_code simdjson_result<fallback::ondemand::document>::get<fallback::ondemand::document>(fallback::ondemand::document &out) && noexcept {
42060
0
  if (error()) { return error(); }
42061
0
  out = std::forward<fallback::ondemand::document>(first);
42062
0
  return SUCCESS;
42063
0
}
42064
42065
0
simdjson_inline simdjson_result<fallback::ondemand::json_type> simdjson_result<fallback::ondemand::document>::type() noexcept {
42066
0
  if (error()) { return error(); }
42067
0
  return first.type();
42068
0
}
42069
42070
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document>::is_scalar() noexcept {
42071
0
  if (error()) { return error(); }
42072
0
  return first.is_scalar();
42073
0
}
42074
42075
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document>::is_string() noexcept {
42076
0
  if (error()) { return error(); }
42077
0
  return first.is_string();
42078
0
}
42079
42080
0
simdjson_inline bool simdjson_result<fallback::ondemand::document>::is_negative() noexcept {
42081
0
  if (error()) { return error(); }
42082
0
  return first.is_negative();
42083
0
}
42084
42085
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document>::is_integer() noexcept {
42086
0
  if (error()) { return error(); }
42087
0
  return first.is_integer();
42088
0
}
42089
42090
0
simdjson_inline simdjson_result<fallback::number_type> simdjson_result<fallback::ondemand::document>::get_number_type() noexcept {
42091
0
  if (error()) { return error(); }
42092
0
  return first.get_number_type();
42093
0
}
42094
42095
0
simdjson_inline simdjson_result<fallback::ondemand::number> simdjson_result<fallback::ondemand::document>::get_number() noexcept {
42096
0
  if (error()) { return error(); }
42097
0
  return first.get_number();
42098
0
}
42099
42100
42101
#if SIMDJSON_EXCEPTIONS
42102
template <class T, typename std::enable_if<std::is_same<T, fallback::ondemand::document>::value == false>::type>
42103
simdjson_inline simdjson_result<fallback::ondemand::document>::operator T() noexcept(false) {
42104
  if (error()) { throw simdjson_error(error()); }
42105
  return first;
42106
}
42107
simdjson_inline simdjson_result<fallback::ondemand::document>::operator fallback::ondemand::array() & noexcept(false) {
42108
  if (error()) { throw simdjson_error(error()); }
42109
  return first;
42110
}
42111
simdjson_inline simdjson_result<fallback::ondemand::document>::operator fallback::ondemand::object() & noexcept(false) {
42112
  if (error()) { throw simdjson_error(error()); }
42113
  return first;
42114
}
42115
simdjson_inline simdjson_result<fallback::ondemand::document>::operator uint64_t() noexcept(false) {
42116
  if (error()) { throw simdjson_error(error()); }
42117
  return first;
42118
}
42119
simdjson_inline simdjson_result<fallback::ondemand::document>::operator int64_t() noexcept(false) {
42120
  if (error()) { throw simdjson_error(error()); }
42121
  return first;
42122
}
42123
simdjson_inline simdjson_result<fallback::ondemand::document>::operator double() noexcept(false) {
42124
  if (error()) { throw simdjson_error(error()); }
42125
  return first;
42126
}
42127
simdjson_inline simdjson_result<fallback::ondemand::document>::operator std::string_view() noexcept(false) {
42128
  if (error()) { throw simdjson_error(error()); }
42129
  return first;
42130
}
42131
simdjson_inline simdjson_result<fallback::ondemand::document>::operator fallback::ondemand::raw_json_string() noexcept(false) {
42132
  if (error()) { throw simdjson_error(error()); }
42133
  return first;
42134
}
42135
simdjson_inline simdjson_result<fallback::ondemand::document>::operator bool() noexcept(false) {
42136
  if (error()) { throw simdjson_error(error()); }
42137
  return first;
42138
}
42139
simdjson_inline simdjson_result<fallback::ondemand::document>::operator fallback::ondemand::value() noexcept(false) {
42140
  if (error()) { throw simdjson_error(error()); }
42141
  return first;
42142
}
42143
#endif
42144
42145
42146
0
simdjson_inline simdjson_result<const char *> simdjson_result<fallback::ondemand::document>::current_location() noexcept {
42147
0
  if (error()) { return error(); }
42148
0
  return first.current_location();
42149
0
}
42150
42151
0
simdjson_inline bool simdjson_result<fallback::ondemand::document>::at_end() const noexcept {
42152
0
  if (error()) { return error(); }
42153
0
  return first.at_end();
42154
0
}
42155
42156
42157
0
simdjson_inline int32_t simdjson_result<fallback::ondemand::document>::current_depth() const noexcept {
42158
0
  if (error()) { return error(); }
42159
0
  return first.current_depth();
42160
0
}
42161
42162
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::document>::raw_json_token() noexcept {
42163
0
  if (error()) { return error(); }
42164
0
  return first.raw_json_token();
42165
0
}
42166
42167
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::at_pointer(std::string_view json_pointer) noexcept {
42168
0
  if (error()) { return error(); }
42169
0
  return first.at_pointer(json_pointer);
42170
0
}
42171
42172
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document>::at_path(std::string_view json_path) noexcept {
42173
0
  if (error()) { return error(); }
42174
0
  return first.at_path(json_path);
42175
0
}
42176
42177
} // namespace simdjson
42178
42179
42180
namespace simdjson {
42181
namespace fallback {
42182
namespace ondemand {
42183
42184
simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {}
42185
simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
42186
0
simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
42187
0
simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
42188
0
simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
42189
/**
42190
 * The document_reference instances are used primarily/solely for streams of JSON
42191
 * documents.
42192
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
42193
 * give an error, so we check for trailing content.
42194
 *
42195
 * However, for streams of JSON documents, we want to be able to start from
42196
 * "321" "321" "321"
42197
 * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
42198
 * successfully each time.
42199
 *
42200
 * To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
42201
 * this indicates that we allow trailing content.
42202
 */
42203
0
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
42204
0
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
42205
0
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
42206
0
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
42207
0
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
42208
0
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
42209
0
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
42210
template <typename string_type>
42211
simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
42212
0
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
42213
0
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
42214
0
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
42215
0
simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
42216
0
simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
42217
0
template<> simdjson_inline simdjson_result<array> document_reference::get() & noexcept { return get_array(); }
42218
0
template<> simdjson_inline simdjson_result<object> document_reference::get() & noexcept { return get_object(); }
42219
0
template<> simdjson_inline simdjson_result<raw_json_string> document_reference::get() & noexcept { return get_raw_json_string(); }
42220
0
template<> simdjson_inline simdjson_result<std::string_view> document_reference::get() & noexcept { return get_string(false); }
42221
0
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
42222
0
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
42223
0
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
42224
0
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
42225
0
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
42226
#if SIMDJSON_EXCEPTIONS
42227
template <class T>
42228
simdjson_inline document_reference::operator T() noexcept(false) { return get<T>(); }
42229
simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
42230
simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
42231
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
42232
simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
42233
simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
42234
simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
42235
simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
42236
simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
42237
simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
42238
#endif
42239
0
simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
42240
0
simdjson_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
42241
0
simdjson_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
42242
0
simdjson_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
42243
0
simdjson_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
42244
0
simdjson_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
42245
0
simdjson_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
42246
0
simdjson_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
42247
0
simdjson_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
42248
0
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
42249
0
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
42250
0
simdjson_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
42251
0
simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
42252
0
simdjson_inline simdjson_result<bool> document_reference::is_string() noexcept { return doc->is_string(); }
42253
0
simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
42254
0
simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
42255
0
simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
42256
0
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
42257
0
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
42258
0
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
42259
0
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
42260
0
simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
42261
0
simdjson_inline simdjson_result<value> document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); }
42262
0
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
42263
0
simdjson_inline document_reference::operator document&() const noexcept { return *doc; }
42264
42265
} // namespace ondemand
42266
} // namespace fallback
42267
} // namespace simdjson
42268
42269
42270
42271
namespace simdjson {
42272
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::simdjson_result(fallback::ondemand::document_reference value, error_code error)
42273
  noexcept : implementation_simdjson_result_base<fallback::ondemand::document_reference>(std::forward<fallback::ondemand::document_reference>(value), error) {}
42274
42275
42276
0
simdjson_inline simdjson_result<size_t> simdjson_result<fallback::ondemand::document_reference>::count_elements() & noexcept {
42277
0
  if (error()) { return error(); }
42278
0
  return first.count_elements();
42279
0
}
42280
0
simdjson_inline simdjson_result<size_t> simdjson_result<fallback::ondemand::document_reference>::count_fields() & noexcept {
42281
0
  if (error()) { return error(); }
42282
0
  return first.count_fields();
42283
0
}
42284
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::at(size_t index) & noexcept {
42285
0
  if (error()) { return error(); }
42286
0
  return first.at(index);
42287
0
}
42288
0
simdjson_inline error_code simdjson_result<fallback::ondemand::document_reference>::rewind() noexcept {
42289
0
  if (error()) { return error(); }
42290
0
  first.rewind();
42291
0
  return SUCCESS;
42292
0
}
42293
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::document_reference>::begin() & noexcept {
42294
0
  if (error()) { return error(); }
42295
0
  return first.begin();
42296
0
}
42297
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::document_reference>::end() & noexcept {
42298
0
  return {};
42299
0
}
42300
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
42301
0
  if (error()) { return error(); }
42302
0
  return first.find_field_unordered(key);
42303
0
}
42304
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
42305
0
  if (error()) { return error(); }
42306
0
  return first.find_field_unordered(key);
42307
0
}
42308
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
42309
0
  if (error()) { return error(); }
42310
0
  return first[key];
42311
0
}
42312
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::operator[](const char *key) & noexcept {
42313
0
  if (error()) { return error(); }
42314
0
  return first[key];
42315
0
}
42316
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
42317
0
  if (error()) { return error(); }
42318
0
  return first.find_field(key);
42319
0
}
42320
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::find_field(const char *key) & noexcept {
42321
0
  if (error()) { return error(); }
42322
0
  return first.find_field(key);
42323
0
}
42324
0
simdjson_inline simdjson_result<fallback::ondemand::array> simdjson_result<fallback::ondemand::document_reference>::get_array() & noexcept {
42325
0
  if (error()) { return error(); }
42326
0
  return first.get_array();
42327
0
}
42328
0
simdjson_inline simdjson_result<fallback::ondemand::object> simdjson_result<fallback::ondemand::document_reference>::get_object() & noexcept {
42329
0
  if (error()) { return error(); }
42330
0
  return first.get_object();
42331
0
}
42332
0
simdjson_inline simdjson_result<uint64_t> simdjson_result<fallback::ondemand::document_reference>::get_uint64() noexcept {
42333
0
  if (error()) { return error(); }
42334
0
  return first.get_uint64();
42335
0
}
42336
0
simdjson_inline simdjson_result<uint64_t> simdjson_result<fallback::ondemand::document_reference>::get_uint64_in_string() noexcept {
42337
0
  if (error()) { return error(); }
42338
0
  return first.get_uint64_in_string();
42339
0
}
42340
0
simdjson_inline simdjson_result<int64_t> simdjson_result<fallback::ondemand::document_reference>::get_int64() noexcept {
42341
0
  if (error()) { return error(); }
42342
0
  return first.get_int64();
42343
0
}
42344
0
simdjson_inline simdjson_result<int64_t> simdjson_result<fallback::ondemand::document_reference>::get_int64_in_string() noexcept {
42345
0
  if (error()) { return error(); }
42346
0
  return first.get_int64_in_string();
42347
0
}
42348
0
simdjson_inline simdjson_result<double> simdjson_result<fallback::ondemand::document_reference>::get_double() noexcept {
42349
0
  if (error()) { return error(); }
42350
0
  return first.get_double();
42351
0
}
42352
0
simdjson_inline simdjson_result<double> simdjson_result<fallback::ondemand::document_reference>::get_double_in_string() noexcept {
42353
0
  if (error()) { return error(); }
42354
0
  return first.get_double_in_string();
42355
0
}
42356
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::document_reference>::get_string(bool allow_replacement) noexcept {
42357
0
  if (error()) { return error(); }
42358
0
  return first.get_string(allow_replacement);
42359
0
}
42360
template <typename string_type>
42361
simdjson_inline error_code simdjson_result<fallback::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
42362
  if (error()) { return error(); }
42363
  return first.get_string(receiver, allow_replacement);
42364
}
42365
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::document_reference>::get_wobbly_string() noexcept {
42366
0
  if (error()) { return error(); }
42367
0
  return first.get_wobbly_string();
42368
0
}
42369
0
simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> simdjson_result<fallback::ondemand::document_reference>::get_raw_json_string() noexcept {
42370
0
  if (error()) { return error(); }
42371
0
  return first.get_raw_json_string();
42372
0
}
42373
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document_reference>::get_bool() noexcept {
42374
0
  if (error()) { return error(); }
42375
0
  return first.get_bool();
42376
0
}
42377
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::get_value() noexcept {
42378
0
  if (error()) { return error(); }
42379
0
  return first.get_value();
42380
0
}
42381
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document_reference>::is_null() noexcept {
42382
0
  if (error()) { return error(); }
42383
0
  return first.is_null();
42384
0
}
42385
0
simdjson_inline simdjson_result<fallback::ondemand::json_type> simdjson_result<fallback::ondemand::document_reference>::type() noexcept {
42386
0
  if (error()) { return error(); }
42387
0
  return first.type();
42388
0
}
42389
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document_reference>::is_scalar() noexcept {
42390
0
  if (error()) { return error(); }
42391
0
  return first.is_scalar();
42392
0
}
42393
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document_reference>::is_string() noexcept {
42394
0
  if (error()) { return error(); }
42395
0
  return first.is_string();
42396
0
}
42397
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document_reference>::is_negative() noexcept {
42398
0
  if (error()) { return error(); }
42399
0
  return first.is_negative();
42400
0
}
42401
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::document_reference>::is_integer() noexcept {
42402
0
  if (error()) { return error(); }
42403
0
  return first.is_integer();
42404
0
}
42405
0
simdjson_inline simdjson_result<fallback::number_type> simdjson_result<fallback::ondemand::document_reference>::get_number_type() noexcept {
42406
0
  if (error()) { return error(); }
42407
0
  return first.get_number_type();
42408
0
}
42409
0
simdjson_inline simdjson_result<fallback::ondemand::number> simdjson_result<fallback::ondemand::document_reference>::get_number() noexcept {
42410
0
  if (error()) { return error(); }
42411
0
  return first.get_number();
42412
0
}
42413
#if SIMDJSON_EXCEPTIONS
42414
template <class T, typename std::enable_if<std::is_same<T, fallback::ondemand::document_reference>::value == false>::type>
42415
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator T() noexcept(false) {
42416
  if (error()) { throw simdjson_error(error()); }
42417
  return first;
42418
}
42419
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator fallback::ondemand::array() & noexcept(false) {
42420
  if (error()) { throw simdjson_error(error()); }
42421
  return first;
42422
}
42423
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator fallback::ondemand::object() & noexcept(false) {
42424
  if (error()) { throw simdjson_error(error()); }
42425
  return first;
42426
}
42427
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator uint64_t() noexcept(false) {
42428
  if (error()) { throw simdjson_error(error()); }
42429
  return first;
42430
}
42431
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator int64_t() noexcept(false) {
42432
  if (error()) { throw simdjson_error(error()); }
42433
  return first;
42434
}
42435
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator double() noexcept(false) {
42436
  if (error()) { throw simdjson_error(error()); }
42437
  return first;
42438
}
42439
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator std::string_view() noexcept(false) {
42440
  if (error()) { throw simdjson_error(error()); }
42441
  return first;
42442
}
42443
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator fallback::ondemand::raw_json_string() noexcept(false) {
42444
  if (error()) { throw simdjson_error(error()); }
42445
  return first;
42446
}
42447
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator bool() noexcept(false) {
42448
  if (error()) { throw simdjson_error(error()); }
42449
  return first;
42450
}
42451
simdjson_inline simdjson_result<fallback::ondemand::document_reference>::operator fallback::ondemand::value() noexcept(false) {
42452
  if (error()) { throw simdjson_error(error()); }
42453
  return first;
42454
}
42455
#endif
42456
42457
0
simdjson_inline simdjson_result<const char *> simdjson_result<fallback::ondemand::document_reference>::current_location() noexcept {
42458
0
  if (error()) { return error(); }
42459
0
  return first.current_location();
42460
0
}
42461
42462
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::document_reference>::raw_json_token() noexcept {
42463
0
  if (error()) { return error(); }
42464
0
  return first.raw_json_token();
42465
0
}
42466
42467
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
42468
0
  if (error()) { return error(); }
42469
0
  return first.at_pointer(json_pointer);
42470
0
}
42471
42472
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::document_reference>::at_path(std::string_view json_path) noexcept {
42473
0
  if (error()) {
42474
0
      return error();
42475
0
  }
42476
0
  return first.at_path(json_path);
42477
0
}
42478
42479
} // namespace simdjson
42480
42481
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
42482
/* end file simdjson/generic/ondemand/document-inl.h for fallback */
42483
/* including simdjson/generic/ondemand/document_stream-inl.h for fallback: #include "simdjson/generic/ondemand/document_stream-inl.h" */
42484
/* begin file simdjson/generic/ondemand/document_stream-inl.h for fallback */
42485
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
42486
42487
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
42488
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */
42489
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
42490
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
42491
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
42492
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
42493
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
42494
42495
#include <algorithm>
42496
#include <stdexcept>
42497
42498
namespace simdjson {
42499
namespace fallback {
42500
namespace ondemand {
42501
42502
#ifdef SIMDJSON_THREADS_ENABLED
42503
42504
0
inline void stage1_worker::finish() {
42505
0
  // After calling "run" someone would call finish() to wait
42506
0
  // for the end of the processing.
42507
0
  // This function will wait until either the thread has done
42508
0
  // the processing or, else, the destructor has been called.
42509
0
  std::unique_lock<std::mutex> lock(locking_mutex);
42510
0
  cond_var.wait(lock, [this]{return has_work == false;});
42511
0
}
42512
42513
inline stage1_worker::~stage1_worker() {
42514
  // The thread may never outlive the stage1_worker instance
42515
  // and will always be stopped/joined before the stage1_worker
42516
  // instance is gone.
42517
  stop_thread();
42518
}
42519
42520
0
inline void stage1_worker::start_thread() {
42521
0
  std::unique_lock<std::mutex> lock(locking_mutex);
42522
0
  if(thread.joinable()) {
42523
0
    return; // This should never happen but we never want to create more than one thread.
42524
0
  }
42525
0
  thread = std::thread([this]{
42526
0
      while(true) {
42527
0
        std::unique_lock<std::mutex> thread_lock(locking_mutex);
42528
0
        // We wait for either "run" or "stop_thread" to be called.
42529
0
        cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
42530
0
        // If, for some reason, the stop_thread() method was called (i.e., the
42531
0
        // destructor of stage1_worker is called, then we want to immediately destroy
42532
0
        // the thread (and not do any more processing).
42533
0
        if(!can_work) {
42534
0
          break;
42535
0
        }
42536
0
        this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
42537
0
              this->_next_batch_start);
42538
0
        this->has_work = false;
42539
0
        // The condition variable call should be moved after thread_lock.unlock() for performance
42540
0
        // reasons but thread sanitizers may report it as a data race if we do.
42541
0
        // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
42542
0
        cond_var.notify_one(); // will notify "finish"
42543
0
        thread_lock.unlock();
42544
0
      }
42545
0
    }
42546
0
  );
42547
0
}
42548
42549
42550
0
inline void stage1_worker::stop_thread() {
42551
0
  std::unique_lock<std::mutex> lock(locking_mutex);
42552
0
  // We have to make sure that all locks can be released.
42553
0
  can_work = false;
42554
0
  has_work = false;
42555
0
  cond_var.notify_all();
42556
0
  lock.unlock();
42557
0
  if(thread.joinable()) {
42558
0
    thread.join();
42559
0
  }
42560
0
}
42561
42562
0
inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) {
42563
0
  std::unique_lock<std::mutex> lock(locking_mutex);
42564
0
  owner = ds;
42565
0
  _next_batch_start = next_batch_start;
42566
0
  stage1_thread_parser = stage1;
42567
0
  has_work = true;
42568
0
  // The condition variable call should be moved after thread_lock.unlock() for performance
42569
0
  // reasons but thread sanitizers may report it as a data race if we do.
42570
0
  // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
42571
0
  cond_var.notify_one(); // will notify the thread lock that we have work
42572
0
  lock.unlock();
42573
0
}
42574
42575
#endif  // SIMDJSON_THREADS_ENABLED
42576
42577
simdjson_inline document_stream::document_stream(
42578
  ondemand::parser &_parser,
42579
  const uint8_t *_buf,
42580
  size_t _len,
42581
  size_t _batch_size,
42582
  bool _allow_comma_separated
42583
) noexcept
42584
  : parser{&_parser},
42585
    buf{_buf},
42586
    len{_len},
42587
    batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
42588
    allow_comma_separated{_allow_comma_separated},
42589
    error{SUCCESS}
42590
    #ifdef SIMDJSON_THREADS_ENABLED
42591
    , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
42592
    #endif
42593
{
42594
#ifdef SIMDJSON_THREADS_ENABLED
42595
  if(worker.get() == nullptr) {
42596
    error = MEMALLOC;
42597
  }
42598
#endif
42599
}
42600
42601
simdjson_inline document_stream::document_stream() noexcept
42602
  : parser{nullptr},
42603
    buf{nullptr},
42604
    len{0},
42605
    batch_size{0},
42606
    allow_comma_separated{false},
42607
    error{UNINITIALIZED}
42608
    #ifdef SIMDJSON_THREADS_ENABLED
42609
    , use_thread(false)
42610
    #endif
42611
{
42612
}
42613
42614
simdjson_inline document_stream::~document_stream() noexcept
42615
{
42616
  #ifdef SIMDJSON_THREADS_ENABLED
42617
  worker.reset();
42618
  #endif
42619
}
42620
42621
0
inline size_t document_stream::size_in_bytes() const noexcept {
42622
0
  return len;
42623
0
}
42624
42625
0
inline size_t document_stream::truncated_bytes() const noexcept {
42626
0
  if(error == CAPACITY) { return len - batch_start; }
42627
0
  return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
42628
0
}
42629
42630
simdjson_inline document_stream::iterator::iterator() noexcept
42631
  : stream{nullptr}, finished{true} {
42632
}
42633
42634
simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
42635
  : stream{_stream}, finished{is_end} {
42636
}
42637
42638
0
simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
42639
0
  //if(stream->error) { return stream->error; }
42640
0
  return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
42641
0
}
42642
42643
0
simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
42644
0
  // If there is an error, then we want the iterator
42645
0
  // to be finished, no matter what. (E.g., we do not
42646
0
  // keep generating documents with errors, or go beyond
42647
0
  // a document with errors.)
42648
0
  //
42649
0
  // Users do not have to call "operator*()" when they use operator++,
42650
0
  // so we need to end the stream in the operator++ function.
42651
0
  //
42652
0
  // Note that setting finished = true is essential otherwise
42653
0
  // we would enter an infinite loop.
42654
0
  if (stream->error) { finished = true; }
42655
0
  // Note that stream->error() is guarded against error conditions
42656
0
  // (it will immediately return if stream->error casts to false).
42657
0
  // In effect, this next function does nothing when (stream->error)
42658
0
  // is true (hence the risk of an infinite loop).
42659
0
  stream->next();
42660
0
  // If that was the last document, we're finished.
42661
0
  // It is the only type of error we do not want to appear
42662
0
  // in operator*.
42663
0
  if (stream->error == EMPTY) { finished = true; }
42664
0
  // If we had any other kind of error (not EMPTY) then we want
42665
0
  // to pass it along to the operator* and we cannot mark the result
42666
0
  // as "finished" just yet.
42667
0
  return *this;
42668
0
}
42669
42670
0
simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
42671
0
  return finished != other.finished;
42672
0
}
42673
42674
0
simdjson_inline document_stream::iterator document_stream::begin() noexcept {
42675
0
  start();
42676
0
  // If there are no documents, we're finished.
42677
0
  return iterator(this, error == EMPTY);
42678
0
}
42679
42680
0
simdjson_inline document_stream::iterator document_stream::end() noexcept {
42681
0
  return iterator(this, true);
42682
0
}
42683
42684
0
inline void document_stream::start() noexcept {
42685
0
  if (error) { return; }
42686
0
  error = parser->allocate(batch_size);
42687
0
  if (error) { return; }
42688
0
  // Always run the first stage 1 parse immediately
42689
0
  batch_start = 0;
42690
0
  error = run_stage1(*parser, batch_start);
42691
0
  while(error == EMPTY) {
42692
0
    // In exceptional cases, we may start with an empty block
42693
0
    batch_start = next_batch_start();
42694
0
    if (batch_start >= len) { return; }
42695
0
    error = run_stage1(*parser, batch_start);
42696
0
  }
42697
0
  if (error) { return; }
42698
0
  doc_index = batch_start;
42699
0
  doc = document(json_iterator(&buf[batch_start], parser));
42700
0
  doc.iter._streaming = true;
42701
0
42702
0
  #ifdef SIMDJSON_THREADS_ENABLED
42703
0
  if (use_thread && next_batch_start() < len) {
42704
0
    // Kick off the first thread on next batch if needed
42705
0
    error = stage1_thread_parser.allocate(batch_size);
42706
0
    if (error) { return; }
42707
0
    worker->start_thread();
42708
0
    start_stage1_thread();
42709
0
    if (error) { return; }
42710
0
  }
42711
0
  #endif // SIMDJSON_THREADS_ENABLED
42712
0
}
42713
42714
0
inline void document_stream::next() noexcept {
42715
0
  // We always enter at once once in an error condition.
42716
0
  if (error) { return; }
42717
0
  next_document();
42718
0
  if (error) { return; }
42719
0
  auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get();
42720
0
  doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index];
42721
0
42722
0
  // Check if at end of structural indexes (i.e. at end of batch)
42723
0
  if(cur_struct_index >= static_cast<int64_t>(parser->implementation->n_structural_indexes)) {
42724
0
    error = EMPTY;
42725
0
    // Load another batch (if available)
42726
0
    while (error == EMPTY) {
42727
0
      batch_start = next_batch_start();
42728
0
      if (batch_start >= len) { break; }
42729
0
      #ifdef SIMDJSON_THREADS_ENABLED
42730
0
      if(use_thread) {
42731
0
        load_from_stage1_thread();
42732
0
      } else {
42733
0
        error = run_stage1(*parser, batch_start);
42734
0
      }
42735
0
      #else
42736
0
      error = run_stage1(*parser, batch_start);
42737
0
      #endif
42738
0
      /**
42739
0
       * Whenever we move to another window, we need to update all pointers to make
42740
0
       * it appear as if the input buffer started at the beginning of the window.
42741
0
       *
42742
0
       * Take this input:
42743
0
       *
42744
0
       * {"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]  [15,  11,   12, 13]  [154,  110,   112, 1311]
42745
0
       *
42746
0
       * Say you process the following window...
42747
0
       *
42748
0
       * '{"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]'
42749
0
       *
42750
0
       * When you do so, the json_iterator has a pointer at the beginning of the memory region
42751
0
       * (pointing at the beginning of '{"z"...'.
42752
0
       *
42753
0
       * When you move to the window that starts at...
42754
0
       *
42755
0
       * '[7,  10,   9]  [15,  11,   12, 13] ...
42756
0
       *
42757
0
       * then it is not sufficient to just run stage 1. You also need to re-anchor the
42758
0
       * json_iterator so that it believes we are starting at '[7,  10,   9]...'.
42759
0
       *
42760
0
       * Under the DOM front-end, this gets done automatically because the parser owns
42761
0
       * the pointer the data, and when you call stage1 and then stage2 on the same
42762
0
       * parser, then stage2 will run on the pointer acquired by stage1.
42763
0
       *
42764
0
       * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that
42765
0
       * we used. But json_iterator has no callback when stage1 is called on the parser.
42766
0
       * In fact, I think that the parser is unaware of json_iterator.
42767
0
       *
42768
0
       *
42769
0
       * So we need to re-anchor the json_iterator after each call to stage 1 so that
42770
0
       * all of the pointers are in sync.
42771
0
       */
42772
0
      doc.iter = json_iterator(&buf[batch_start], parser);
42773
0
      doc.iter._streaming = true;
42774
0
      /**
42775
0
       * End of resync.
42776
0
       */
42777
0
42778
0
      if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
42779
0
      doc_index = batch_start;
42780
0
    }
42781
0
  }
42782
0
}
42783
42784
0
inline void document_stream::next_document() noexcept {
42785
0
  // Go to next place where depth=0 (document depth)
42786
0
  error = doc.iter.skip_child(0);
42787
0
  if (error) { return; }
42788
0
  // Always set depth=1 at the start of document
42789
0
  doc.iter._depth = 1;
42790
0
  // consume comma if comma separated is allowed
42791
0
  if (allow_comma_separated) { doc.iter.consume_character(','); }
42792
0
  // Resets the string buffer at the beginning, thus invalidating the strings.
42793
0
  doc.iter._string_buf_loc = parser->string_buf.get();
42794
0
  doc.iter._root = doc.iter.position();
42795
0
}
42796
42797
0
inline size_t document_stream::next_batch_start() const noexcept {
42798
0
  return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
42799
0
}
42800
42801
0
inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept {
42802
0
  // This code only updates the structural index in the parser, it does not update any json_iterator
42803
0
  // instance.
42804
0
  size_t remaining = len - _batch_start;
42805
0
  if (remaining <= batch_size) {
42806
0
    return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
42807
0
  } else {
42808
0
    return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
42809
0
  }
42810
0
}
42811
42812
0
simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
42813
0
  return stream->doc_index;
42814
0
}
42815
42816
0
simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
42817
0
  auto depth = stream->doc.iter.depth();
42818
0
  auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get();
42819
0
42820
0
  // If at root, process the first token to determine if scalar value
42821
0
  if (stream->doc.iter.at_root()) {
42822
0
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
42823
0
      case '{': case '[':   // Depth=1 already at start of document
42824
0
        break;
42825
0
      case '}': case ']':
42826
0
        depth--;
42827
0
        break;
42828
0
      default:    // Scalar value document
42829
0
        // TODO: Remove any trailing whitespaces
42830
0
        // This returns a string spanning from start of value to the beginning of the next document (excluded)
42831
0
        return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[++cur_struct_index] - current_index() - 1);
42832
0
    }
42833
0
    cur_struct_index++;
42834
0
  }
42835
0
42836
0
  while (cur_struct_index <= static_cast<int64_t>(stream->parser->implementation->n_structural_indexes)) {
42837
0
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
42838
0
      case '{': case '[':
42839
0
        depth++;
42840
0
        break;
42841
0
      case '}': case ']':
42842
0
        depth--;
42843
0
        break;
42844
0
    }
42845
0
    if (depth == 0) { break; }
42846
0
    cur_struct_index++;
42847
0
  }
42848
0
42849
0
  return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);;
42850
0
}
42851
42852
0
inline error_code document_stream::iterator::error() const noexcept {
42853
0
  return stream->error;
42854
0
}
42855
42856
#ifdef SIMDJSON_THREADS_ENABLED
42857
42858
0
inline void document_stream::load_from_stage1_thread() noexcept {
42859
0
  worker->finish();
42860
0
  // Swap to the parser that was loaded up in the thread. Make sure the parser has
42861
0
  // enough memory to swap to, as well.
42862
0
  std::swap(stage1_thread_parser,*parser);
42863
0
  error = stage1_thread_error;
42864
0
  if (error) { return; }
42865
0
42866
0
  // If there's anything left, start the stage 1 thread!
42867
0
  if (next_batch_start() < len) {
42868
0
    start_stage1_thread();
42869
0
  }
42870
0
}
42871
42872
0
inline void document_stream::start_stage1_thread() noexcept {
42873
0
  // we call the thread on a lambda that will update
42874
0
  // this->stage1_thread_error
42875
0
  // there is only one thread that may write to this value
42876
0
  // TODO this is NOT exception-safe.
42877
0
  this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
42878
0
  size_t _next_batch_start = this->next_batch_start();
42879
0
42880
0
  worker->run(this, & this->stage1_thread_parser, _next_batch_start);
42881
0
}
42882
42883
#endif // SIMDJSON_THREADS_ENABLED
42884
42885
} // namespace ondemand
42886
} // namespace fallback
42887
} // namespace simdjson
42888
42889
namespace simdjson {
42890
42891
simdjson_inline simdjson_result<fallback::ondemand::document_stream>::simdjson_result(
42892
  error_code error
42893
) noexcept :
42894
    implementation_simdjson_result_base<fallback::ondemand::document_stream>(error)
42895
{
42896
}
42897
simdjson_inline simdjson_result<fallback::ondemand::document_stream>::simdjson_result(
42898
  fallback::ondemand::document_stream &&value
42899
) noexcept :
42900
    implementation_simdjson_result_base<fallback::ondemand::document_stream>(
42901
      std::forward<fallback::ondemand::document_stream>(value)
42902
    )
42903
{
42904
}
42905
42906
}
42907
42908
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
42909
/* end file simdjson/generic/ondemand/document_stream-inl.h for fallback */
42910
/* including simdjson/generic/ondemand/field-inl.h for fallback: #include "simdjson/generic/ondemand/field-inl.h" */
42911
/* begin file simdjson/generic/ondemand/field-inl.h for fallback */
42912
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
42913
42914
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
42915
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */
42916
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
42917
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
42918
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
42919
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
42920
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
42921
42922
namespace simdjson {
42923
namespace fallback {
42924
namespace ondemand {
42925
42926
// clang 6 does not think the default constructor can be noexcept, so we make it explicit
42927
0
simdjson_inline field::field() noexcept : std::pair<raw_json_string, ondemand::value>() {}
42928
42929
simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept
42930
0
  : std::pair<raw_json_string, ondemand::value>(key, std::forward<ondemand::value>(value))
42931
0
{
42932
0
}
42933
42934
0
simdjson_inline simdjson_result<field> field::start(value_iterator &parent_iter) noexcept {
42935
0
  raw_json_string key;
42936
0
  SIMDJSON_TRY( parent_iter.field_key().get(key) );
42937
0
  SIMDJSON_TRY( parent_iter.field_value() );
42938
0
  return field::start(parent_iter, key);
42939
0
}
42940
42941
0
simdjson_inline simdjson_result<field> field::start(const value_iterator &parent_iter, raw_json_string key) noexcept {
42942
0
    return field(key, parent_iter.child());
42943
0
}
42944
42945
0
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> field::unescaped_key(bool allow_replacement) noexcept {
42946
0
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us.
42947
0
  simdjson_result<std::string_view> answer = first.unescape(second.iter.json_iter(), allow_replacement);
42948
0
  first.consume();
42949
0
  return answer;
42950
0
}
42951
42952
0
simdjson_inline raw_json_string field::key() const noexcept {
42953
0
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
42954
0
  return first;
42955
0
}
42956
42957
42958
0
simdjson_inline std::string_view field::key_raw_json_token() const noexcept {
42959
0
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
42960
0
  return std::string_view(reinterpret_cast<const char*>(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1);
42961
0
}
42962
42963
0
simdjson_inline value &field::value() & noexcept {
42964
0
  return second;
42965
0
}
42966
42967
0
simdjson_inline value field::value() && noexcept {
42968
0
  return std::forward<field>(*this).second;
42969
0
}
42970
42971
} // namespace ondemand
42972
} // namespace fallback
42973
} // namespace simdjson
42974
42975
namespace simdjson {
42976
42977
simdjson_inline simdjson_result<fallback::ondemand::field>::simdjson_result(
42978
  fallback::ondemand::field &&value
42979
) noexcept :
42980
0
    implementation_simdjson_result_base<fallback::ondemand::field>(
42981
0
      std::forward<fallback::ondemand::field>(value)
42982
0
    )
42983
0
{
42984
0
}
42985
simdjson_inline simdjson_result<fallback::ondemand::field>::simdjson_result(
42986
  error_code error
42987
) noexcept :
42988
0
    implementation_simdjson_result_base<fallback::ondemand::field>(error)
42989
0
{
42990
0
}
42991
42992
0
simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> simdjson_result<fallback::ondemand::field>::key() noexcept {
42993
0
  if (error()) { return error(); }
42994
0
  return first.key();
42995
0
}
42996
42997
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::field>::key_raw_json_token() noexcept {
42998
0
  if (error()) { return error(); }
42999
0
  return first.key_raw_json_token();
43000
0
}
43001
43002
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::field>::unescaped_key(bool allow_replacement) noexcept {
43003
0
  if (error()) { return error(); }
43004
0
  return first.unescaped_key(allow_replacement);
43005
0
}
43006
43007
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::field>::value() noexcept {
43008
0
  if (error()) { return error(); }
43009
0
  return std::move(first.value());
43010
0
}
43011
43012
} // namespace simdjson
43013
43014
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
43015
/* end file simdjson/generic/ondemand/field-inl.h for fallback */
43016
/* including simdjson/generic/ondemand/json_iterator-inl.h for fallback: #include "simdjson/generic/ondemand/json_iterator-inl.h" */
43017
/* begin file simdjson/generic/ondemand/json_iterator-inl.h for fallback */
43018
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
43019
43020
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
43021
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */
43022
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
43023
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
43024
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
43025
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
43026
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
43027
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */
43028
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */
43029
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */
43030
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
43031
43032
namespace simdjson {
43033
namespace fallback {
43034
namespace ondemand {
43035
43036
simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
43037
0
  : token(std::forward<token_iterator>(other.token)),
43038
0
    parser{other.parser},
43039
0
    _string_buf_loc{other._string_buf_loc},
43040
0
    error{other.error},
43041
0
    _depth{other._depth},
43042
0
    _root{other._root},
43043
0
    _streaming{other._streaming}
43044
0
{
43045
0
  other.parser = nullptr;
43046
0
}
43047
0
simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept {
43048
0
  token = other.token;
43049
0
  parser = other.parser;
43050
0
  _string_buf_loc = other._string_buf_loc;
43051
0
  error = other.error;
43052
0
  _depth = other._depth;
43053
0
  _root = other._root;
43054
0
  _streaming = other._streaming;
43055
0
  other.parser = nullptr;
43056
0
  return *this;
43057
0
}
43058
43059
simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept
43060
0
  : token(buf, &_parser->implementation->structural_indexes[0]),
43061
0
    parser{_parser},
43062
0
    _string_buf_loc{parser->string_buf.get()},
43063
0
    _depth{1},
43064
0
    _root{parser->implementation->structural_indexes.get()},
43065
0
    _streaming{false}
43066
43067
0
{
43068
0
  logger::log_headers();
43069
#if SIMDJSON_CHECK_EOF
43070
  assert_more_tokens();
43071
#endif
43072
0
}
43073
43074
0
inline void json_iterator::rewind() noexcept {
43075
0
  token.set_position( root_position() );
43076
0
  logger::log_headers(); // We start again
43077
0
  _string_buf_loc = parser->string_buf.get();
43078
0
  _depth = 1;
43079
0
}
43080
43081
0
inline bool json_iterator::balanced() const noexcept {
43082
0
  token_iterator ti(token);
43083
0
  int32_t count{0};
43084
0
  ti.set_position( root_position() );
43085
0
  while(ti.peek() <= peek_last()) {
43086
0
    switch (*ti.return_current_and_advance())
43087
0
    {
43088
0
    case '[': case '{':
43089
0
      count++;
43090
0
      break;
43091
0
    case ']': case '}':
43092
0
      count--;
43093
0
      break;
43094
0
    default:
43095
0
      break;
43096
0
    }
43097
0
  }
43098
0
  return count == 0;
43099
0
}
43100
43101
43102
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
43103
// relating depth and parent_depth, which is a desired effect. The warning does not show up if the
43104
// skip_child() function is not marked inline).
43105
SIMDJSON_PUSH_DISABLE_WARNINGS
43106
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
43107
0
simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
43108
0
  if (depth() <= parent_depth) { return SUCCESS; }
43109
0
  switch (*return_current_and_advance()) {
43110
    // TODO consider whether matching braces is a requirement: if non-matching braces indicates
43111
    // *missing* braces, then future lookups are not in the object/arrays they think they are,
43112
    // violating the rule "validate enough structure that the user can be confident they are
43113
    // looking at the right values."
43114
    // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
43115
43116
    // For the first open array/object in a value, we've already incremented depth, so keep it the same
43117
    // We never stop at colon, but if we did, it wouldn't affect depth
43118
0
    case '[': case '{': case ':':
43119
0
      logger::log_start_value(*this, "skip");
43120
0
      break;
43121
    // If there is a comma, we have just finished a value in an array/object, and need to get back in
43122
0
    case ',':
43123
0
      logger::log_value(*this, "skip");
43124
0
      break;
43125
    // ] or } means we just finished a value and need to jump out of the array/object
43126
0
    case ']': case '}':
43127
0
      logger::log_end_value(*this, "skip");
43128
0
      _depth--;
43129
0
      if (depth() <= parent_depth) { return SUCCESS; }
43130
#if SIMDJSON_CHECK_EOF
43131
      // If there are no more tokens, the parent is incomplete.
43132
      if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
43133
#endif // SIMDJSON_CHECK_EOF
43134
0
      break;
43135
0
    case '"':
43136
0
      if(*peek() == ':') {
43137
        // We are at a key!!!
43138
        // This might happen if you just started an object and you skip it immediately.
43139
        // Performance note: it would be nice to get rid of this check as it is somewhat
43140
        // expensive.
43141
        // https://github.com/simdjson/simdjson/issues/1742
43142
0
        logger::log_value(*this, "key");
43143
0
        return_current_and_advance(); // eat up the ':'
43144
0
        break; // important!!!
43145
0
      }
43146
0
      simdjson_fallthrough;
43147
    // Anything else must be a scalar value
43148
0
    default:
43149
      // For the first scalar, we will have incremented depth already, so we decrement it here.
43150
0
      logger::log_value(*this, "skip");
43151
0
      _depth--;
43152
0
      if (depth() <= parent_depth) { return SUCCESS; }
43153
0
      break;
43154
0
  }
43155
43156
  // Now that we've considered the first value, we only increment/decrement for arrays/objects
43157
0
  while (position() < end_position()) {
43158
0
    switch (*return_current_and_advance()) {
43159
0
      case '[': case '{':
43160
0
        logger::log_start_value(*this, "skip");
43161
0
        _depth++;
43162
0
        break;
43163
      // TODO consider whether matching braces is a requirement: if non-matching braces indicates
43164
      // *missing* braces, then future lookups are not in the object/arrays they think they are,
43165
      // violating the rule "validate enough structure that the user can be confident they are
43166
      // looking at the right values."
43167
      // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
43168
0
      case ']': case '}':
43169
0
        logger::log_end_value(*this, "skip");
43170
0
        _depth--;
43171
0
        if (depth() <= parent_depth) { return SUCCESS; }
43172
0
        break;
43173
0
      default:
43174
0
        logger::log_value(*this, "skip", "");
43175
0
        break;
43176
0
    }
43177
0
  }
43178
43179
0
  return report_error(TAPE_ERROR, "not enough close braces");
43180
0
}
43181
43182
SIMDJSON_POP_DISABLE_WARNINGS
43183
43184
0
simdjson_inline bool json_iterator::at_root() const noexcept {
43185
0
  return position() == root_position();
43186
0
}
43187
43188
0
simdjson_inline bool json_iterator::is_single_token() const noexcept {
43189
0
  return parser->implementation->n_structural_indexes == 1;
43190
0
}
43191
43192
0
simdjson_inline bool json_iterator::streaming() const noexcept {
43193
0
  return _streaming;
43194
0
}
43195
43196
0
simdjson_inline token_position json_iterator::root_position() const noexcept {
43197
0
  return _root;
43198
0
}
43199
43200
0
simdjson_inline void json_iterator::assert_at_document_depth() const noexcept {
43201
0
  SIMDJSON_ASSUME( _depth == 1 );
43202
0
}
43203
43204
0
simdjson_inline void json_iterator::assert_at_root() const noexcept {
43205
0
  SIMDJSON_ASSUME( _depth == 1 );
43206
0
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
43207
0
  // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument
43208
0
  // has side effects that will be discarded.
43209
0
  SIMDJSON_ASSUME( token.position() == _root );
43210
0
#endif
43211
0
}
43212
43213
0
simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
43214
0
  assert_valid_position(token._position + required_tokens - 1);
43215
0
}
43216
43217
0
simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
43218
0
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
43219
0
  SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
43220
0
  SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
43221
0
#endif
43222
0
}
43223
43224
0
simdjson_inline bool json_iterator::at_end() const noexcept {
43225
0
  return position() == end_position();
43226
0
}
43227
0
simdjson_inline token_position json_iterator::end_position() const noexcept {
43228
0
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
43229
0
  return &parser->implementation->structural_indexes[n_structural_indexes];
43230
0
}
43231
43232
0
inline std::string json_iterator::to_string() const noexcept {
43233
0
  if( !is_alive() ) { return "dead json_iterator instance"; }
43234
0
  const char * current_structural = reinterpret_cast<const char *>(token.peek());
43235
0
  return std::string("json_iterator [ depth : ") + std::to_string(_depth)
43236
0
          + std::string(", structural : '") + std::string(current_structural,1)
43237
0
          + std::string("', offset : ") + std::to_string(token.current_offset())
43238
0
          + std::string("', error : ") + error_message(error)
43239
0
          + std::string(" ]");
43240
0
}
43241
43242
0
inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
43243
0
  if (!is_alive()) {    // Unrecoverable error
43244
0
    if (!at_root()) {
43245
0
      return reinterpret_cast<const char *>(token.peek(-1));
43246
0
    } else {
43247
0
      return reinterpret_cast<const char *>(token.peek());
43248
0
    }
43249
0
  }
43250
0
  if (at_end()) {
43251
0
    return OUT_OF_BOUNDS;
43252
0
  }
43253
0
  return reinterpret_cast<const char *>(token.peek());
43254
0
}
43255
43256
0
simdjson_inline bool json_iterator::is_alive() const noexcept {
43257
0
  return parser;
43258
0
}
43259
43260
0
simdjson_inline void json_iterator::abandon() noexcept {
43261
0
  parser = nullptr;
43262
0
  _depth = 0;
43263
0
}
43264
43265
0
simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
43266
#if SIMDJSON_CHECK_EOF
43267
  assert_more_tokens();
43268
#endif // SIMDJSON_CHECK_EOF
43269
0
  return token.return_current_and_advance();
43270
0
}
43271
43272
0
simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
43273
  // deliberately done without safety guard:
43274
0
  return token.peek();
43275
0
}
43276
43277
0
simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
43278
#if SIMDJSON_CHECK_EOF
43279
  assert_more_tokens(delta+1);
43280
#endif // SIMDJSON_CHECK_EOF
43281
0
  return token.peek(delta);
43282
0
}
43283
43284
0
simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
43285
0
#if SIMDJSON_CHECK_EOF
43286
0
  assert_more_tokens(delta+1);
43287
0
#endif // #if SIMDJSON_CHECK_EOF
43288
0
  return token.peek_length(delta);
43289
0
}
43290
43291
0
simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
43292
  // todo: currently we require end-of-string buffering, but the following
43293
  // assert_valid_position should be turned on if/when we lift that condition.
43294
  // assert_valid_position(position);
43295
  // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
43296
  // is ON by default, we have no choice but to disable it for real with a comment.
43297
0
  return token.peek(position);
43298
0
}
43299
43300
0
simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
43301
#if SIMDJSON_CHECK_EOF
43302
  assert_valid_position(position);
43303
#endif // SIMDJSON_CHECK_EOF
43304
0
  return token.peek_length(position);
43305
0
}
43306
0
simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept {
43307
0
#if SIMDJSON_CHECK_EOF
43308
0
  assert_valid_position(position);
43309
0
#endif // SIMDJSON_CHECK_EOF
43310
0
  return token.peek_root_length(position);
43311
0
}
43312
43313
0
simdjson_inline token_position json_iterator::last_position() const noexcept {
43314
  // The following line fails under some compilers...
43315
  // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0);
43316
  // since it has side-effects.
43317
0
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
43318
0
  SIMDJSON_ASSUME(n_structural_indexes > 0);
43319
0
  return &parser->implementation->structural_indexes[n_structural_indexes - 1];
43320
0
}
43321
0
simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept {
43322
0
  return token.peek(last_position());
43323
0
}
43324
43325
0
simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
43326
0
  SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
43327
0
  SIMDJSON_ASSUME(_depth == parent_depth + 1);
43328
0
  _depth = parent_depth;
43329
0
}
43330
43331
0
simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
43332
0
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
43333
0
  SIMDJSON_ASSUME(_depth == child_depth - 1);
43334
0
  _depth = child_depth;
43335
0
}
43336
43337
0
simdjson_inline depth_t json_iterator::depth() const noexcept {
43338
0
  return _depth;
43339
0
}
43340
43341
0
simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
43342
0
  return _string_buf_loc;
43343
0
}
43344
43345
0
simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept {
43346
0
  SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD);
43347
0
  logger::log_error(*this, message);
43348
0
  error = _error;
43349
0
  return error;
43350
0
}
43351
43352
0
simdjson_inline token_position json_iterator::position() const noexcept {
43353
0
  return token.position();
43354
0
}
43355
43356
0
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept {
43357
0
  return parser->unescape(in, _string_buf_loc, allow_replacement);
43358
0
}
43359
43360
0
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in) noexcept {
43361
0
  return parser->unescape_wobbly(in, _string_buf_loc);
43362
0
}
43363
43364
0
simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
43365
0
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
43366
0
  SIMDJSON_ASSUME(_depth == child_depth - 1);
43367
0
#if SIMDJSON_DEVELOPMENT_CHECKS
43368
0
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
43369
0
  SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
43370
0
  SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
43371
0
#endif
43372
0
#endif
43373
0
  token.set_position(position);
43374
0
  _depth = child_depth;
43375
0
}
43376
43377
0
simdjson_inline error_code json_iterator::consume_character(char c) noexcept {
43378
0
  if (*peek() == c) {
43379
0
    return_current_and_advance();
43380
0
    return SUCCESS;
43381
0
  }
43382
0
  return TAPE_ERROR;
43383
0
}
43384
43385
#if SIMDJSON_DEVELOPMENT_CHECKS
43386
43387
simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
43388
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
43389
  return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
43390
}
43391
43392
simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
43393
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
43394
  if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
43395
}
43396
43397
#endif
43398
43399
43400
0
simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept {
43401
0
  SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD);
43402
0
  logger::log_error(*this, message);
43403
0
  return _error;
43404
0
}
43405
43406
43407
0
simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept {
43408
0
  // This function is not expected to be called in performance-sensitive settings.
43409
0
  // Let us guard against silly cases:
43410
0
  if((N < max_len) || (N == 0)) { return false; }
43411
0
  // Copy to the buffer.
43412
0
  std::memcpy(tmpbuf, json, max_len);
43413
0
  if(N > max_len) { // We pad whatever remains with ' '.
43414
0
    std::memset(tmpbuf + max_len, ' ', N - max_len);
43415
0
  }
43416
0
  return true;
43417
0
}
43418
43419
} // namespace ondemand
43420
} // namespace fallback
43421
} // namespace simdjson
43422
43423
namespace simdjson {
43424
43425
simdjson_inline simdjson_result<fallback::ondemand::json_iterator>::simdjson_result(fallback::ondemand::json_iterator &&value) noexcept
43426
    : implementation_simdjson_result_base<fallback::ondemand::json_iterator>(std::forward<fallback::ondemand::json_iterator>(value)) {}
43427
simdjson_inline simdjson_result<fallback::ondemand::json_iterator>::simdjson_result(error_code error) noexcept
43428
    : implementation_simdjson_result_base<fallback::ondemand::json_iterator>(error) {}
43429
43430
} // namespace simdjson
43431
43432
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
43433
/* end file simdjson/generic/ondemand/json_iterator-inl.h for fallback */
43434
/* including simdjson/generic/ondemand/json_type-inl.h for fallback: #include "simdjson/generic/ondemand/json_type-inl.h" */
43435
/* begin file simdjson/generic/ondemand/json_type-inl.h for fallback */
43436
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
43437
43438
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
43439
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */
43440
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
43441
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
43442
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
43443
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
43444
43445
namespace simdjson {
43446
namespace fallback {
43447
namespace ondemand {
43448
43449
0
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
43450
0
    switch (type) {
43451
0
        case json_type::array: out << "array"; break;
43452
0
        case json_type::object: out << "object"; break;
43453
0
        case json_type::number: out << "number"; break;
43454
0
        case json_type::string: out << "string"; break;
43455
0
        case json_type::boolean: out << "boolean"; break;
43456
0
        case json_type::null: out << "null"; break;
43457
0
        default: SIMDJSON_UNREACHABLE();
43458
0
    }
43459
0
    return out;
43460
0
}
43461
43462
#if SIMDJSON_EXCEPTIONS
43463
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
43464
    return out << type.value();
43465
}
43466
#endif
43467
43468
43469
43470
0
simdjson_inline number_type number::get_number_type() const noexcept {
43471
0
  return type;
43472
0
}
43473
43474
0
simdjson_inline bool number::is_uint64() const noexcept {
43475
0
  return get_number_type() == number_type::unsigned_integer;
43476
0
}
43477
43478
0
simdjson_inline uint64_t number::get_uint64() const noexcept {
43479
0
  return payload.unsigned_integer;
43480
0
}
43481
43482
0
simdjson_inline number::operator uint64_t() const noexcept {
43483
0
  return get_uint64();
43484
0
}
43485
43486
0
simdjson_inline bool number::is_int64() const noexcept {
43487
0
  return get_number_type() == number_type::signed_integer;
43488
0
}
43489
43490
0
simdjson_inline int64_t number::get_int64() const noexcept {
43491
0
  return payload.signed_integer;
43492
0
}
43493
43494
0
simdjson_inline number::operator int64_t() const noexcept {
43495
0
  return get_int64();
43496
0
}
43497
43498
0
simdjson_inline bool number::is_double() const noexcept {
43499
0
    return get_number_type() == number_type::floating_point_number;
43500
0
}
43501
43502
0
simdjson_inline double number::get_double() const noexcept {
43503
0
  return payload.floating_point_number;
43504
0
}
43505
43506
0
simdjson_inline number::operator double() const noexcept {
43507
0
  return get_double();
43508
0
}
43509
43510
0
simdjson_inline double number::as_double() const noexcept {
43511
0
  if(is_double()) {
43512
0
    return payload.floating_point_number;
43513
0
  }
43514
0
  if(is_int64()) {
43515
0
    return double(payload.signed_integer);
43516
0
  }
43517
0
  return double(payload.unsigned_integer);
43518
0
}
43519
43520
0
simdjson_inline void number::append_s64(int64_t value) noexcept {
43521
0
  payload.signed_integer = value;
43522
0
  type = number_type::signed_integer;
43523
0
}
43524
43525
0
simdjson_inline void number::append_u64(uint64_t value) noexcept {
43526
0
  payload.unsigned_integer = value;
43527
0
  type = number_type::unsigned_integer;
43528
0
}
43529
43530
0
simdjson_inline void number::append_double(double value) noexcept {
43531
0
  payload.floating_point_number = value;
43532
0
  type = number_type::floating_point_number;
43533
0
}
43534
43535
0
simdjson_inline void number::skip_double() noexcept {
43536
0
  type = number_type::floating_point_number;
43537
0
}
43538
43539
} // namespace ondemand
43540
} // namespace fallback
43541
} // namespace simdjson
43542
43543
namespace simdjson {
43544
43545
simdjson_inline simdjson_result<fallback::ondemand::json_type>::simdjson_result(fallback::ondemand::json_type &&value) noexcept
43546
0
    : implementation_simdjson_result_base<fallback::ondemand::json_type>(std::forward<fallback::ondemand::json_type>(value)) {}
43547
simdjson_inline simdjson_result<fallback::ondemand::json_type>::simdjson_result(error_code error) noexcept
43548
0
    : implementation_simdjson_result_base<fallback::ondemand::json_type>(error) {}
43549
43550
} // namespace simdjson
43551
43552
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
43553
/* end file simdjson/generic/ondemand/json_type-inl.h for fallback */
43554
/* including simdjson/generic/ondemand/logger-inl.h for fallback: #include "simdjson/generic/ondemand/logger-inl.h" */
43555
/* begin file simdjson/generic/ondemand/logger-inl.h for fallback */
43556
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
43557
43558
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
43559
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */
43560
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
43561
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
43562
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
43563
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
43564
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
43565
43566
#include <memory>
43567
#include <cstring>
43568
43569
namespace simdjson {
43570
namespace fallback {
43571
namespace ondemand {
43572
namespace logger {
43573
43574
static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
43575
static constexpr const int LOG_EVENT_LEN = 20;
43576
static constexpr const int LOG_BUFFER_LEN = 30;
43577
static constexpr const int LOG_SMALL_BUFFER_LEN = 10;
43578
static int log_depth = 0; // Not threadsafe. Log only.
43579
43580
// Helper to turn unprintable or newline characters into spaces
43581
0
static inline char printable_char(char c) {
43582
0
  if (c >= 0x20) {
43583
0
    return c;
43584
0
  } else {
43585
0
    return ' ';
43586
0
  }
43587
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::printable_char(char)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::printable_char(char)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::printable_char(char)
43588
43589
template<typename... Args>
43590
static inline std::string string_format(const std::string& format, const Args&... args)
43591
0
{
43592
0
  SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
43593
0
  int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
43594
0
  auto size = static_cast<size_t>(size_s);
43595
0
  if (size <= 0) return std::string();
43596
0
  std::unique_ptr<char[]> buf(new char[size]);
43597
0
  std::snprintf(buf.get(), size, format.c_str(), args...);
43598
0
  SIMDJSON_POP_DISABLE_WARNINGS
43599
0
  return std::string(buf.get(), buf.get() + size - 1);
43600
0
}
Unexecuted instantiation: node_metadata.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > simdjson::fallback::ondemand::logger::string_format<>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: node_metadata.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > simdjson::fallback::ondemand::logger::string_format<int, char const*>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int const&, char const* const&)
Unexecuted instantiation: node_modules.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > simdjson::fallback::ondemand::logger::string_format<>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: node_modules.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > simdjson::fallback::ondemand::logger::string_format<int, char const*>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int const&, char const* const&)
Unexecuted instantiation: node_snapshotable.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > simdjson::fallback::ondemand::logger::string_format<>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: node_snapshotable.cc:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > simdjson::fallback::ondemand::logger::string_format<int, char const*>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int const&, char const* const&)
43601
43602
static inline log_level get_log_level_from_env()
43603
0
{
43604
0
  SIMDJSON_PUSH_DISABLE_WARNINGS
43605
0
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
43606
0
      char *lvl = getenv("SIMDJSON_LOG_LEVEL");
43607
0
  SIMDJSON_POP_DISABLE_WARNINGS
43608
0
  if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; }
43609
0
  return log_level::info;
43610
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::get_log_level_from_env()
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::get_log_level_from_env()
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::get_log_level_from_env()
43611
43612
static inline log_level log_threshold()
43613
0
{
43614
0
  static log_level threshold = get_log_level_from_env();
43615
0
  return threshold;
43616
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_threshold()
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_threshold()
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_threshold()
43617
43618
static inline bool should_log(log_level level)
43619
0
{
43620
0
  return level >= log_threshold();
43621
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::should_log(simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::should_log(simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::should_log(simdjson::fallback::ondemand::logger::log_level)
43622
43623
0
inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
43624
0
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
43625
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_event(simdjson::fallback::ondemand::json_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_event(simdjson::fallback::ondemand::json_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_event(simdjson::fallback::ondemand::json_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
43626
43627
0
inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
43628
0
  log_line(iter, index, depth, "", type, detail, log_level::info);
43629
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
43630
0
inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
43631
0
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
43632
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::json_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::json_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::json_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
43633
43634
0
inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
43635
0
  log_line(iter, index, depth, "+", type, detail, log_level::info);
43636
0
  if (LOG_ENABLED) { log_depth++; }
43637
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
43638
0
inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
43639
0
  log_line(iter, "+", type, "", delta, depth_delta, log_level::info);
43640
0
  if (LOG_ENABLED) { log_depth++; }
43641
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::json_iterator const&, char const*, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::json_iterator const&, char const*, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::json_iterator const&, char const*, int, int)
43642
43643
0
inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
43644
0
  if (LOG_ENABLED) { log_depth--; }
43645
0
  log_line(iter, "-", type, "", delta, depth_delta, log_level::info);
43646
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_end_value(simdjson::fallback::ondemand::json_iterator const&, char const*, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_end_value(simdjson::fallback::ondemand::json_iterator const&, char const*, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_end_value(simdjson::fallback::ondemand::json_iterator const&, char const*, int, int)
43647
43648
0
inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
43649
0
  log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error);
43650
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, int, int)
43651
0
inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept {
43652
0
  log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error);
43653
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*)
43654
43655
0
inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
43656
0
  log_event(iter.json_iter(), type, detail, delta, depth_delta);
43657
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_event(simdjson::fallback::ondemand::value_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_event(simdjson::fallback::ondemand::value_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_event(simdjson::fallback::ondemand::value_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
43658
43659
0
inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
43660
0
  log_value(iter.json_iter(), type, detail, delta, depth_delta);
43661
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::value_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::value_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_value(simdjson::fallback::ondemand::value_iterator const&, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int)
43662
43663
0
inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
43664
0
  log_start_value(iter.json_iter(), type, delta, depth_delta);
43665
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::value_iterator const&, char const*, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::value_iterator const&, char const*, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_start_value(simdjson::fallback::ondemand::value_iterator const&, char const*, int, int)
43666
43667
0
inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
43668
0
  log_end_value(iter.json_iter(), type, delta, depth_delta);
43669
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_end_value(simdjson::fallback::ondemand::value_iterator const&, char const*, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_end_value(simdjson::fallback::ondemand::value_iterator const&, char const*, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_end_value(simdjson::fallback::ondemand::value_iterator const&, char const*, int, int)
43670
43671
0
inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
43672
0
  log_error(iter.json_iter(), error, detail, delta, depth_delta);
43673
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::value_iterator const&, char const*, char const*, int, int)
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::value_iterator const&, char const*, char const*, int, int)
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_error(simdjson::fallback::ondemand::value_iterator const&, char const*, char const*, int, int)
43674
43675
0
inline void log_headers() noexcept {
43676
0
  if (LOG_ENABLED) {
43677
0
    if (simdjson_unlikely(should_log(log_level::info))) {
43678
      // Technically a static variable is not thread-safe, but if you are using threads and logging... well...
43679
0
      static bool displayed_hint{false};
43680
0
      log_depth = 0;
43681
0
      printf("\n");
43682
0
      if (!displayed_hint) {
43683
        // We only print this helpful header once.
43684
0
        printf("# Logging provides the depth and position of the iterator user-visible steps:\n");
43685
0
        printf("# +array says 'this is where we were when we discovered the start array'\n");
43686
0
        printf(
43687
0
            "# -array says 'this is where we were when we ended the array'\n");
43688
0
        printf("# skip says 'this is a structural or value I am skipping'\n");
43689
0
        printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
43690
0
        printf("#\n");
43691
0
        printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
43692
0
        printf("# in addition to the depth being displayed.\n");
43693
0
        printf("#\n");
43694
0
        printf("# Every token in the document has a single depth determined by the tokens before it,\n");
43695
0
        printf("# and is not affected by what the token actually is.\n");
43696
0
        printf("#\n");
43697
0
        printf("# Not all structural elements are presented as tokens in the logs.\n");
43698
0
        printf("#\n");
43699
0
        printf("# We never give control to the user within an empty array or an empty object.\n");
43700
0
        printf("#\n");
43701
0
        printf("# Inside an array, having a depth greater than the array's depth means that\n");
43702
0
        printf("# we are pointing inside a value.\n");
43703
0
        printf("# Having a depth equal to the array means that we are pointing right before a value.\n");
43704
0
        printf("# Having a depth smaller than the array means that we have moved beyond the array.\n");
43705
0
        displayed_hint = true;
43706
0
      }
43707
0
      printf("\n");
43708
0
      printf("| %-*s ", LOG_EVENT_LEN, "Event");
43709
0
      printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
43710
0
      printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next");
43711
      // printf("| %-*s ", 5,                    "Next#");
43712
0
      printf("| %-*s ", 5, "Depth");
43713
0
      printf("| Detail ");
43714
0
      printf("|\n");
43715
43716
0
      printf("|%.*s", LOG_EVENT_LEN + 2, DASHES);
43717
0
      printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES);
43718
0
      printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
43719
      // printf("|%.*s", 5+2, DASHES);
43720
0
      printf("|%.*s", 5 + 2, DASHES);
43721
0
      printf("|--------");
43722
0
      printf("|\n");
43723
0
      fflush(stdout);
43724
0
    }
43725
0
  }
43726
0
}
Unexecuted instantiation: node_metadata.cc:simdjson::fallback::ondemand::logger::log_headers()
Unexecuted instantiation: node_modules.cc:simdjson::fallback::ondemand::logger::log_headers()
Unexecuted instantiation: node_snapshotable.cc:simdjson::fallback::ondemand::logger::log_headers()
43727
43728
template <typename... Args>
43729
0
inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept {
43730
0
  log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
43731
0
}
Unexecuted instantiation: node_metadata.cc:void simdjson::fallback::ondemand::logger::log_line<>(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int, simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_metadata.cc:void simdjson::fallback::ondemand::logger::log_line<int, char const*>(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int, simdjson::fallback::ondemand::logger::log_level, int&&, char const*&&)
Unexecuted instantiation: node_modules.cc:void simdjson::fallback::ondemand::logger::log_line<>(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int, simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_modules.cc:void simdjson::fallback::ondemand::logger::log_line<int, char const*>(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int, simdjson::fallback::ondemand::logger::log_level, int&&, char const*&&)
Unexecuted instantiation: node_snapshotable.cc:void simdjson::fallback::ondemand::logger::log_line<>(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int, simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_snapshotable.cc:void simdjson::fallback::ondemand::logger::log_line<int, char const*>(simdjson::fallback::ondemand::json_iterator const&, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, int, simdjson::fallback::ondemand::logger::log_level, int&&, char const*&&)
43732
43733
template <typename... Args>
43734
0
inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
43735
0
  if (LOG_ENABLED) {
43736
0
    if (simdjson_unlikely(should_log(level))) {
43737
0
      const int indent = depth * 2;
43738
0
      const auto buf = iter.token.buf;
43739
0
      auto msg = string_format(title, std::forward<Args>(args)...);
43740
0
      printf("| %*s%s%-*s ", indent, "", title_prefix,
43741
0
             LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str());
43742
0
      {
43743
        // Print the current structural.
43744
0
        printf("| ");
43745
        // Before we begin, the index might point right before the document.
43746
        // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
43747
0
        if (index < iter._root) {
43748
0
          printf("%*s", LOG_BUFFER_LEN, "");
43749
0
        } else {
43750
0
          auto current_structural = &buf[*index];
43751
0
          for (int i = 0; i < LOG_BUFFER_LEN; i++) {
43752
0
            printf("%c", printable_char(current_structural[i]));
43753
0
          }
43754
0
        }
43755
0
        printf(" ");
43756
0
      }
43757
0
      {
43758
        // Print the next structural.
43759
0
        printf("| ");
43760
0
        auto next_structural = &buf[*(index + 1)];
43761
0
        for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
43762
0
          printf("%c", printable_char(next_structural[i]));
43763
0
        }
43764
0
        printf(" ");
43765
0
      }
43766
      // printf("| %5u ", *(index+1));
43767
0
      printf("| %5i ", depth);
43768
0
      printf("| %6.*s ", int(detail.size()), detail.data());
43769
0
      printf("|\n");
43770
0
      fflush(stdout);
43771
0
    }
43772
0
  }
43773
0
}
Unexecuted instantiation: node_metadata.cc:void simdjson::fallback::ondemand::logger::log_line<>(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_metadata.cc:void simdjson::fallback::ondemand::logger::log_line<int, char const*>(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, simdjson::fallback::ondemand::logger::log_level, int&&, char const*&&)
Unexecuted instantiation: node_modules.cc:void simdjson::fallback::ondemand::logger::log_line<>(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_modules.cc:void simdjson::fallback::ondemand::logger::log_line<int, char const*>(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, simdjson::fallback::ondemand::logger::log_level, int&&, char const*&&)
Unexecuted instantiation: node_snapshotable.cc:void simdjson::fallback::ondemand::logger::log_line<>(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, simdjson::fallback::ondemand::logger::log_level)
Unexecuted instantiation: node_snapshotable.cc:void simdjson::fallback::ondemand::logger::log_line<int, char const*>(simdjson::fallback::ondemand::json_iterator const&, unsigned int const*, int, char const*, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >, simdjson::fallback::ondemand::logger::log_level, int&&, char const*&&)
43774
43775
} // namespace logger
43776
} // namespace ondemand
43777
} // namespace fallback
43778
} // namespace simdjson
43779
43780
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
43781
/* end file simdjson/generic/ondemand/logger-inl.h for fallback */
43782
/* including simdjson/generic/ondemand/object-inl.h for fallback: #include "simdjson/generic/ondemand/object-inl.h" */
43783
/* begin file simdjson/generic/ondemand/object-inl.h for fallback */
43784
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
43785
43786
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
43787
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */
43788
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
43789
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
43790
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
43791
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
43792
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
43793
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
43794
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
43795
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
43796
43797
namespace simdjson {
43798
namespace fallback {
43799
namespace ondemand {
43800
43801
0
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
43802
0
  bool has_value;
43803
0
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
43804
0
  if (!has_value) {
43805
0
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
43806
0
    return NO_SUCH_FIELD;
43807
0
  }
43808
0
  return value(iter.child());
43809
0
}
43810
0
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
43811
0
  bool has_value;
43812
0
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
43813
0
  if (!has_value) {
43814
0
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
43815
0
    return NO_SUCH_FIELD;
43816
0
  }
43817
0
  return value(iter.child());
43818
0
}
43819
0
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
43820
0
  return find_field_unordered(key);
43821
0
}
43822
0
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
43823
0
  return std::forward<object>(*this).find_field_unordered(key);
43824
0
}
43825
0
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
43826
0
  bool has_value;
43827
0
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
43828
0
  if (!has_value) {
43829
0
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
43830
0
    return NO_SUCH_FIELD;
43831
0
  }
43832
0
  return value(iter.child());
43833
0
}
43834
0
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
43835
0
  bool has_value;
43836
0
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
43837
0
  if (!has_value) {
43838
0
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
43839
0
    return NO_SUCH_FIELD;
43840
0
  }
43841
0
  return value(iter.child());
43842
0
}
43843
43844
0
simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
43845
0
  SIMDJSON_TRY( iter.start_object().error() );
43846
0
  return object(iter);
43847
0
}
43848
0
simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
43849
0
  SIMDJSON_TRY( iter.start_root_object().error() );
43850
0
  return object(iter);
43851
0
}
43852
0
simdjson_inline error_code object::consume() noexcept {
43853
0
  if(iter.is_at_key()) {
43854
    /**
43855
     * whenever you are pointing at a key, calling skip_child() is
43856
     * unsafe because you will hit a string and you will assume that
43857
     * it is string value, and this mistake will lead you to make bad
43858
     * depth computation.
43859
     */
43860
    /**
43861
     * We want to 'consume' the key. We could really
43862
     * just do _json_iter->return_current_and_advance(); at this
43863
     * point, but, for clarity, we will use the high-level API to
43864
     * eat the key. We assume that the compiler optimizes away
43865
     * most of the work.
43866
     */
43867
0
    simdjson_unused raw_json_string actual_key;
43868
0
    auto error = iter.field_key().get(actual_key);
43869
0
    if (error) { iter.abandon(); return error; };
43870
    // Let us move to the value while we are at it.
43871
0
    if ((error = iter.field_value())) { iter.abandon(); return error; }
43872
0
  }
43873
0
  auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
43874
0
  if(error_skip) { iter.abandon(); }
43875
0
  return error_skip;
43876
0
}
43877
43878
0
simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
43879
0
  const uint8_t * starting_point{iter.peek_start()};
43880
0
  auto error = consume();
43881
0
  if(error) { return error; }
43882
0
  const uint8_t * final_point{iter._json_iter->peek()};
43883
0
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
43884
0
}
43885
43886
0
simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
43887
0
  SIMDJSON_TRY( iter.started_object().error() );
43888
0
  return object(iter);
43889
0
}
43890
43891
0
simdjson_inline object object::resume(const value_iterator &iter) noexcept {
43892
0
  return iter;
43893
0
}
43894
43895
simdjson_inline object::object(const value_iterator &_iter) noexcept
43896
0
  : iter{_iter}
43897
0
{
43898
0
}
43899
43900
0
simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
43901
#if SIMDJSON_DEVELOPMENT_CHECKS
43902
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
43903
#endif
43904
0
  return object_iterator(iter);
43905
0
}
43906
0
simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
43907
0
  return object_iterator(iter);
43908
0
}
43909
43910
0
inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
43911
0
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
43912
0
  json_pointer = json_pointer.substr(1);
43913
0
  size_t slash = json_pointer.find('/');
43914
0
  std::string_view key = json_pointer.substr(0, slash);
43915
0
  // Grab the child with the given key
43916
0
  simdjson_result<value> child;
43917
0
43918
0
  // If there is an escape character in the key, unescape it and then get the child.
43919
0
  size_t escape = key.find('~');
43920
0
  if (escape != std::string_view::npos) {
43921
0
    // Unescape the key
43922
0
    std::string unescaped(key);
43923
0
    do {
43924
0
      switch (unescaped[escape+1]) {
43925
0
        case '0':
43926
0
          unescaped.replace(escape, 2, "~");
43927
0
          break;
43928
0
        case '1':
43929
0
          unescaped.replace(escape, 2, "/");
43930
0
          break;
43931
0
        default:
43932
0
          return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
43933
0
      }
43934
0
      escape = unescaped.find('~', escape+1);
43935
0
    } while (escape != std::string::npos);
43936
0
    child = find_field(unescaped);  // Take note find_field does not unescape keys when matching
43937
0
  } else {
43938
0
    child = find_field(key);
43939
0
  }
43940
0
  if(child.error()) {
43941
0
    return child; // we do not continue if there was an error
43942
0
  }
43943
0
  // If there is a /, we have to recurse and look up more of the path
43944
0
  if (slash != std::string_view::npos) {
43945
0
    child = child.at_pointer(json_pointer.substr(slash));
43946
0
  }
43947
0
  return child;
43948
0
}
43949
43950
0
inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
43951
0
  auto json_pointer = json_path_to_pointer_conversion(json_path);
43952
0
  if (json_pointer == "-1") {
43953
0
    return INVALID_JSON_POINTER;
43954
0
  }
43955
0
  return at_pointer(json_pointer);
43956
0
}
43957
43958
0
simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
43959
0
  size_t count{0};
43960
0
  // Important: we do not consume any of the values.
43961
0
  for(simdjson_unused auto v : *this) { count++; }
43962
0
  // The above loop will always succeed, but we want to report errors.
43963
0
  if(iter.error()) { return iter.error(); }
43964
0
  // We need to move back at the start because we expect users to iterate through
43965
0
  // the object after counting the number of elements.
43966
0
  iter.reset_object();
43967
0
  return count;
43968
0
}
43969
43970
0
simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
43971
0
  bool is_not_empty;
43972
0
  auto error = iter.reset_object().get(is_not_empty);
43973
0
  if(error) { return error; }
43974
0
  return !is_not_empty;
43975
0
}
43976
43977
0
simdjson_inline simdjson_result<bool> object::reset() & noexcept {
43978
0
  return iter.reset_object();
43979
0
}
43980
43981
} // namespace ondemand
43982
} // namespace fallback
43983
} // namespace simdjson
43984
43985
namespace simdjson {
43986
43987
simdjson_inline simdjson_result<fallback::ondemand::object>::simdjson_result(fallback::ondemand::object &&value) noexcept
43988
0
    : implementation_simdjson_result_base<fallback::ondemand::object>(std::forward<fallback::ondemand::object>(value)) {}
43989
simdjson_inline simdjson_result<fallback::ondemand::object>::simdjson_result(error_code error) noexcept
43990
0
    : implementation_simdjson_result_base<fallback::ondemand::object>(error) {}
43991
43992
0
simdjson_inline simdjson_result<fallback::ondemand::object_iterator> simdjson_result<fallback::ondemand::object>::begin() noexcept {
43993
0
  if (error()) { return error(); }
43994
0
  return first.begin();
43995
0
}
43996
0
simdjson_inline simdjson_result<fallback::ondemand::object_iterator> simdjson_result<fallback::ondemand::object>::end() noexcept {
43997
0
  if (error()) { return error(); }
43998
0
  return first.end();
43999
0
}
44000
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
44001
0
  if (error()) { return error(); }
44002
0
  return first.find_field_unordered(key);
44003
0
}
44004
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
44005
0
  if (error()) { return error(); }
44006
0
  return std::forward<fallback::ondemand::object>(first).find_field_unordered(key);
44007
0
}
44008
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::operator[](std::string_view key) & noexcept {
44009
0
  if (error()) { return error(); }
44010
0
  return first[key];
44011
0
}
44012
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::operator[](std::string_view key) && noexcept {
44013
0
  if (error()) { return error(); }
44014
0
  return std::forward<fallback::ondemand::object>(first)[key];
44015
0
}
44016
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::find_field(std::string_view key) & noexcept {
44017
0
  if (error()) { return error(); }
44018
0
  return first.find_field(key);
44019
0
}
44020
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::find_field(std::string_view key) && noexcept {
44021
0
  if (error()) { return error(); }
44022
0
  return std::forward<fallback::ondemand::object>(first).find_field(key);
44023
0
}
44024
44025
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
44026
0
  if (error()) { return error(); }
44027
0
  return first.at_pointer(json_pointer);
44028
0
}
44029
44030
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::object>::at_path(
44031
0
    std::string_view json_path) noexcept {
44032
0
  if (error()) {
44033
0
    return error();
44034
0
  }
44035
0
  return first.at_path(json_path);
44036
0
}
44037
44038
0
inline simdjson_result<bool> simdjson_result<fallback::ondemand::object>::reset() noexcept {
44039
0
  if (error()) { return error(); }
44040
0
  return first.reset();
44041
0
}
44042
44043
0
inline simdjson_result<bool> simdjson_result<fallback::ondemand::object>::is_empty() noexcept {
44044
0
  if (error()) { return error(); }
44045
0
  return first.is_empty();
44046
0
}
44047
44048
0
simdjson_inline  simdjson_result<size_t> simdjson_result<fallback::ondemand::object>::count_fields() & noexcept {
44049
0
  if (error()) { return error(); }
44050
0
  return first.count_fields();
44051
0
}
44052
44053
0
simdjson_inline  simdjson_result<std::string_view> simdjson_result<fallback::ondemand::object>::raw_json() noexcept {
44054
0
  if (error()) { return error(); }
44055
0
  return first.raw_json();
44056
0
}
44057
} // namespace simdjson
44058
44059
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
44060
/* end file simdjson/generic/ondemand/object-inl.h for fallback */
44061
/* including simdjson/generic/ondemand/object_iterator-inl.h for fallback: #include "simdjson/generic/ondemand/object_iterator-inl.h" */
44062
/* begin file simdjson/generic/ondemand/object_iterator-inl.h for fallback */
44063
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
44064
44065
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
44066
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */
44067
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
44068
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
44069
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */
44070
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
44071
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
44072
44073
namespace simdjson {
44074
namespace fallback {
44075
namespace ondemand {
44076
44077
//
44078
// object_iterator
44079
//
44080
44081
simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
44082
0
  : iter{_iter}
44083
0
{}
44084
44085
0
simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
44086
0
  error_code error = iter.error();
44087
0
  if (error) { iter.abandon(); return error; }
44088
0
  auto result = field::start(iter);
44089
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
44090
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
44091
0
  if (result.error()) { iter.abandon(); }
44092
0
  return result;
44093
0
}
44094
0
simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
44095
0
  return !(*this != other);
44096
0
}
44097
0
simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
44098
0
  return iter.is_open();
44099
0
}
44100
44101
SIMDJSON_PUSH_DISABLE_WARNINGS
44102
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
44103
0
simdjson_inline object_iterator &object_iterator::operator++() noexcept {
44104
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
44105
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
44106
0
  if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
44107
44108
0
  simdjson_unused error_code error;
44109
0
  if ((error = iter.skip_child() )) { return *this; }
44110
44111
0
  simdjson_unused bool has_value;
44112
0
  if ((error = iter.has_next_field().get(has_value) )) { return *this; };
44113
0
  return *this;
44114
0
}
44115
SIMDJSON_POP_DISABLE_WARNINGS
44116
44117
//
44118
// ### Live States
44119
//
44120
// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
44121
// always SUCCESS:
44122
//
44123
// - Start: This is the state when the object is first found and the iterator is just past the {.
44124
//   In this state, at_start == true.
44125
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
44126
//   iterate over, the iterator is at the , or } before the next value. In this state,
44127
//   depth == iter.depth, at_start == false, and error == SUCCESS.
44128
// - Unfinished Business: When we hand an array/object to the user which they do not fully
44129
//   iterate over, we need to finish that iteration by skipping child values until we reach the
44130
//   Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
44131
//
44132
// ## Error States
44133
//
44134
// In error states, we will yield exactly one more value before stopping. iter.depth == depth
44135
// and at_start is always false. We decrement after yielding the error, moving to the Finished
44136
// state.
44137
//
44138
// - Chained Error: When the object iterator is part of an error chain--for example, in
44139
//   `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
44140
//   object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
44141
//   iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
44142
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
44143
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
44144
//   error == TAPE_ERROR, iter.depth == depth, and at_start == false.
44145
//
44146
// Errors that occur while reading a field to give to the user (such as when the key is not a
44147
// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
44148
// moving to the Finished state without transitioning through an Error state at all.
44149
//
44150
// ## Terminal State
44151
//
44152
// The terminal state has iter.depth < depth. at_start is always false.
44153
//
44154
// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
44155
//   In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
44156
//
44157
44158
} // namespace ondemand
44159
} // namespace fallback
44160
} // namespace simdjson
44161
44162
namespace simdjson {
44163
44164
simdjson_inline simdjson_result<fallback::ondemand::object_iterator>::simdjson_result(
44165
  fallback::ondemand::object_iterator &&value
44166
) noexcept
44167
0
  : implementation_simdjson_result_base<fallback::ondemand::object_iterator>(std::forward<fallback::ondemand::object_iterator>(value))
44168
0
{
44169
0
  first.iter.assert_is_valid();
44170
0
}
44171
simdjson_inline simdjson_result<fallback::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
44172
  : implementation_simdjson_result_base<fallback::ondemand::object_iterator>({}, error)
44173
{
44174
}
44175
44176
0
simdjson_inline simdjson_result<fallback::ondemand::field> simdjson_result<fallback::ondemand::object_iterator>::operator*() noexcept {
44177
0
  if (error()) { return error(); }
44178
0
  return *first;
44179
0
}
44180
// If we're iterating and there is an error, return the error once.
44181
0
simdjson_inline bool simdjson_result<fallback::ondemand::object_iterator>::operator==(const simdjson_result<fallback::ondemand::object_iterator> &other) const noexcept {
44182
0
  if (!first.iter.is_valid()) { return !error(); }
44183
0
  return first == other.first;
44184
0
}
44185
// If we're iterating and there is an error, return the error once.
44186
0
simdjson_inline bool simdjson_result<fallback::ondemand::object_iterator>::operator!=(const simdjson_result<fallback::ondemand::object_iterator> &other) const noexcept {
44187
0
  if (!first.iter.is_valid()) { return error(); }
44188
0
  return first != other.first;
44189
0
}
44190
// Checks for ']' and ','
44191
0
simdjson_inline simdjson_result<fallback::ondemand::object_iterator> &simdjson_result<fallback::ondemand::object_iterator>::operator++() noexcept {
44192
  // Clear the error if there is one, so we don't yield it twice
44193
0
  if (error()) { second = SUCCESS; return *this; }
44194
0
  ++first;
44195
0
  return *this;
44196
0
}
44197
44198
} // namespace simdjson
44199
44200
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
44201
/* end file simdjson/generic/ondemand/object_iterator-inl.h for fallback */
44202
/* including simdjson/generic/ondemand/parser-inl.h for fallback: #include "simdjson/generic/ondemand/parser-inl.h" */
44203
/* begin file simdjson/generic/ondemand/parser-inl.h for fallback */
44204
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
44205
44206
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
44207
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */
44208
/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */
44209
/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */
44210
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
44211
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
44212
/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */
44213
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
44214
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
44215
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
44216
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
44217
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
44218
44219
namespace simdjson {
44220
namespace fallback {
44221
namespace ondemand {
44222
44223
simdjson_inline parser::parser(size_t max_capacity) noexcept
44224
134k
  : _max_capacity{max_capacity} {
44225
134k
}
44226
44227
0
simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept {
44228
0
  if (new_capacity > max_capacity()) { return CAPACITY; }
44229
0
  if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; }
44230
44231
  // string_capacity copied from document::allocate
44232
0
  _capacity = 0;
44233
0
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64);
44234
0
  string_buf.reset(new (std::nothrow) uint8_t[string_capacity]);
44235
#if SIMDJSON_DEVELOPMENT_CHECKS
44236
  start_positions.reset(new (std::nothrow) token_position[new_max_depth]);
44237
#endif
44238
0
  if (implementation) {
44239
0
    SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
44240
0
    SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
44241
0
  } else {
44242
0
    SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
44243
0
  }
44244
0
  _capacity = new_capacity;
44245
0
  _max_depth = new_max_depth;
44246
0
  return SUCCESS;
44247
0
}
44248
44249
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(padded_string_view json) & noexcept {
44250
0
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
44251
44252
0
  json.remove_utf8_bom();
44253
44254
  // Allocate if needed
44255
0
  if (capacity() < json.length() || !string_buf) {
44256
0
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
44257
0
  }
44258
44259
  // Run stage 1.
44260
0
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
44261
0
  return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this });
44262
0
}
44263
44264
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const char *json, size_t len, size_t allocated) & noexcept {
44265
0
  return iterate(padded_string_view(json, len, allocated));
44266
0
}
44267
44268
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept {
44269
0
  return iterate(padded_string_view(json, len, allocated));
44270
0
}
44271
44272
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string_view json, size_t allocated) & noexcept {
44273
0
  return iterate(padded_string_view(json, allocated));
44274
0
}
44275
44276
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
44277
0
  if(json.capacity() - json.size() < SIMDJSON_PADDING) {
44278
0
    json.reserve(json.size() + SIMDJSON_PADDING);
44279
0
  }
44280
0
  return iterate(padded_string_view(json));
44281
0
}
44282
44283
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
44284
0
  return iterate(padded_string_view(json));
44285
0
}
44286
44287
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string_view> &result) & noexcept {
44288
0
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
44289
0
  SIMDJSON_TRY( result.error() );
44290
0
  padded_string_view json = result.value_unsafe();
44291
0
  return iterate(json);
44292
0
}
44293
44294
0
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
44295
0
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
44296
0
  SIMDJSON_TRY( result.error() );
44297
0
  const padded_string &json = result.value_unsafe();
44298
0
  return iterate(json);
44299
0
}
44300
44301
0
simdjson_warn_unused simdjson_inline simdjson_result<json_iterator> parser::iterate_raw(padded_string_view json) & noexcept {
44302
0
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
44303
0
44304
0
  json.remove_utf8_bom();
44305
0
44306
0
  // Allocate if needed
44307
0
  if (capacity() < json.length()) {
44308
0
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
44309
0
  }
44310
0
44311
0
  // Run stage 1.
44312
0
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
44313
0
  return json_iterator(reinterpret_cast<const uint8_t *>(json.data()), this);
44314
0
}
44315
44316
0
inline simdjson_result<document_stream> parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
44317
0
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
44318
0
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
44319
0
    buf += 3;
44320
0
    len -= 3;
44321
0
  }
44322
0
  if(allow_comma_separated && batch_size < len) { batch_size = len; }
44323
0
  return document_stream(*this, buf, len, batch_size, allow_comma_separated);
44324
0
}
44325
0
inline simdjson_result<document_stream> parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
44326
0
  return iterate_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size, allow_comma_separated);
44327
0
}
44328
0
inline simdjson_result<document_stream> parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept {
44329
0
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
44330
0
}
44331
0
inline simdjson_result<document_stream> parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept {
44332
0
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
44333
0
}
44334
44335
0
simdjson_inline size_t parser::capacity() const noexcept {
44336
0
  return _capacity;
44337
0
}
44338
0
simdjson_inline size_t parser::max_capacity() const noexcept {
44339
0
  return _max_capacity;
44340
0
}
44341
0
simdjson_inline size_t parser::max_depth() const noexcept {
44342
0
  return _max_depth;
44343
0
}
44344
44345
0
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
44346
0
  if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
44347
0
    _max_capacity = max_capacity;
44348
0
  } else {
44349
0
    _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
44350
0
  }
44351
0
}
44352
44353
0
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept {
44354
0
  uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement);
44355
0
  if (!end) { return STRING_ERROR; }
44356
0
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
44357
0
  dst = end;
44358
0
  return result;
44359
0
}
44360
44361
0
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept {
44362
0
  uint8_t *end = implementation->parse_wobbly_string(in.buf, dst);
44363
0
  if (!end) { return STRING_ERROR; }
44364
0
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
44365
0
  dst = end;
44366
0
  return result;
44367
0
}
44368
44369
} // namespace ondemand
44370
} // namespace fallback
44371
} // namespace simdjson
44372
44373
namespace simdjson {
44374
44375
simdjson_inline simdjson_result<fallback::ondemand::parser>::simdjson_result(fallback::ondemand::parser &&value) noexcept
44376
    : implementation_simdjson_result_base<fallback::ondemand::parser>(std::forward<fallback::ondemand::parser>(value)) {}
44377
simdjson_inline simdjson_result<fallback::ondemand::parser>::simdjson_result(error_code error) noexcept
44378
    : implementation_simdjson_result_base<fallback::ondemand::parser>(error) {}
44379
44380
} // namespace simdjson
44381
44382
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
44383
/* end file simdjson/generic/ondemand/parser-inl.h for fallback */
44384
/* including simdjson/generic/ondemand/raw_json_string-inl.h for fallback: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
44385
/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for fallback */
44386
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
44387
44388
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
44389
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */
44390
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
44391
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
44392
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
44393
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
44394
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
44395
44396
namespace simdjson {
44397
44398
namespace fallback {
44399
namespace ondemand {
44400
44401
0
simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
44402
44403
0
simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
44404
44405
44406
0
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
44407
0
  size_t pos{0};
44408
0
  // if the content has no escape character, just scan through it quickly!
44409
0
  for(;pos < target.size() && target[pos] != '\\';pos++) {}
44410
0
  // slow path may begin.
44411
0
  bool escaping{false};
44412
0
  for(;pos < target.size();pos++) {
44413
0
    if((target[pos] == '"') && !escaping) {
44414
0
      return false;
44415
0
    } else if(target[pos] == '\\') {
44416
0
      escaping = !escaping;
44417
0
    } else {
44418
0
      escaping = false;
44419
0
    }
44420
0
  }
44421
0
  return true;
44422
0
}
44423
44424
0
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
44425
0
  size_t pos{0};
44426
0
  // if the content has no escape character, just scan through it quickly!
44427
0
  for(;target[pos] && target[pos] != '\\';pos++) {}
44428
0
  // slow path may begin.
44429
0
  bool escaping{false};
44430
0
  for(;target[pos];pos++) {
44431
0
    if((target[pos] == '"') && !escaping) {
44432
0
      return false;
44433
0
    } else if(target[pos] == '\\') {
44434
0
      escaping = !escaping;
44435
0
    } else {
44436
0
      escaping = false;
44437
0
    }
44438
0
  }
44439
0
  return true;
44440
0
}
44441
44442
44443
0
simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
44444
0
  // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
44445
0
  return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
44446
0
}
44447
44448
0
simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
44449
  // Assumptions: does not contain unescaped quote characters, and
44450
  // the raw content is quote terminated within a valid JSON string.
44451
0
  if(target.size() <= SIMDJSON_PADDING) {
44452
0
    return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
44453
0
  }
44454
0
  const char * r{raw()};
44455
0
  size_t pos{0};
44456
0
  for(;pos < target.size();pos++) {
44457
0
    if(r[pos] != target[pos]) { return false; }
44458
0
  }
44459
0
  if(r[pos] != '"') { return false; }
44460
0
  return true;
44461
0
}
44462
44463
0
simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
44464
0
  const char * r{raw()};
44465
0
  size_t pos{0};
44466
0
  bool escaping{false};
44467
0
  for(;pos < target.size();pos++) {
44468
0
    if(r[pos] != target[pos]) { return false; }
44469
0
    // if target is a compile-time constant and it is free from
44470
0
    // quotes, then the next part could get optimized away through
44471
0
    // inlining.
44472
0
    if((target[pos] == '"') && !escaping) {
44473
0
      // We have reached the end of the raw_json_string but
44474
0
      // the target is not done.
44475
0
      return false;
44476
0
    } else if(target[pos] == '\\') {
44477
0
      escaping = !escaping;
44478
0
    } else {
44479
0
      escaping = false;
44480
0
    }
44481
0
  }
44482
0
  if(r[pos] != '"') { return false; }
44483
0
  return true;
44484
0
}
44485
44486
44487
0
simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
44488
0
  // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
44489
0
  // the raw content is quote terminated within a valid JSON string.
44490
0
  const char * r{raw()};
44491
0
  size_t pos{0};
44492
0
  for(;target[pos];pos++) {
44493
0
    if(r[pos] != target[pos]) { return false; }
44494
0
  }
44495
0
  if(r[pos] != '"') { return false; }
44496
0
  return true;
44497
0
}
44498
44499
0
simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
44500
0
  // Assumptions: does not contain unescaped quote characters, and
44501
0
  // the raw content is quote terminated within a valid JSON string.
44502
0
  const char * r{raw()};
44503
0
  size_t pos{0};
44504
0
  bool escaping{false};
44505
0
  for(;target[pos];pos++) {
44506
0
    if(r[pos] != target[pos]) { return false; }
44507
0
    // if target is a compile-time constant and it is free from
44508
0
    // quotes, then the next part could get optimized away through
44509
0
    // inlining.
44510
0
    if((target[pos] == '"') && !escaping) {
44511
0
      // We have reached the end of the raw_json_string but
44512
0
      // the target is not done.
44513
0
      return false;
44514
0
    } else if(target[pos] == '\\') {
44515
0
      escaping = !escaping;
44516
0
    } else {
44517
0
      escaping = false;
44518
0
    }
44519
0
  }
44520
0
  if(r[pos] != '"') { return false; }
44521
0
  return true;
44522
0
}
44523
44524
0
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
44525
0
  return a.unsafe_is_equal(c);
44526
0
}
44527
44528
0
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
44529
0
  return a == c;
44530
0
}
44531
44532
0
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
44533
0
  return !(a == c);
44534
0
}
44535
44536
0
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
44537
0
  return !(a == c);
44538
0
}
44539
44540
44541
0
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
44542
0
  return iter.unescape(*this, allow_replacement);
44543
0
}
44544
44545
0
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
44546
0
  return iter.unescape_wobbly(*this);
44547
0
}
44548
44549
0
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
44550
0
  bool in_escape = false;
44551
0
  const char *s = str.raw();
44552
0
  while (true) {
44553
0
    switch (*s) {
44554
0
      case '\\': in_escape = !in_escape; break;
44555
0
      case '"': if (in_escape) { in_escape = false; } else { return out; } break;
44556
0
      default: if (in_escape) { in_escape = false; }
44557
0
    }
44558
0
    out << *s;
44559
0
    s++;
44560
0
  }
44561
0
}
44562
44563
} // namespace ondemand
44564
} // namespace fallback
44565
} // namespace simdjson
44566
44567
namespace simdjson {
44568
44569
simdjson_inline simdjson_result<fallback::ondemand::raw_json_string>::simdjson_result(fallback::ondemand::raw_json_string &&value) noexcept
44570
0
    : implementation_simdjson_result_base<fallback::ondemand::raw_json_string>(std::forward<fallback::ondemand::raw_json_string>(value)) {}
44571
simdjson_inline simdjson_result<fallback::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
44572
0
    : implementation_simdjson_result_base<fallback::ondemand::raw_json_string>(error) {}
44573
44574
0
simdjson_inline simdjson_result<const char *> simdjson_result<fallback::ondemand::raw_json_string>::raw() const noexcept {
44575
0
  if (error()) { return error(); }
44576
0
  return first.raw();
44577
0
}
44578
0
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<fallback::ondemand::raw_json_string>::unescape(fallback::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
44579
0
  if (error()) { return error(); }
44580
0
  return first.unescape(iter, allow_replacement);
44581
0
}
44582
0
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<fallback::ondemand::raw_json_string>::unescape_wobbly(fallback::ondemand::json_iterator &iter) const noexcept {
44583
0
  if (error()) { return error(); }
44584
0
  return first.unescape_wobbly(iter);
44585
0
}
44586
} // namespace simdjson
44587
44588
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
44589
/* end file simdjson/generic/ondemand/raw_json_string-inl.h for fallback */
44590
/* including simdjson/generic/ondemand/serialization-inl.h for fallback: #include "simdjson/generic/ondemand/serialization-inl.h" */
44591
/* begin file simdjson/generic/ondemand/serialization-inl.h for fallback */
44592
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
44593
44594
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
44595
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */
44596
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
44597
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
44598
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
44599
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
44600
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
44601
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */
44602
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
44603
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
44604
44605
namespace simdjson {
44606
44607
0
inline std::string_view trim(const std::string_view str) noexcept {
44608
0
  // We can almost surely do better by rolling our own find_first_not_of function.
44609
0
  size_t first = str.find_first_not_of(" \t\n\r");
44610
0
  // If we have the empty string (just white space), then no trimming is possible, and
44611
0
  // we return the empty string_view.
44612
0
  if (std::string_view::npos == first) { return std::string_view(); }
44613
0
  size_t last = str.find_last_not_of(" \t\n\r");
44614
0
  return str.substr(first, (last - first + 1));
44615
0
}
44616
44617
44618
0
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::document& x) noexcept {
44619
0
  std::string_view v;
44620
0
  auto error = x.raw_json().get(v);
44621
0
  if(error) {return error; }
44622
0
  return trim(v);
44623
0
}
44624
44625
0
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::document_reference& x) noexcept {
44626
0
  std::string_view v;
44627
0
  auto error = x.raw_json().get(v);
44628
0
  if(error) {return error; }
44629
0
  return trim(v);
44630
0
}
44631
44632
0
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::value& x) noexcept {
44633
0
  /**
44634
0
   * If we somehow receive a value that has already been consumed,
44635
0
   * then the following code could be in trouble. E.g., we create
44636
0
   * an array as needed, but if an array was already created, then
44637
0
   * it could be bad.
44638
0
   */
44639
0
  using namespace fallback::ondemand;
44640
0
  fallback::ondemand::json_type t;
44641
0
  auto error = x.type().get(t);
44642
0
  if(error != SUCCESS) { return error; }
44643
0
  switch (t)
44644
0
  {
44645
0
    case json_type::array:
44646
0
    {
44647
0
      fallback::ondemand::array array;
44648
0
      error = x.get_array().get(array);
44649
0
      if(error) { return error; }
44650
0
      return to_json_string(array);
44651
0
    }
44652
0
    case json_type::object:
44653
0
    {
44654
0
      fallback::ondemand::object object;
44655
0
      error = x.get_object().get(object);
44656
0
      if(error) { return error; }
44657
0
      return to_json_string(object);
44658
0
    }
44659
0
    default:
44660
0
      return trim(x.raw_json_token());
44661
0
  }
44662
0
}
44663
44664
0
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::object& x) noexcept {
44665
0
  std::string_view v;
44666
0
  auto error = x.raw_json().get(v);
44667
0
  if(error) {return error; }
44668
0
  return trim(v);
44669
0
}
44670
44671
0
inline simdjson_result<std::string_view> to_json_string(fallback::ondemand::array& x) noexcept {
44672
0
  std::string_view v;
44673
0
  auto error = x.raw_json().get(v);
44674
0
  if(error) {return error; }
44675
0
  return trim(v);
44676
0
}
44677
44678
0
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::document> x) {
44679
0
  if (x.error()) { return x.error(); }
44680
0
  return to_json_string(x.value_unsafe());
44681
0
}
44682
44683
0
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::document_reference> x) {
44684
0
  if (x.error()) { return x.error(); }
44685
0
  return to_json_string(x.value_unsafe());
44686
0
}
44687
44688
0
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::value> x) {
44689
0
  if (x.error()) { return x.error(); }
44690
0
  return to_json_string(x.value_unsafe());
44691
0
}
44692
44693
0
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::object> x) {
44694
0
  if (x.error()) { return x.error(); }
44695
0
  return to_json_string(x.value_unsafe());
44696
0
}
44697
44698
0
inline simdjson_result<std::string_view> to_json_string(simdjson_result<fallback::ondemand::array> x) {
44699
0
  if (x.error()) { return x.error(); }
44700
0
  return to_json_string(x.value_unsafe());
44701
0
}
44702
} // namespace simdjson
44703
44704
namespace simdjson { namespace fallback { namespace ondemand {
44705
44706
#if SIMDJSON_EXCEPTIONS
44707
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::value x) {
44708
  std::string_view v;
44709
  auto error = simdjson::to_json_string(x).get(v);
44710
  if(error == simdjson::SUCCESS) {
44711
    return (out << v);
44712
  } else {
44713
    throw simdjson::simdjson_error(error);
44714
  }
44715
}
44716
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::value> x) {
44717
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
44718
  return (out << x.value());
44719
}
44720
#else
44721
0
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::value x) {
44722
0
  std::string_view v;
44723
0
  auto error = simdjson::to_json_string(x).get(v);
44724
0
  if(error == simdjson::SUCCESS) {
44725
0
    return (out << v);
44726
0
  } else {
44727
0
    return (out << error);
44728
0
  }
44729
0
}
44730
#endif
44731
44732
#if SIMDJSON_EXCEPTIONS
44733
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::array value) {
44734
  std::string_view v;
44735
  auto error = simdjson::to_json_string(value).get(v);
44736
  if(error == simdjson::SUCCESS) {
44737
    return (out << v);
44738
  } else {
44739
    throw simdjson::simdjson_error(error);
44740
  }
44741
}
44742
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::array> x) {
44743
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
44744
  return (out << x.value());
44745
}
44746
#else
44747
0
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::array value) {
44748
0
  std::string_view v;
44749
0
  auto error = simdjson::to_json_string(value).get(v);
44750
0
  if(error == simdjson::SUCCESS) {
44751
0
    return (out << v);
44752
0
  } else {
44753
0
    return (out << error);
44754
0
  }
44755
0
}
44756
#endif
44757
44758
#if SIMDJSON_EXCEPTIONS
44759
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::document& value)  {
44760
  std::string_view v;
44761
  auto error = simdjson::to_json_string(value).get(v);
44762
  if(error == simdjson::SUCCESS) {
44763
    return (out << v);
44764
  } else {
44765
    throw simdjson::simdjson_error(error);
44766
  }
44767
}
44768
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::document_reference& value)  {
44769
  std::string_view v;
44770
  auto error = simdjson::to_json_string(value).get(v);
44771
  if(error == simdjson::SUCCESS) {
44772
    return (out << v);
44773
  } else {
44774
    throw simdjson::simdjson_error(error);
44775
  }
44776
}
44777
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::document>&& x) {
44778
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
44779
  return (out << x.value());
44780
}
44781
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::fallback::ondemand::document_reference>&& x) {
44782
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
44783
  return (out << x.value());
44784
}
44785
#else
44786
0
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::document& value)  {
44787
0
  std::string_view v;
44788
0
  auto error = simdjson::to_json_string(value).get(v);
44789
0
  if(error == simdjson::SUCCESS) {
44790
0
    return (out << v);
44791
0
  } else {
44792
0
    return (out << error);
44793
0
  }
44794
0
}
44795
#endif
44796
44797
#if SIMDJSON_EXCEPTIONS
44798
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::object value) {
44799
  std::string_view v;
44800
  auto error = simdjson::to_json_string(value).get(v);
44801
  if(error == simdjson::SUCCESS) {
44802
    return (out << v);
44803
  } else {
44804
    throw simdjson::simdjson_error(error);
44805
  }
44806
}
44807
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::fallback::ondemand::object> x) {
44808
  if (x.error()) { throw  simdjson::simdjson_error(x.error()); }
44809
  return (out << x.value());
44810
}
44811
#else
44812
0
inline std::ostream& operator<<(std::ostream& out, simdjson::fallback::ondemand::object value) {
44813
0
  std::string_view v;
44814
0
  auto error = simdjson::to_json_string(value).get(v);
44815
0
  if(error == simdjson::SUCCESS) {
44816
0
    return (out << v);
44817
0
  } else {
44818
0
    return (out << error);
44819
0
  }
44820
0
}
44821
#endif
44822
}}} // namespace simdjson::fallback::ondemand
44823
44824
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
44825
/* end file simdjson/generic/ondemand/serialization-inl.h for fallback */
44826
/* including simdjson/generic/ondemand/token_iterator-inl.h for fallback: #include "simdjson/generic/ondemand/token_iterator-inl.h" */
44827
/* begin file simdjson/generic/ondemand/token_iterator-inl.h for fallback */
44828
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
44829
44830
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
44831
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */
44832
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
44833
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
44834
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
44835
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
44836
44837
namespace simdjson {
44838
namespace fallback {
44839
namespace ondemand {
44840
44841
simdjson_inline token_iterator::token_iterator(
44842
  const uint8_t *_buf,
44843
  token_position position
44844
0
) noexcept : buf{_buf}, _position{position}
44845
0
{
44846
0
}
44847
44848
0
simdjson_inline uint32_t token_iterator::current_offset() const noexcept {
44849
0
  return *(_position);
44850
0
}
44851
44852
44853
0
simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept {
44854
0
  return &buf[*(_position++)];
44855
0
}
44856
44857
0
simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept {
44858
0
  return &buf[*position];
44859
0
}
44860
0
simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept {
44861
0
  return *position;
44862
0
}
44863
0
simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept {
44864
0
  return *(position+1) - *position;
44865
0
}
44866
44867
0
simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept {
44868
0
  return *(position+2) - *(position) > *(position+1) - *(position) ?
44869
0
      *(position+1) - *(position)
44870
0
      : *(position+2) - *(position);
44871
0
}
44872
0
simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept {
44873
0
  return &buf[*(_position+delta)];
44874
0
}
44875
0
simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept {
44876
0
  return *(_position+delta);
44877
0
}
44878
0
simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept {
44879
0
  return *(_position+delta+1) - *(_position+delta);
44880
0
}
44881
44882
0
simdjson_inline token_position token_iterator::position() const noexcept {
44883
0
  return _position;
44884
0
}
44885
0
simdjson_inline void token_iterator::set_position(token_position target_position) noexcept {
44886
0
  _position = target_position;
44887
0
}
44888
44889
0
simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept {
44890
0
  return _position == other._position;
44891
0
}
44892
0
simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept {
44893
0
  return _position != other._position;
44894
0
}
44895
0
simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept {
44896
0
  return _position > other._position;
44897
0
}
44898
0
simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept {
44899
0
  return _position >= other._position;
44900
0
}
44901
0
simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept {
44902
0
  return _position < other._position;
44903
0
}
44904
0
simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept {
44905
0
  return _position <= other._position;
44906
0
}
44907
44908
} // namespace ondemand
44909
} // namespace fallback
44910
} // namespace simdjson
44911
44912
namespace simdjson {
44913
44914
simdjson_inline simdjson_result<fallback::ondemand::token_iterator>::simdjson_result(fallback::ondemand::token_iterator &&value) noexcept
44915
    : implementation_simdjson_result_base<fallback::ondemand::token_iterator>(std::forward<fallback::ondemand::token_iterator>(value)) {}
44916
simdjson_inline simdjson_result<fallback::ondemand::token_iterator>::simdjson_result(error_code error) noexcept
44917
    : implementation_simdjson_result_base<fallback::ondemand::token_iterator>(error) {}
44918
44919
} // namespace simdjson
44920
44921
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
44922
/* end file simdjson/generic/ondemand/token_iterator-inl.h for fallback */
44923
/* including simdjson/generic/ondemand/value-inl.h for fallback: #include "simdjson/generic/ondemand/value-inl.h" */
44924
/* begin file simdjson/generic/ondemand/value-inl.h for fallback */
44925
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
44926
44927
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
44928
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */
44929
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
44930
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
44931
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
44932
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
44933
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
44934
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
44935
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
44936
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
44937
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
44938
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
44939
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
44940
44941
namespace simdjson {
44942
namespace fallback {
44943
namespace ondemand {
44944
44945
simdjson_inline value::value(const value_iterator &_iter) noexcept
44946
0
  : iter{_iter}
44947
0
{
44948
0
}
44949
0
simdjson_inline value value::start(const value_iterator &iter) noexcept {
44950
0
  return iter;
44951
0
}
44952
0
simdjson_inline value value::resume(const value_iterator &iter) noexcept {
44953
0
  return iter;
44954
0
}
44955
44956
0
simdjson_inline simdjson_result<array> value::get_array() noexcept {
44957
0
  return array::start(iter);
44958
0
}
44959
0
simdjson_inline simdjson_result<object> value::get_object() noexcept {
44960
0
  return object::start(iter);
44961
0
}
44962
0
simdjson_inline simdjson_result<object> value::start_or_resume_object() noexcept {
44963
0
  if (iter.at_start()) {
44964
0
    return get_object();
44965
0
  } else {
44966
0
    return object::resume(iter);
44967
0
  }
44968
0
}
44969
44970
0
simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
44971
0
  return iter.get_raw_json_string();
44972
0
}
44973
0
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
44974
0
  return iter.get_string(allow_replacement);
44975
0
}
44976
template <typename string_type>
44977
0
simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
44978
0
  return iter.get_string(receiver, allow_replacement);
44979
0
}
44980
0
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
44981
0
  return iter.get_wobbly_string();
44982
0
}
44983
0
simdjson_inline simdjson_result<double> value::get_double() noexcept {
44984
0
  return iter.get_double();
44985
0
}
44986
0
simdjson_inline simdjson_result<double> value::get_double_in_string() noexcept {
44987
0
  return iter.get_double_in_string();
44988
0
}
44989
0
simdjson_inline simdjson_result<uint64_t> value::get_uint64() noexcept {
44990
0
  return iter.get_uint64();
44991
0
}
44992
0
simdjson_inline simdjson_result<uint64_t> value::get_uint64_in_string() noexcept {
44993
0
  return iter.get_uint64_in_string();
44994
0
}
44995
0
simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
44996
0
  return iter.get_int64();
44997
0
}
44998
0
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
44999
0
  return iter.get_int64_in_string();
45000
0
}
45001
0
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
45002
0
  return iter.get_bool();
45003
0
}
45004
0
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
45005
0
  return iter.is_null();
45006
0
}
45007
0
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
45008
0
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
45009
0
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
45010
0
template<> simdjson_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(false); }
45011
0
template<> simdjson_inline simdjson_result<number> value::get() noexcept { return get_number(); }
45012
0
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
45013
0
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
45014
0
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
45015
0
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
45016
45017
template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
45018
  return get<T>().get(out);
45019
}
45020
45021
#if SIMDJSON_EXCEPTIONS
45022
template <class T>
45023
simdjson_inline value::operator T() noexcept(false) {
45024
  return get<T>();
45025
}
45026
simdjson_inline value::operator array() noexcept(false) {
45027
  return get_array();
45028
}
45029
simdjson_inline value::operator object() noexcept(false) {
45030
  return get_object();
45031
}
45032
simdjson_inline value::operator uint64_t() noexcept(false) {
45033
  return get_uint64();
45034
}
45035
simdjson_inline value::operator int64_t() noexcept(false) {
45036
  return get_int64();
45037
}
45038
simdjson_inline value::operator double() noexcept(false) {
45039
  return get_double();
45040
}
45041
simdjson_inline value::operator std::string_view() noexcept(false) {
45042
  return get_string(false);
45043
}
45044
simdjson_inline value::operator raw_json_string() noexcept(false) {
45045
  return get_raw_json_string();
45046
}
45047
simdjson_inline value::operator bool() noexcept(false) {
45048
  return get_bool();
45049
}
45050
#endif
45051
45052
0
simdjson_inline simdjson_result<array_iterator> value::begin() & noexcept {
45053
0
  return get_array().begin();
45054
0
}
45055
0
simdjson_inline simdjson_result<array_iterator> value::end() & noexcept {
45056
0
  return {};
45057
0
}
45058
0
simdjson_inline simdjson_result<size_t> value::count_elements() & noexcept {
45059
0
  simdjson_result<size_t> answer;
45060
0
  auto a = get_array();
45061
0
  answer = a.count_elements();
45062
0
  // count_elements leaves you pointing inside the array, at the first element.
45063
0
  // We need to move back so that the user can create a new array (which requires that
45064
0
  // we point at '[').
45065
0
  iter.move_at_start();
45066
0
  return answer;
45067
0
}
45068
0
simdjson_inline simdjson_result<size_t> value::count_fields() & noexcept {
45069
0
  simdjson_result<size_t> answer;
45070
0
  auto a = get_object();
45071
0
  answer = a.count_fields();
45072
0
  iter.move_at_start();
45073
0
  return answer;
45074
0
}
45075
0
simdjson_inline simdjson_result<value> value::at(size_t index) noexcept {
45076
0
  auto a = get_array();
45077
0
  return a.at(index);
45078
0
}
45079
45080
0
simdjson_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
45081
0
  return start_or_resume_object().find_field(key);
45082
0
}
45083
0
simdjson_inline simdjson_result<value> value::find_field(const char *key) noexcept {
45084
0
  return start_or_resume_object().find_field(key);
45085
0
}
45086
45087
0
simdjson_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
45088
0
  return start_or_resume_object().find_field_unordered(key);
45089
0
}
45090
0
simdjson_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
45091
0
  return start_or_resume_object().find_field_unordered(key);
45092
0
}
45093
45094
0
simdjson_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
45095
0
  return start_or_resume_object()[key];
45096
0
}
45097
0
simdjson_inline simdjson_result<value> value::operator[](const char *key) noexcept {
45098
0
  return start_or_resume_object()[key];
45099
0
}
45100
45101
0
simdjson_inline simdjson_result<json_type> value::type() noexcept {
45102
0
  return iter.type();
45103
0
}
45104
45105
0
simdjson_inline simdjson_result<bool> value::is_scalar() noexcept {
45106
0
  json_type this_type;
45107
0
  auto error = type().get(this_type);
45108
0
  if(error) { return error; }
45109
0
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
45110
0
}
45111
45112
0
simdjson_inline simdjson_result<bool> value::is_string() noexcept {
45113
0
  json_type this_type;
45114
0
  auto error = type().get(this_type);
45115
0
  if(error) { return error; }
45116
0
  return (this_type == json_type::string);
45117
0
}
45118
45119
45120
0
simdjson_inline bool value::is_negative() noexcept {
45121
0
  return iter.is_negative();
45122
0
}
45123
45124
0
simdjson_inline simdjson_result<bool> value::is_integer() noexcept {
45125
0
  return iter.is_integer();
45126
0
}
45127
0
simdjson_warn_unused simdjson_inline simdjson_result<number_type> value::get_number_type() noexcept {
45128
0
  return iter.get_number_type();
45129
0
}
45130
0
simdjson_warn_unused simdjson_inline simdjson_result<number> value::get_number() noexcept {
45131
0
  return iter.get_number();
45132
0
}
45133
45134
0
simdjson_inline std::string_view value::raw_json_token() noexcept {
45135
0
  return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
45136
0
}
45137
45138
0
simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
45139
0
  json_type t;
45140
0
  SIMDJSON_TRY(type().get(t));
45141
0
  switch (t)
45142
0
  {
45143
0
    case json_type::array: {
45144
0
      ondemand::array array;
45145
0
      SIMDJSON_TRY(get_array().get(array));
45146
0
      return array.raw_json();
45147
0
    }
45148
0
    case json_type::object: {
45149
0
      ondemand::object object;
45150
0
      SIMDJSON_TRY(get_object().get(object));
45151
0
      return object.raw_json();
45152
0
    }
45153
0
    default:
45154
0
      return raw_json_token();
45155
0
  }
45156
0
}
45157
45158
0
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
45159
0
  return iter.json_iter().current_location();
45160
0
}
45161
45162
0
simdjson_inline int32_t value::current_depth() const noexcept{
45163
0
  return iter.json_iter().depth();
45164
0
}
45165
45166
0
simdjson_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
45167
0
  json_type t;
45168
0
  SIMDJSON_TRY(type().get(t));
45169
0
  switch (t)
45170
0
  {
45171
0
    case json_type::array:
45172
0
      return (*this).get_array().at_pointer(json_pointer);
45173
0
    case json_type::object:
45174
0
      return (*this).get_object().at_pointer(json_pointer);
45175
0
    default:
45176
0
      return INVALID_JSON_POINTER;
45177
0
  }
45178
0
}
45179
45180
0
simdjson_inline simdjson_result<value> value::at_path(std::string_view json_path) noexcept {
45181
0
  json_type t;
45182
0
  SIMDJSON_TRY(type().get(t));
45183
0
  switch (t) {
45184
0
  case json_type::array:
45185
0
      return (*this).get_array().at_path(json_path);
45186
0
  case json_type::object:
45187
0
      return (*this).get_object().at_path(json_path);
45188
0
  default:
45189
0
      return INVALID_JSON_POINTER;
45190
0
  }
45191
0
}
45192
45193
} // namespace ondemand
45194
} // namespace fallback
45195
} // namespace simdjson
45196
45197
namespace simdjson {
45198
45199
simdjson_inline simdjson_result<fallback::ondemand::value>::simdjson_result(
45200
  fallback::ondemand::value &&value
45201
) noexcept :
45202
0
    implementation_simdjson_result_base<fallback::ondemand::value>(
45203
0
      std::forward<fallback::ondemand::value>(value)
45204
0
    )
45205
0
{
45206
0
}
45207
simdjson_inline simdjson_result<fallback::ondemand::value>::simdjson_result(
45208
  error_code error
45209
) noexcept :
45210
0
    implementation_simdjson_result_base<fallback::ondemand::value>(error)
45211
0
{
45212
0
}
45213
0
simdjson_inline simdjson_result<size_t> simdjson_result<fallback::ondemand::value>::count_elements() & noexcept {
45214
0
  if (error()) { return error(); }
45215
0
  return first.count_elements();
45216
0
}
45217
0
simdjson_inline simdjson_result<size_t> simdjson_result<fallback::ondemand::value>::count_fields() & noexcept {
45218
0
  if (error()) { return error(); }
45219
0
  return first.count_fields();
45220
0
}
45221
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::at(size_t index) noexcept {
45222
0
  if (error()) { return error(); }
45223
0
  return first.at(index);
45224
0
}
45225
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::value>::begin() & noexcept {
45226
0
  if (error()) { return error(); }
45227
0
  return first.begin();
45228
0
}
45229
0
simdjson_inline simdjson_result<fallback::ondemand::array_iterator> simdjson_result<fallback::ondemand::value>::end() & noexcept {
45230
0
  if (error()) { return error(); }
45231
0
  return {};
45232
0
}
45233
45234
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::find_field(std::string_view key) noexcept {
45235
0
  if (error()) { return error(); }
45236
0
  return first.find_field(key);
45237
0
}
45238
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::find_field(const char *key) noexcept {
45239
0
  if (error()) { return error(); }
45240
0
  return first.find_field(key);
45241
0
}
45242
45243
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
45244
0
  if (error()) { return error(); }
45245
0
  return first.find_field_unordered(key);
45246
0
}
45247
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::find_field_unordered(const char *key) noexcept {
45248
0
  if (error()) { return error(); }
45249
0
  return first.find_field_unordered(key);
45250
0
}
45251
45252
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::operator[](std::string_view key) noexcept {
45253
0
  if (error()) { return error(); }
45254
0
  return first[key];
45255
0
}
45256
0
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::operator[](const char *key) noexcept {
45257
0
  if (error()) { return error(); }
45258
0
  return first[key];
45259
0
}
45260
45261
0
simdjson_inline simdjson_result<fallback::ondemand::array> simdjson_result<fallback::ondemand::value>::get_array() noexcept {
45262
0
  if (error()) { return error(); }
45263
0
  return first.get_array();
45264
0
}
45265
0
simdjson_inline simdjson_result<fallback::ondemand::object> simdjson_result<fallback::ondemand::value>::get_object() noexcept {
45266
0
  if (error()) { return error(); }
45267
0
  return first.get_object();
45268
0
}
45269
0
simdjson_inline simdjson_result<uint64_t> simdjson_result<fallback::ondemand::value>::get_uint64() noexcept {
45270
0
  if (error()) { return error(); }
45271
0
  return first.get_uint64();
45272
0
}
45273
0
simdjson_inline simdjson_result<uint64_t> simdjson_result<fallback::ondemand::value>::get_uint64_in_string() noexcept {
45274
0
  if (error()) { return error(); }
45275
0
  return first.get_uint64_in_string();
45276
0
}
45277
0
simdjson_inline simdjson_result<int64_t> simdjson_result<fallback::ondemand::value>::get_int64() noexcept {
45278
0
  if (error()) { return error(); }
45279
0
  return first.get_int64();
45280
0
}
45281
0
simdjson_inline simdjson_result<int64_t> simdjson_result<fallback::ondemand::value>::get_int64_in_string() noexcept {
45282
0
  if (error()) { return error(); }
45283
0
  return first.get_int64_in_string();
45284
0
}
45285
0
simdjson_inline simdjson_result<double> simdjson_result<fallback::ondemand::value>::get_double() noexcept {
45286
0
  if (error()) { return error(); }
45287
0
  return first.get_double();
45288
0
}
45289
0
simdjson_inline simdjson_result<double> simdjson_result<fallback::ondemand::value>::get_double_in_string() noexcept {
45290
0
  if (error()) { return error(); }
45291
0
  return first.get_double_in_string();
45292
0
}
45293
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::value>::get_string(bool allow_replacement) noexcept {
45294
0
  if (error()) { return error(); }
45295
0
  return first.get_string(allow_replacement);
45296
0
}
45297
template <typename string_type>
45298
simdjson_inline error_code simdjson_result<fallback::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
45299
  if (error()) { return error(); }
45300
  return first.get_string(receiver, allow_replacement);
45301
}
45302
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::value>::get_wobbly_string() noexcept {
45303
0
  if (error()) { return error(); }
45304
0
  return first.get_wobbly_string();
45305
0
}
45306
0
simdjson_inline simdjson_result<fallback::ondemand::raw_json_string> simdjson_result<fallback::ondemand::value>::get_raw_json_string() noexcept {
45307
0
  if (error()) { return error(); }
45308
0
  return first.get_raw_json_string();
45309
0
}
45310
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::value>::get_bool() noexcept {
45311
0
  if (error()) { return error(); }
45312
0
  return first.get_bool();
45313
0
}
45314
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::value>::is_null() noexcept {
45315
0
  if (error()) { return error(); }
45316
0
  return first.is_null();
45317
0
}
45318
45319
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<fallback::ondemand::value>::get() noexcept {
45320
  if (error()) { return error(); }
45321
  return first.get<T>();
45322
}
45323
template<typename T> simdjson_inline error_code simdjson_result<fallback::ondemand::value>::get(T &out) noexcept {
45324
  if (error()) { return error(); }
45325
  return first.get<T>(out);
45326
}
45327
45328
0
template<> simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::get<fallback::ondemand::value>() noexcept  {
45329
0
  if (error()) { return error(); }
45330
0
  return std::move(first);
45331
0
}
45332
0
template<> simdjson_inline error_code simdjson_result<fallback::ondemand::value>::get<fallback::ondemand::value>(fallback::ondemand::value &out) noexcept {
45333
0
  if (error()) { return error(); }
45334
0
  out = first;
45335
0
  return SUCCESS;
45336
0
}
45337
45338
0
simdjson_inline simdjson_result<fallback::ondemand::json_type> simdjson_result<fallback::ondemand::value>::type() noexcept {
45339
0
  if (error()) { return error(); }
45340
0
  return first.type();
45341
0
}
45342
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::value>::is_scalar() noexcept {
45343
0
  if (error()) { return error(); }
45344
0
  return first.is_scalar();
45345
0
}
45346
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::value>::is_string() noexcept {
45347
0
  if (error()) { return error(); }
45348
0
  return first.is_string();
45349
0
}
45350
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::value>::is_negative() noexcept {
45351
0
  if (error()) { return error(); }
45352
0
  return first.is_negative();
45353
0
}
45354
0
simdjson_inline simdjson_result<bool> simdjson_result<fallback::ondemand::value>::is_integer() noexcept {
45355
0
  if (error()) { return error(); }
45356
0
  return first.is_integer();
45357
0
}
45358
0
simdjson_inline simdjson_result<fallback::number_type> simdjson_result<fallback::ondemand::value>::get_number_type() noexcept {
45359
0
  if (error()) { return error(); }
45360
0
  return first.get_number_type();
45361
0
}
45362
0
simdjson_inline simdjson_result<fallback::ondemand::number> simdjson_result<fallback::ondemand::value>::get_number() noexcept {
45363
0
  if (error()) { return error(); }
45364
0
  return first.get_number();
45365
0
}
45366
#if SIMDJSON_EXCEPTIONS
45367
template <class T>
45368
simdjson_inline simdjson_result<fallback::ondemand::value>::operator T() noexcept(false) {
45369
  if (error()) { throw simdjson_error(error()); }
45370
  return static_cast<T>(first);
45371
}
45372
simdjson_inline simdjson_result<fallback::ondemand::value>::operator fallback::ondemand::array() noexcept(false) {
45373
  if (error()) { throw simdjson_error(error()); }
45374
  return first;
45375
}
45376
simdjson_inline simdjson_result<fallback::ondemand::value>::operator fallback::ondemand::object() noexcept(false) {
45377
  if (error()) { throw simdjson_error(error()); }
45378
  return first;
45379
}
45380
simdjson_inline simdjson_result<fallback::ondemand::value>::operator uint64_t() noexcept(false) {
45381
  if (error()) { throw simdjson_error(error()); }
45382
  return first;
45383
}
45384
simdjson_inline simdjson_result<fallback::ondemand::value>::operator int64_t() noexcept(false) {
45385
  if (error()) { throw simdjson_error(error()); }
45386
  return first;
45387
}
45388
simdjson_inline simdjson_result<fallback::ondemand::value>::operator double() noexcept(false) {
45389
  if (error()) { throw simdjson_error(error()); }
45390
  return first;
45391
}
45392
simdjson_inline simdjson_result<fallback::ondemand::value>::operator std::string_view() noexcept(false) {
45393
  if (error()) { throw simdjson_error(error()); }
45394
  return first;
45395
}
45396
simdjson_inline simdjson_result<fallback::ondemand::value>::operator fallback::ondemand::raw_json_string() noexcept(false) {
45397
  if (error()) { throw simdjson_error(error()); }
45398
  return first;
45399
}
45400
simdjson_inline simdjson_result<fallback::ondemand::value>::operator bool() noexcept(false) {
45401
  if (error()) { throw simdjson_error(error()); }
45402
  return first;
45403
}
45404
#endif
45405
45406
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::value>::raw_json_token() noexcept {
45407
0
  if (error()) { return error(); }
45408
0
  return first.raw_json_token();
45409
0
}
45410
45411
0
simdjson_inline simdjson_result<std::string_view> simdjson_result<fallback::ondemand::value>::raw_json() noexcept {
45412
0
  if (error()) { return error(); }
45413
0
  return first.raw_json();
45414
0
}
45415
45416
0
simdjson_inline simdjson_result<const char *> simdjson_result<fallback::ondemand::value>::current_location() noexcept {
45417
0
  if (error()) { return error(); }
45418
0
  return first.current_location();
45419
0
}
45420
45421
0
simdjson_inline simdjson_result<int32_t> simdjson_result<fallback::ondemand::value>::current_depth() const noexcept {
45422
0
  if (error()) { return error(); }
45423
0
  return first.current_depth();
45424
0
}
45425
45426
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::at_pointer(
45427
0
    std::string_view json_pointer) noexcept {
45428
0
  if (error()) {
45429
0
      return error();
45430
0
  }
45431
0
  return first.at_pointer(json_pointer);
45432
0
}
45433
45434
simdjson_inline simdjson_result<fallback::ondemand::value> simdjson_result<fallback::ondemand::value>::at_path(
45435
0
      std::string_view json_path) noexcept {
45436
0
  if (error()) {
45437
0
    return error();
45438
0
  }
45439
0
  return first.at_path(json_path);
45440
0
}
45441
45442
} // namespace simdjson
45443
45444
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
45445
/* end file simdjson/generic/ondemand/value-inl.h for fallback */
45446
/* including simdjson/generic/ondemand/value_iterator-inl.h for fallback: #include "simdjson/generic/ondemand/value_iterator-inl.h" */
45447
/* begin file simdjson/generic/ondemand/value_iterator-inl.h for fallback */
45448
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
45449
45450
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
45451
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */
45452
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
45453
/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */
45454
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
45455
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
45456
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */
45457
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
45458
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
45459
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
45460
45461
namespace simdjson {
45462
namespace fallback {
45463
namespace ondemand {
45464
45465
simdjson_inline value_iterator::value_iterator(
45466
  json_iterator *json_iter,
45467
  depth_t depth,
45468
  token_position start_position
45469
0
) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
45470
0
{
45471
0
}
45472
45473
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
45474
0
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
45475
0
  return started_object();
45476
0
}
45477
45478
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
45479
0
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
45480
0
  return started_root_object();
45481
0
}
45482
45483
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
45484
0
  assert_at_container_start();
45485
#if SIMDJSON_DEVELOPMENT_CHECKS
45486
  _json_iter->set_start_position(_depth, start_position());
45487
#endif
45488
0
  if (*_json_iter->peek() == '}') {
45489
0
    logger::log_value(*_json_iter, "empty object");
45490
0
    _json_iter->return_current_and_advance();
45491
0
    end_container();
45492
0
    return false;
45493
0
  }
45494
0
  return true;
45495
0
}
45496
45497
0
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
45498
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
45499
  // current document. It only works in the normal mode where we have indexed a single document.
45500
  // Note that adding a check for 'streaming' is not expensive since we only have at most
45501
  // one root element.
45502
0
  if ( ! _json_iter->streaming() ) {
45503
    // The following lines do not fully protect against garbage content within the
45504
    // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
45505
    // call `at_end()` on the document instance at the end of the processing to
45506
    // ensure that the processing has finished at the end.
45507
    //
45508
0
    if (*_json_iter->peek_last() != '}') {
45509
0
      _json_iter->abandon();
45510
0
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
45511
0
    }
45512
    // If the last character is } *and* the first gibberish character is also '}'
45513
    // then on-demand could accidentally go over. So we need additional checks.
45514
    // https://github.com/simdjson/simdjson/issues/1834
45515
    // Checking that the document is balanced requires a full scan which is potentially
45516
    // expensive, but it only happens in edge cases where the first padding character is
45517
    // a closing bracket.
45518
0
    if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
45519
0
      _json_iter->abandon();
45520
      // The exact error would require more work. It will typically be an unclosed object.
45521
0
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
45522
0
    }
45523
0
  }
45524
0
  return SUCCESS;
45525
0
}
45526
45527
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
45528
0
  auto error = check_root_object();
45529
0
  if(error) { return error; }
45530
0
  return started_object();
45531
0
}
45532
45533
0
simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
45534
#if SIMDJSON_CHECK_EOF
45535
    if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
45536
    // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
45537
#endif // SIMDJSON_CHECK_EOF
45538
0
    _json_iter->ascend_to(depth()-1);
45539
0
    return SUCCESS;
45540
0
}
45541
45542
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
45543
0
  assert_at_next();
45544
45545
  // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
45546
  // obligated to verify there are more tokens if they are not the top level.
45547
0
  switch (*_json_iter->return_current_and_advance()) {
45548
0
    case '}':
45549
0
      logger::log_end_value(*_json_iter, "object");
45550
0
      SIMDJSON_TRY( end_container() );
45551
0
      return false;
45552
0
    case ',':
45553
0
      return true;
45554
0
    default:
45555
0
      return report_error(TAPE_ERROR, "Missing comma between object fields");
45556
0
  }
45557
0
}
45558
45559
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
45560
0
  error_code error;
45561
0
  bool has_value;
45562
0
  //
45563
0
  // Initially, the object can be in one of a few different places:
45564
0
  //
45565
0
  // 1. The start of the object, at the first field:
45566
0
  //
45567
0
  //    ```
45568
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45569
0
  //      ^ (depth 2, index 1)
45570
0
  //    ```
45571
0
  if (at_first_field()) {
45572
0
    has_value = true;
45573
0
45574
0
  //
45575
0
  // 2. When a previous search did not yield a value or the object is empty:
45576
0
  //
45577
0
  //    ```
45578
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45579
0
  //                                     ^ (depth 0)
45580
0
  //    { }
45581
0
  //        ^ (depth 0, index 2)
45582
0
  //    ```
45583
0
  //
45584
0
  } else if (!is_open()) {
45585
0
#if SIMDJSON_DEVELOPMENT_CHECKS
45586
0
    // If we're past the end of the object, we're being iterated out of order.
45587
0
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
45588
0
    // this object iterator will blithely scan that object for fields.
45589
0
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
45590
0
#endif
45591
0
    return false;
45592
0
45593
0
  // 3. When a previous search found a field or an iterator yielded a value:
45594
0
  //
45595
0
  //    ```
45596
0
  //    // When a field was not fully consumed (or not even touched at all)
45597
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45598
0
  //           ^ (depth 2)
45599
0
  //    // When a field was fully consumed
45600
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45601
0
  //                   ^ (depth 1)
45602
0
  //    // When the last field was fully consumed
45603
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45604
0
  //                                   ^ (depth 1)
45605
0
  //    ```
45606
0
  //
45607
0
  } else {
45608
0
    if ((error = skip_child() )) { abandon(); return error; }
45609
0
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
45610
0
#if SIMDJSON_DEVELOPMENT_CHECKS
45611
0
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
45612
0
#endif
45613
0
  }
45614
0
  while (has_value) {
45615
0
    // Get the key and colon, stopping at the value.
45616
0
    raw_json_string actual_key;
45617
0
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
45618
0
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
45619
0
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
45620
0
    // The depth is left unchanged by field_key().
45621
0
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
45622
0
    // field_value() will advance and check that we find a ':' separating the
45623
0
    // key and the value. It will also increment the depth by one.
45624
0
    if ((error = field_value() )) { abandon(); return error; }
45625
0
    // If it matches, stop and return
45626
0
    // We could do it this way if we wanted to allow arbitrary
45627
0
    // key content (including escaped quotes).
45628
0
    //if (actual_key.unsafe_is_equal(max_key_length, key)) {
45629
0
    // Instead we do the following which may trigger buffer overruns if the
45630
0
    // user provides an adversarial key (containing a well placed unescaped quote
45631
0
    // character and being longer than the number of bytes remaining in the JSON
45632
0
    // input).
45633
0
    if (actual_key.unsafe_is_equal(key)) {
45634
0
      logger::log_event(*this, "match", key, -2);
45635
0
      // If we return here, then we return while pointing at the ':' that we just checked.
45636
0
      return true;
45637
0
    }
45638
0
45639
0
    // No match: skip the value and see if , or } is next
45640
0
    logger::log_event(*this, "no match", key, -2);
45641
0
    // The call to skip_child is meant to skip over the value corresponding to the key.
45642
0
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
45643
0
    SIMDJSON_TRY( skip_child() ); // Skip the value entirely
45644
0
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
45645
0
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
45646
0
    // then we are in error and we abort.
45647
0
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
45648
0
  }
45649
0
45650
0
  // If the loop ended, we're out of fields to look at.
45651
0
  return false;
45652
0
}
45653
45654
SIMDJSON_PUSH_DISABLE_WARNINGS
45655
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
45656
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
45657
0
  /**
45658
0
   * When find_field_unordered_raw is called, we can either be pointing at the
45659
0
   * first key, pointing outside (at the closing brace) or if a key was matched
45660
0
   * we can be either pointing right afterthe ':' right before the value (that we need skip),
45661
0
   * or we may have consumed the value and we might be at a comma or at the
45662
0
   * final brace (ready for a call to has_next_field()).
45663
0
   */
45664
0
  error_code error;
45665
0
  bool has_value;
45666
0
45667
0
  // First, we scan from that point to the end.
45668
0
  // If we don't find a match, we may loop back around, and scan from the beginning to that point.
45669
0
  token_position search_start = _json_iter->position();
45670
0
45671
0
  // We want to know whether we need to go back to the beginning.
45672
0
  bool at_first = at_first_field();
45673
0
  ///////////////
45674
0
  // Initially, the object can be in one of a few different places:
45675
0
  //
45676
0
  // 1. At the first key:
45677
0
  //
45678
0
  //    ```
45679
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45680
0
  //      ^ (depth 2, index 1)
45681
0
  //    ```
45682
0
  //
45683
0
  if (at_first) {
45684
0
    has_value = true;
45685
0
45686
0
  // 2. When a previous search did not yield a value or the object is empty:
45687
0
  //
45688
0
  //    ```
45689
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45690
0
  //                                     ^ (depth 0)
45691
0
  //    { }
45692
0
  //        ^ (depth 0, index 2)
45693
0
  //    ```
45694
0
  //
45695
0
  } else if (!is_open()) {
45696
0
45697
0
#if SIMDJSON_DEVELOPMENT_CHECKS
45698
0
    // If we're past the end of the object, we're being iterated out of order.
45699
0
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
45700
0
    // this object iterator will blithely scan that object for fields.
45701
0
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
45702
0
#endif
45703
0
    SIMDJSON_TRY(reset_object().get(has_value));
45704
0
    at_first = true;
45705
0
  // 3. When a previous search found a field or an iterator yielded a value:
45706
0
  //
45707
0
  //    ```
45708
0
  //    // When a field was not fully consumed (or not even touched at all)
45709
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45710
0
  //           ^ (depth 2)
45711
0
  //    // When a field was fully consumed
45712
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45713
0
  //                   ^ (depth 1)
45714
0
  //    // When the last field was fully consumed
45715
0
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45716
0
  //                                   ^ (depth 1)
45717
0
  //    ```
45718
0
  //
45719
0
  } else {
45720
0
    // If someone queried a key but they not did access the value, then we are left pointing
45721
0
    // at the ':' and we need to move forward through the value... If the value was
45722
0
    // processed then skip_child() does not move the iterator (but may adjust the depth).
45723
0
    if ((error = skip_child() )) { abandon(); return error; }
45724
0
    search_start = _json_iter->position();
45725
0
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
45726
0
#if SIMDJSON_DEVELOPMENT_CHECKS
45727
0
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
45728
0
#endif
45729
0
  }
45730
0
45731
0
  // After initial processing, we will be in one of two states:
45732
0
  //
45733
0
  // ```
45734
0
  // // At the beginning of a field
45735
0
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45736
0
  //   ^ (depth 1)
45737
0
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45738
0
  //                  ^ (depth 1)
45739
0
  // // At the end of the object
45740
0
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
45741
0
  //                                  ^ (depth 0)
45742
0
  // ```
45743
0
  //
45744
0
  // Next, we find a match starting from the current position.
45745
0
  while (has_value) {
45746
0
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
45747
0
45748
0
    // Get the key and colon, stopping at the value.
45749
0
    raw_json_string actual_key;
45750
0
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
45751
0
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
45752
0
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
45753
0
    // The depth is left unchanged by field_key().
45754
0
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
45755
0
    // field_value() will advance and check that we find a ':' separating the
45756
0
    // key and the value. It will also increment the depth by one.
45757
0
    if ((error = field_value() )) { abandon(); return error; }
45758
0
45759
0
    // If it matches, stop and return
45760
0
    // We could do it this way if we wanted to allow arbitrary
45761
0
    // key content (including escaped quotes).
45762
0
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
45763
0
    // Instead we do the following which may trigger buffer overruns if the
45764
0
    // user provides an adversarial key (containing a well placed unescaped quote
45765
0
    // character and being longer than the number of bytes remaining in the JSON
45766
0
    // input).
45767
0
    if (actual_key.unsafe_is_equal(key)) {
45768
0
      logger::log_event(*this, "match", key, -2);
45769
0
      // If we return here, then we return while pointing at the ':' that we just checked.
45770
0
      return true;
45771
0
    }
45772
0
45773
0
    // No match: skip the value and see if , or } is next
45774
0
    logger::log_event(*this, "no match", key, -2);
45775
0
    // The call to skip_child is meant to skip over the value corresponding to the key.
45776
0
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
45777
0
    SIMDJSON_TRY( skip_child() );
45778
0
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
45779
0
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
45780
0
    // then we are in error and we abort.
45781
0
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
45782
0
  }
45783
0
  // Performance note: it maybe wasteful to rewind to the beginning when there might be
45784
0
  // no other query following. Indeed, it would require reskipping the whole object.
45785
0
  // Instead, you can just stay where you are. If there is a new query, there is always time
45786
0
  // to rewind.
45787
0
  if(at_first) { return false; }
45788
0
45789
0
  // If we reach the end without finding a match, search the rest of the fields starting at the
45790
0
  // beginning of the object.
45791
0
  // (We have already run through the object before, so we've already validated its structure. We
45792
0
  // don't check errors in this bit.)
45793
0
  SIMDJSON_TRY(reset_object().get(has_value));
45794
0
  while (true) {
45795
0
    SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
45796
0
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
45797
0
45798
0
    // Get the key and colon, stopping at the value.
45799
0
    raw_json_string actual_key;
45800
0
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
45801
0
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
45802
0
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
45803
0
    // The depth is left unchanged by field_key().
45804
0
    error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
45805
0
    // field_value() will advance and check that we find a ':' separating the
45806
0
    // key and the value.  It will also increment the depth by one.
45807
0
    error = field_value(); SIMDJSON_ASSUME(!error);
45808
0
45809
0
    // If it matches, stop and return
45810
0
    // We could do it this way if we wanted to allow arbitrary
45811
0
    // key content (including escaped quotes).
45812
0
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
45813
0
    // Instead we do the following which may trigger buffer overruns if the
45814
0
    // user provides an adversarial key (containing a well placed unescaped quote
45815
0
    // character and being longer than the number of bytes remaining in the JSON
45816
0
    // input).
45817
0
    if (actual_key.unsafe_is_equal(key)) {
45818
0
      logger::log_event(*this, "match", key, -2);
45819
0
      // If we return here, then we return while pointing at the ':' that we just checked.
45820
0
      return true;
45821
0
    }
45822
0
45823
0
    // No match: skip the value and see if , or } is next
45824
0
    logger::log_event(*this, "no match", key, -2);
45825
0
    // The call to skip_child is meant to skip over the value corresponding to the key.
45826
0
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
45827
0
    SIMDJSON_TRY( skip_child() );
45828
0
    // If we reached the end of the key-value pair we started from, then we know
45829
0
    // that the key is not there so we return false. We are either right before
45830
0
    // the next comma or the final brace.
45831
0
    if(_json_iter->position() == search_start) { return false; }
45832
0
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
45833
0
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
45834
0
    // then we are in error and we abort.
45835
0
    error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
45836
0
    // If we make the mistake of exiting here, then we could be left pointing at a key
45837
0
    // in the middle of an object. That's not an allowable state.
45838
0
  }
45839
0
  // If the loop ended, we're out of fields to look at. The program should
45840
0
  // never reach this point.
45841
0
  return false;
45842
0
}
45843
SIMDJSON_POP_DISABLE_WARNINGS
45844
45845
0
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
45846
0
  assert_at_next();
45847
45848
0
  const uint8_t *key = _json_iter->return_current_and_advance();
45849
0
  if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
45850
0
  return raw_json_string(key);
45851
0
}
45852
45853
0
simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
45854
0
  assert_at_next();
45855
45856
0
  if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
45857
0
  _json_iter->descend_to(depth()+1);
45858
0
  return SUCCESS;
45859
0
}
45860
45861
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
45862
0
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
45863
0
  return started_array();
45864
0
}
45865
45866
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
45867
0
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
45868
0
  return started_root_array();
45869
0
}
45870
45871
0
inline std::string value_iterator::to_string() const noexcept {
45872
0
  auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
45873
0
  if(_json_iter != nullptr) { answer +=  _json_iter->to_string(); }
45874
0
  answer += std::string(" ]");
45875
0
  return answer;
45876
0
}
45877
45878
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
45879
0
  assert_at_container_start();
45880
0
  if (*_json_iter->peek() == ']') {
45881
0
    logger::log_value(*_json_iter, "empty array");
45882
0
    _json_iter->return_current_and_advance();
45883
0
    SIMDJSON_TRY( end_container() );
45884
0
    return false;
45885
0
  }
45886
0
  _json_iter->descend_to(depth()+1);
45887
#if SIMDJSON_DEVELOPMENT_CHECKS
45888
  _json_iter->set_start_position(_depth, start_position());
45889
#endif
45890
0
  return true;
45891
0
}
45892
45893
0
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
45894
0
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
45895
0
  // current document. It only works in the normal mode where we have indexed a single document.
45896
0
  // Note that adding a check for 'streaming' is not expensive since we only have at most
45897
0
  // one root element.
45898
0
  if ( ! _json_iter->streaming() ) {
45899
0
    // The following lines do not fully protect against garbage content within the
45900
0
    // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
45901
0
    // also call `at_end()` on the document instance at the end of the processing to
45902
0
    // ensure that the processing has finished at the end.
45903
0
    //
45904
0
    if (*_json_iter->peek_last() != ']') {
45905
0
      _json_iter->abandon();
45906
0
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
45907
0
    }
45908
0
    // If the last character is ] *and* the first gibberish character is also ']'
45909
0
    // then on-demand could accidentally go over. So we need additional checks.
45910
0
    // https://github.com/simdjson/simdjson/issues/1834
45911
0
    // Checking that the document is balanced requires a full scan which is potentially
45912
0
    // expensive, but it only happens in edge cases where the first padding character is
45913
0
    // a closing bracket.
45914
0
    if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
45915
0
      _json_iter->abandon();
45916
0
      // The exact error would require more work. It will typically be an unclosed array.
45917
0
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
45918
0
    }
45919
0
  }
45920
0
  return SUCCESS;
45921
0
}
45922
45923
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
45924
0
  auto error = check_root_array();
45925
0
  if (error) { return error; }
45926
0
  return started_array();
45927
0
}
45928
45929
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
45930
0
  assert_at_next();
45931
0
45932
0
  logger::log_event(*this, "has_next_element");
45933
0
  switch (*_json_iter->return_current_and_advance()) {
45934
0
    case ']':
45935
0
      logger::log_end_value(*_json_iter, "array");
45936
0
      SIMDJSON_TRY( end_container() );
45937
0
      return false;
45938
0
    case ',':
45939
0
      _json_iter->descend_to(depth()+1);
45940
0
      return true;
45941
0
    default:
45942
0
      return report_error(TAPE_ERROR, "Missing comma between array elements");
45943
0
  }
45944
0
}
45945
45946
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
45947
0
  auto not_true = atomparsing::str4ncmp(json, "true");
45948
0
  auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
45949
0
  bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
45950
0
  if (error) { return incorrect_type_error("Not a boolean"); }
45951
0
  return simdjson_result<bool>(!not_true);
45952
0
}
45953
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
45954
0
  bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
45955
0
  // if we start with 'n', we must be a null
45956
0
  if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
45957
0
  return is_null_string;
45958
0
}
45959
45960
0
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
45961
0
  return get_raw_json_string().unescape(json_iter(), allow_replacement);
45962
0
}
45963
template <typename string_type>
45964
0
simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
45965
0
  std::string_view content;
45966
0
  auto err = get_string(allow_replacement).get(content);
45967
0
  if (err) { return err; }
45968
0
  receiver = content;
45969
0
  return SUCCESS;
45970
0
}
45971
0
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
45972
0
  return get_raw_json_string().unescape_wobbly(json_iter());
45973
0
}
45974
0
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
45975
0
  auto json = peek_scalar("string");
45976
0
  if (*json != '"') { return incorrect_type_error("Not a string"); }
45977
0
  advance_scalar("string");
45978
0
  return raw_json_string(json+1);
45979
0
}
45980
0
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
45981
0
  auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
45982
0
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
45983
0
  return result;
45984
0
}
45985
0
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
45986
0
  auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
45987
0
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
45988
0
  return result;
45989
0
}
45990
0
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
45991
0
  auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
45992
0
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
45993
0
  return result;
45994
0
}
45995
0
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
45996
0
  auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
45997
0
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
45998
0
  return result;
45999
0
}
46000
0
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
46001
0
  auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
46002
0
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
46003
0
  return result;
46004
0
}
46005
0
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
46006
0
  auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
46007
0
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
46008
0
  return result;
46009
0
}
46010
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
46011
0
  auto result = parse_bool(peek_non_root_scalar("bool"));
46012
0
  if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
46013
0
  return result;
46014
0
}
46015
0
simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
46016
0
  bool is_null_value;
46017
0
  SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
46018
0
  if(is_null_value) { advance_non_root_scalar("null"); }
46019
0
  return is_null_value;
46020
0
}
46021
0
simdjson_inline bool value_iterator::is_negative() noexcept {
46022
0
  return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
46023
0
}
46024
0
simdjson_inline bool value_iterator::is_root_negative() noexcept {
46025
0
  return numberparsing::is_negative(peek_root_scalar("numbersign"));
46026
0
}
46027
0
simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
46028
0
  return numberparsing::is_integer(peek_non_root_scalar("integer"));
46029
0
}
46030
0
simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
46031
0
  return numberparsing::get_number_type(peek_non_root_scalar("integer"));
46032
0
}
46033
0
simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
46034
0
  number num;
46035
0
  error_code error =  numberparsing::parse_number(peek_non_root_scalar("number"), num);
46036
0
  if(error) { return error; }
46037
0
  return num;
46038
0
}
46039
46040
0
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
46041
0
  auto max_len = peek_root_length();
46042
0
  auto json = peek_root_scalar("is_root_integer");
46043
0
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
46044
0
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
46045
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
46046
0
    return false; // if there are more than 20 characters, it cannot be represented as an integer.
46047
0
  }
46048
0
  auto answer = numberparsing::is_integer(tmpbuf);
46049
0
  // If the parsing was a success, we must still check that it is
46050
0
  // a single scalar. Note that we parse first because of cases like '[]' where
46051
0
  // getting TRAILING_CONTENT is wrong.
46052
0
  if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
46053
0
  return answer;
46054
0
}
46055
46056
0
simdjson_inline simdjson_result<fallback::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
46057
0
  auto max_len = peek_root_length();
46058
0
  auto json = peek_root_scalar("number");
46059
0
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
46060
0
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
46061
0
  // number: -0.<fraction>e-308.
46062
0
  uint8_t tmpbuf[1074+8+1+1];
46063
0
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
46064
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
46065
0
    if(numberparsing::check_if_integer(json, max_len)) {
46066
0
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46067
0
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
46068
0
      return number_type::big_integer;
46069
0
    }
46070
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
46071
0
    return NUMBER_ERROR;
46072
0
  }
46073
0
  auto answer = numberparsing::get_number_type(tmpbuf);
46074
0
  if (check_trailing && (answer.error() == SUCCESS)  && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46075
0
  return answer;
46076
0
}
46077
0
simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
46078
0
  auto max_len = peek_root_length();
46079
0
  auto json = peek_root_scalar("number");
46080
0
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
46081
0
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
46082
0
  // number: -0.<fraction>e-308.
46083
0
  // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
46084
0
  uint8_t tmpbuf[1074+8+1+1];
46085
0
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
46086
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
46087
0
    if(numberparsing::check_if_integer(json, max_len)) {
46088
0
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46089
0
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
46090
0
      return BIGINT_ERROR;
46091
0
    }
46092
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
46093
0
    return NUMBER_ERROR;
46094
0
  }
46095
0
  number num;
46096
0
  error_code error =  numberparsing::parse_number(tmpbuf, num);
46097
0
  if(error) { return error; }
46098
0
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46099
0
  advance_root_scalar("number");
46100
0
  return num;
46101
0
}
46102
0
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
46103
0
  return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
46104
0
}
46105
template <typename string_type>
46106
simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
46107
  std::string_view content;
46108
  auto err = get_root_string(check_trailing, allow_replacement).get(content);
46109
  if (err) { return err; }
46110
  receiver = content;
46111
  return SUCCESS;
46112
}
46113
0
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
46114
0
  return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
46115
0
}
46116
0
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
46117
0
  auto json = peek_scalar("string");
46118
0
  if (*json != '"') { return incorrect_type_error("Not a string"); }
46119
0
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46120
0
  advance_scalar("string");
46121
0
  return raw_json_string(json+1);
46122
0
}
46123
0
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
46124
0
  auto max_len = peek_root_length();
46125
0
  auto json = peek_root_scalar("uint64");
46126
0
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
46127
0
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
46128
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
46129
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
46130
0
    return NUMBER_ERROR;
46131
0
  }
46132
0
  auto result = numberparsing::parse_unsigned(tmpbuf);
46133
0
  if(result.error() == SUCCESS) {
46134
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46135
0
    advance_root_scalar("uint64");
46136
0
  }
46137
0
  return result;
46138
0
}
46139
0
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
46140
0
  auto max_len = peek_root_length();
46141
0
  auto json = peek_root_scalar("uint64");
46142
0
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
46143
0
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
46144
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
46145
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
46146
0
    return NUMBER_ERROR;
46147
0
  }
46148
0
  auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
46149
0
  if(result.error() == SUCCESS) {
46150
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46151
0
    advance_root_scalar("uint64");
46152
0
  }
46153
0
  return result;
46154
0
}
46155
0
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
46156
0
  auto max_len = peek_root_length();
46157
0
  auto json = peek_root_scalar("int64");
46158
0
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
46159
0
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
46160
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
46161
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
46162
0
    return NUMBER_ERROR;
46163
0
  }
46164
0
46165
0
  auto result = numberparsing::parse_integer(tmpbuf);
46166
0
  if(result.error() == SUCCESS) {
46167
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46168
0
    advance_root_scalar("int64");
46169
0
  }
46170
0
  return result;
46171
0
}
46172
0
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
46173
0
  auto max_len = peek_root_length();
46174
0
  auto json = peek_root_scalar("int64");
46175
0
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
46176
0
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
46177
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
46178
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
46179
0
    return NUMBER_ERROR;
46180
0
  }
46181
0
46182
0
  auto result = numberparsing::parse_integer_in_string(tmpbuf);
46183
0
  if(result.error() == SUCCESS) {
46184
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46185
0
    advance_root_scalar("int64");
46186
0
  }
46187
0
  return result;
46188
0
}
46189
0
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
46190
0
  auto max_len = peek_root_length();
46191
0
  auto json = peek_root_scalar("double");
46192
0
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
46193
0
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
46194
0
  // number: -0.<fraction>e-308.
46195
0
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
46196
0
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
46197
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
46198
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
46199
0
    return NUMBER_ERROR;
46200
0
  }
46201
0
  auto result = numberparsing::parse_double(tmpbuf);
46202
0
  if(result.error() == SUCCESS) {
46203
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46204
0
    advance_root_scalar("double");
46205
0
  }
46206
0
  return result;
46207
0
}
46208
46209
0
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
46210
0
  auto max_len = peek_root_length();
46211
0
  auto json = peek_root_scalar("double");
46212
0
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
46213
0
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
46214
0
  // number: -0.<fraction>e-308.
46215
0
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
46216
0
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
46217
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
46218
0
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
46219
0
    return NUMBER_ERROR;
46220
0
  }
46221
0
  auto result = numberparsing::parse_double_in_string(tmpbuf);
46222
0
  if(result.error() == SUCCESS) {
46223
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46224
0
    advance_root_scalar("double");
46225
0
  }
46226
0
  return result;
46227
0
}
46228
0
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
46229
0
  auto max_len = peek_root_length();
46230
0
  auto json = peek_root_scalar("bool");
46231
0
  uint8_t tmpbuf[5+1+1]; // +1 for null termination
46232
0
  tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
46233
0
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
46234
0
  auto result = parse_bool(tmpbuf);
46235
0
  if(result.error() == SUCCESS) {
46236
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46237
0
    advance_root_scalar("bool");
46238
0
  }
46239
0
  return result;
46240
0
}
46241
0
simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
46242
0
  auto max_len = peek_root_length();
46243
0
  auto json = peek_root_scalar("null");
46244
0
  bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
46245
0
         (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
46246
0
  if(result) { // we have something that looks like a null.
46247
0
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
46248
0
    advance_root_scalar("null");
46249
0
  }
46250
0
  return result;
46251
0
}
46252
46253
0
simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
46254
0
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
46255
0
  SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
46256
46257
0
  return _json_iter->skip_child(depth());
46258
0
}
46259
46260
0
simdjson_inline value_iterator value_iterator::child() const noexcept {
46261
0
  assert_at_child();
46262
0
  return { _json_iter, depth()+1, _json_iter->token.position() };
46263
0
}
46264
46265
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
46266
// relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
46267
// marked non-inline.
46268
SIMDJSON_PUSH_DISABLE_WARNINGS
46269
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
46270
0
simdjson_inline bool value_iterator::is_open() const noexcept {
46271
0
  return _json_iter->depth() >= depth();
46272
0
}
46273
SIMDJSON_POP_DISABLE_WARNINGS
46274
46275
0
simdjson_inline bool value_iterator::at_end() const noexcept {
46276
0
  return _json_iter->at_end();
46277
0
}
46278
46279
0
simdjson_inline bool value_iterator::at_start() const noexcept {
46280
0
  return _json_iter->token.position() == start_position();
46281
0
}
46282
46283
0
simdjson_inline bool value_iterator::at_first_field() const noexcept {
46284
0
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
46285
0
  return _json_iter->token.position() == start_position() + 1;
46286
0
}
46287
46288
0
simdjson_inline void value_iterator::abandon() noexcept {
46289
0
  _json_iter->abandon();
46290
0
}
46291
46292
0
simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
46293
0
  return _depth;
46294
0
}
46295
0
simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
46296
0
  return _json_iter->error;
46297
0
}
46298
0
simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
46299
0
  return _json_iter->string_buf_loc();
46300
0
}
46301
0
simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
46302
0
  return *_json_iter;
46303
0
}
46304
0
simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
46305
0
  return *_json_iter;
46306
0
}
46307
46308
0
simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
46309
0
  return _json_iter->peek(start_position());
46310
0
}
46311
0
simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
46312
0
  return _json_iter->peek_length(start_position());
46313
0
}
46314
0
simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
46315
0
  return _json_iter->peek_root_length(start_position());
46316
0
}
46317
46318
0
simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
46319
0
  logger::log_value(*_json_iter, start_position(), depth(), type);
46320
  // If we're not at the position anymore, we don't want to advance the cursor.
46321
0
  if (!is_at_start()) { return peek_start(); }
46322
46323
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
46324
0
  assert_at_start();
46325
0
  return _json_iter->peek();
46326
0
}
46327
46328
0
simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
46329
0
  logger::log_value(*_json_iter, start_position(), depth(), type);
46330
  // If we're not at the position anymore, we don't want to advance the cursor.
46331
0
  if (!is_at_start()) { return; }
46332
46333
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
46334
0
  assert_at_start();
46335
0
  _json_iter->return_current_and_advance();
46336
0
  _json_iter->ascend_to(depth()-1);
46337
0
}
46338
46339
0
simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
46340
0
  logger::log_start_value(*_json_iter, start_position(), depth(), type);
46341
  // If we're not at the position anymore, we don't want to advance the cursor.
46342
0
  const uint8_t *json;
46343
0
  if (!is_at_start()) {
46344
#if SIMDJSON_DEVELOPMENT_CHECKS
46345
    if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
46346
#endif
46347
0
    json = peek_start();
46348
0
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
46349
0
  } else {
46350
0
    assert_at_start();
46351
    /**
46352
     * We should be prudent. Let us peek. If it is not the right type, we
46353
     * return an error. Only once we have determined that we have the right
46354
     * type are we allowed to advance!
46355
     */
46356
0
    json = _json_iter->peek();
46357
0
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
46358
0
    _json_iter->return_current_and_advance();
46359
0
  }
46360
46361
46362
0
  return SUCCESS;
46363
0
}
46364
46365
46366
0
simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
46367
0
  logger::log_value(*_json_iter, start_position(), depth(), type);
46368
0
  if (!is_at_start()) { return peek_start(); }
46369
0
46370
0
  assert_at_root();
46371
0
  return _json_iter->peek();
46372
0
}
46373
0
simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
46374
0
  logger::log_value(*_json_iter, start_position(), depth(), type);
46375
0
  if (!is_at_start()) { return peek_start(); }
46376
0
46377
0
  assert_at_non_root_start();
46378
0
  return _json_iter->peek();
46379
0
}
46380
46381
0
simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
46382
0
  logger::log_value(*_json_iter, start_position(), depth(), type);
46383
0
  if (!is_at_start()) { return; }
46384
0
46385
0
  assert_at_root();
46386
0
  _json_iter->return_current_and_advance();
46387
0
  _json_iter->ascend_to(depth()-1);
46388
0
}
46389
0
simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
46390
0
  logger::log_value(*_json_iter, start_position(), depth(), type);
46391
0
  if (!is_at_start()) { return; }
46392
0
46393
0
  assert_at_non_root_start();
46394
0
  _json_iter->return_current_and_advance();
46395
0
  _json_iter->ascend_to(depth()-1);
46396
0
}
46397
46398
0
simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
46399
0
  logger::log_error(*_json_iter, start_position(), depth(), message);
46400
0
  return INCORRECT_TYPE;
46401
0
}
46402
46403
0
simdjson_inline bool value_iterator::is_at_start() const noexcept {
46404
0
  return position() == start_position();
46405
0
}
46406
46407
0
simdjson_inline bool value_iterator::is_at_key() const noexcept {
46408
  // Keys are at the same depth as the object.
46409
  // Note here that we could be safer and check that we are within an object,
46410
  // but we do not.
46411
0
  return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
46412
0
}
46413
46414
0
simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
46415
0
  // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
46416
0
  auto delta = position() - start_position();
46417
0
  return delta == 1 || delta == 2;
46418
0
}
46419
46420
0
inline void value_iterator::assert_at_start() const noexcept {
46421
0
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
46422
0
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
46423
0
  SIMDJSON_ASSUME( _depth > 0 );
46424
0
}
46425
46426
0
inline void value_iterator::assert_at_container_start() const noexcept {
46427
0
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
46428
0
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
46429
0
  SIMDJSON_ASSUME( _depth > 0 );
46430
0
}
46431
46432
0
inline void value_iterator::assert_at_next() const noexcept {
46433
0
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
46434
0
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
46435
0
  SIMDJSON_ASSUME( _depth > 0 );
46436
0
}
46437
46438
0
simdjson_inline void value_iterator::move_at_start() noexcept {
46439
0
  _json_iter->_depth = _depth;
46440
0
  _json_iter->token.set_position(_start_position);
46441
0
}
46442
46443
0
simdjson_inline void value_iterator::move_at_container_start() noexcept {
46444
0
  _json_iter->_depth = _depth;
46445
0
  _json_iter->token.set_position(_start_position + 1);
46446
0
}
46447
46448
0
simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
46449
0
  if(error()) { return error(); }
46450
0
  move_at_container_start();
46451
0
  return started_array();
46452
0
}
46453
46454
0
simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
46455
0
  if(error()) { return error(); }
46456
0
  move_at_container_start();
46457
0
  return started_object();
46458
0
}
46459
46460
0
inline void value_iterator::assert_at_child() const noexcept {
46461
0
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
46462
0
  SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
46463
0
  SIMDJSON_ASSUME( _depth > 0 );
46464
0
}
46465
46466
0
inline void value_iterator::assert_at_root() const noexcept {
46467
0
  assert_at_start();
46468
0
  SIMDJSON_ASSUME( _depth == 1 );
46469
0
}
46470
46471
0
inline void value_iterator::assert_at_non_root_start() const noexcept {
46472
0
  assert_at_start();
46473
0
  SIMDJSON_ASSUME( _depth > 1 );
46474
0
}
46475
46476
0
inline void value_iterator::assert_is_valid() const noexcept {
46477
0
  SIMDJSON_ASSUME( _json_iter != nullptr );
46478
0
}
46479
46480
0
simdjson_inline bool value_iterator::is_valid() const noexcept {
46481
0
  return _json_iter != nullptr;
46482
0
}
46483
46484
0
simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
46485
0
  switch (*peek_start()) {
46486
0
    case '{':
46487
0
      return json_type::object;
46488
0
    case '[':
46489
0
      return json_type::array;
46490
0
    case '"':
46491
0
      return json_type::string;
46492
0
    case 'n':
46493
0
      return json_type::null;
46494
0
    case 't': case 'f':
46495
0
      return json_type::boolean;
46496
0
    case '-':
46497
0
    case '0': case '1': case '2': case '3': case '4':
46498
0
    case '5': case '6': case '7': case '8': case '9':
46499
0
      return json_type::number;
46500
0
    default:
46501
0
      return TAPE_ERROR;
46502
0
  }
46503
0
}
46504
46505
0
simdjson_inline token_position value_iterator::start_position() const noexcept {
46506
0
  return _start_position;
46507
0
}
46508
46509
0
simdjson_inline token_position value_iterator::position() const noexcept {
46510
0
  return _json_iter->position();
46511
0
}
46512
46513
0
simdjson_inline token_position value_iterator::end_position() const noexcept {
46514
0
  return _json_iter->end_position();
46515
0
}
46516
46517
0
simdjson_inline token_position value_iterator::last_position() const noexcept {
46518
0
  return _json_iter->last_position();
46519
0
}
46520
46521
0
simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
46522
0
  return _json_iter->report_error(error, message);
46523
0
}
46524
46525
} // namespace ondemand
46526
} // namespace fallback
46527
} // namespace simdjson
46528
46529
namespace simdjson {
46530
46531
simdjson_inline simdjson_result<fallback::ondemand::value_iterator>::simdjson_result(fallback::ondemand::value_iterator &&value) noexcept
46532
    : implementation_simdjson_result_base<fallback::ondemand::value_iterator>(std::forward<fallback::ondemand::value_iterator>(value)) {}
46533
simdjson_inline simdjson_result<fallback::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
46534
    : implementation_simdjson_result_base<fallback::ondemand::value_iterator>(error) {}
46535
46536
} // namespace simdjson
46537
46538
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
46539
/* end file simdjson/generic/ondemand/value_iterator-inl.h for fallback */
46540
/* end file simdjson/generic/ondemand/amalgamated.h for fallback */
46541
/* including simdjson/fallback/end.h: #include "simdjson/fallback/end.h" */
46542
/* begin file simdjson/fallback/end.h */
46543
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46544
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
46545
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46546
46547
/* undefining SIMDJSON_IMPLEMENTATION from "fallback" */
46548
#undef SIMDJSON_IMPLEMENTATION
46549
/* end file simdjson/fallback/end.h */
46550
46551
#endif // SIMDJSON_FALLBACK_ONDEMAND_H
46552
/* end file simdjson/fallback/ondemand.h */
46553
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
46554
/* including simdjson/haswell/ondemand.h: #include "simdjson/haswell/ondemand.h" */
46555
/* begin file simdjson/haswell/ondemand.h */
46556
#ifndef SIMDJSON_HASWELL_ONDEMAND_H
46557
#define SIMDJSON_HASWELL_ONDEMAND_H
46558
46559
/* including simdjson/haswell/begin.h: #include "simdjson/haswell/begin.h" */
46560
/* begin file simdjson/haswell/begin.h */
46561
/* defining SIMDJSON_IMPLEMENTATION to "haswell" */
46562
#define SIMDJSON_IMPLEMENTATION haswell
46563
46564
/* including simdjson/haswell/base.h: #include "simdjson/haswell/base.h" */
46565
/* begin file simdjson/haswell/base.h */
46566
#ifndef SIMDJSON_HASWELL_BASE_H
46567
#define SIMDJSON_HASWELL_BASE_H
46568
46569
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46570
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
46571
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46572
46573
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_HASWELL
46574
namespace simdjson {
46575
/**
46576
 * Implementation for Haswell (Intel AVX2).
46577
 */
46578
namespace haswell {
46579
46580
class implementation;
46581
46582
namespace {
46583
namespace simd {
46584
template <typename T> struct simd8;
46585
template <typename T> struct simd8x64;
46586
} // namespace simd
46587
} // unnamed namespace
46588
46589
} // namespace haswell
46590
} // namespace simdjson
46591
46592
#endif // SIMDJSON_HASWELL_BASE_H
46593
/* end file simdjson/haswell/base.h */
46594
/* including simdjson/haswell/intrinsics.h: #include "simdjson/haswell/intrinsics.h" */
46595
/* begin file simdjson/haswell/intrinsics.h */
46596
#ifndef SIMDJSON_HASWELL_INTRINSICS_H
46597
#define SIMDJSON_HASWELL_INTRINSICS_H
46598
46599
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46600
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
46601
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46602
46603
#if SIMDJSON_VISUAL_STUDIO
46604
// under clang within visual studio, this will include <x86intrin.h>
46605
#include <intrin.h>  // visual studio or clang
46606
#else
46607
#include <x86intrin.h> // elsewhere
46608
#endif // SIMDJSON_VISUAL_STUDIO
46609
46610
#if SIMDJSON_CLANG_VISUAL_STUDIO
46611
/**
46612
 * You are not supposed, normally, to include these
46613
 * headers directly. Instead you should either include intrin.h
46614
 * or x86intrin.h. However, when compiling with clang
46615
 * under Windows (i.e., when _MSC_VER is set), these headers
46616
 * only get included *if* the corresponding features are detected
46617
 * from macros:
46618
 * e.g., if __AVX2__ is set... in turn,  we normally set these
46619
 * macros by compiling against the corresponding architecture
46620
 * (e.g., arch:AVX2, -mavx2, etc.) which compiles the whole
46621
 * software with these advanced instructions. In simdjson, we
46622
 * want to compile the whole program for a generic target,
46623
 * and only target our specific kernels. As a workaround,
46624
 * we directly include the needed headers. These headers would
46625
 * normally guard against such usage, but we carefully included
46626
 * <x86intrin.h>  (or <intrin.h>) before, so the headers
46627
 * are fooled.
46628
 */
46629
#include <bmiintrin.h>   // for _blsr_u64
46630
#include <lzcntintrin.h> // for  __lzcnt64
46631
#include <immintrin.h>   // for most things (AVX2, AVX512, _popcnt64)
46632
#include <smmintrin.h>
46633
#include <tmmintrin.h>
46634
#include <avxintrin.h>
46635
#include <avx2intrin.h>
46636
#include <wmmintrin.h>   // for  _mm_clmulepi64_si128
46637
// unfortunately, we may not get _blsr_u64, but, thankfully, clang
46638
// has it as a macro.
46639
#ifndef _blsr_u64
46640
// we roll our own
46641
#define _blsr_u64(n) ((n - 1) & n)
46642
#endif //  _blsr_u64
46643
#endif // SIMDJSON_CLANG_VISUAL_STUDIO
46644
46645
static_assert(sizeof(__m256i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for haswell kernel.");
46646
46647
#endif // SIMDJSON_HASWELL_INTRINSICS_H
46648
/* end file simdjson/haswell/intrinsics.h */
46649
46650
#if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL
46651
SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt")
46652
#endif
46653
46654
/* including simdjson/haswell/bitmanipulation.h: #include "simdjson/haswell/bitmanipulation.h" */
46655
/* begin file simdjson/haswell/bitmanipulation.h */
46656
#ifndef SIMDJSON_HASWELL_BITMANIPULATION_H
46657
#define SIMDJSON_HASWELL_BITMANIPULATION_H
46658
46659
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46660
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
46661
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
46662
/* amalgamation skipped (editor-only): #include "simdjson/haswell/bitmask.h" */
46663
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46664
46665
namespace simdjson {
46666
namespace haswell {
46667
namespace {
46668
46669
// We sometimes call trailing_zero on inputs that are zero,
46670
// but the algorithms do not end up using the returned value.
46671
// Sadly, sanitizers are not smart enough to figure it out.
46672
SIMDJSON_NO_SANITIZE_UNDEFINED
46673
// This function can be used safely even if not all bytes have been
46674
// initialized.
46675
// See issue https://github.com/simdjson/simdjson/issues/1965
46676
SIMDJSON_NO_SANITIZE_MEMORY
46677
simdjson_inline int trailing_zeroes(uint64_t input_num) {
46678
#if SIMDJSON_REGULAR_VISUAL_STUDIO
46679
  return (int)_tzcnt_u64(input_num);
46680
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
46681
  ////////
46682
  // You might expect the next line to be equivalent to
46683
  // return (int)_tzcnt_u64(input_num);
46684
  // but the generated code differs and might be less efficient?
46685
  ////////
46686
  return __builtin_ctzll(input_num);
46687
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
46688
}
46689
46690
/* result might be undefined when input_num is zero */
46691
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
46692
  return _blsr_u64(input_num);
46693
}
46694
46695
/* result might be undefined when input_num is zero */
46696
simdjson_inline int leading_zeroes(uint64_t input_num) {
46697
  return int(_lzcnt_u64(input_num));
46698
}
46699
46700
#if SIMDJSON_REGULAR_VISUAL_STUDIO
46701
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
46702
  // note: we do not support legacy 32-bit Windows in this kernel
46703
  return __popcnt64(input_num);// Visual Studio wants two underscores
46704
}
46705
#else
46706
simdjson_inline long long int count_ones(uint64_t input_num) {
46707
  return _popcnt64(input_num);
46708
}
46709
#endif
46710
46711
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
46712
                                uint64_t *result) {
46713
#if SIMDJSON_REGULAR_VISUAL_STUDIO
46714
  return _addcarry_u64(0, value1, value2,
46715
                       reinterpret_cast<unsigned __int64 *>(result));
46716
#else
46717
  return __builtin_uaddll_overflow(value1, value2,
46718
                                   reinterpret_cast<unsigned long long *>(result));
46719
#endif
46720
}
46721
46722
} // unnamed namespace
46723
} // namespace haswell
46724
} // namespace simdjson
46725
46726
#endif // SIMDJSON_HASWELL_BITMANIPULATION_H
46727
/* end file simdjson/haswell/bitmanipulation.h */
46728
/* including simdjson/haswell/bitmask.h: #include "simdjson/haswell/bitmask.h" */
46729
/* begin file simdjson/haswell/bitmask.h */
46730
#ifndef SIMDJSON_HASWELL_BITMASK_H
46731
#define SIMDJSON_HASWELL_BITMASK_H
46732
46733
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46734
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
46735
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
46736
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46737
46738
namespace simdjson {
46739
namespace haswell {
46740
namespace {
46741
46742
//
46743
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
46744
//
46745
// For example, prefix_xor(00100100) == 00011100
46746
//
46747
simdjson_inline uint64_t prefix_xor(const uint64_t bitmask) {
46748
  // There should be no such thing with a processor supporting avx2
46749
  // but not clmul.
46750
  __m128i all_ones = _mm_set1_epi8('\xFF');
46751
  __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, bitmask), all_ones, 0);
46752
  return _mm_cvtsi128_si64(result);
46753
}
46754
46755
} // unnamed namespace
46756
} // namespace haswell
46757
} // namespace simdjson
46758
46759
#endif // SIMDJSON_HASWELL_BITMASK_H
46760
/* end file simdjson/haswell/bitmask.h */
46761
/* including simdjson/haswell/numberparsing_defs.h: #include "simdjson/haswell/numberparsing_defs.h" */
46762
/* begin file simdjson/haswell/numberparsing_defs.h */
46763
#ifndef SIMDJSON_HASWELL_NUMBERPARSING_DEFS_H
46764
#define SIMDJSON_HASWELL_NUMBERPARSING_DEFS_H
46765
46766
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46767
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
46768
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
46769
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46770
46771
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46772
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
46773
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46774
46775
namespace simdjson {
46776
namespace haswell {
46777
namespace numberparsing {
46778
46779
/** @private */
46780
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
46781
  // this actually computes *16* values so we are being wasteful.
46782
  const __m128i ascii0 = _mm_set1_epi8('0');
46783
  const __m128i mul_1_10 =
46784
      _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1);
46785
  const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1);
46786
  const __m128i mul_1_10000 =
46787
      _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1);
46788
  const __m128i input = _mm_sub_epi8(
46789
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0);
46790
  const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10);
46791
  const __m128i t2 = _mm_madd_epi16(t1, mul_1_100);
46792
  const __m128i t3 = _mm_packus_epi32(t2, t2);
46793
  const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000);
46794
  return _mm_cvtsi128_si32(
46795
      t4); // only captures the sum of the first 8 digits, drop the rest
46796
}
46797
46798
/** @private */
46799
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
46800
  internal::value128 answer;
46801
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
46802
#ifdef _M_ARM64
46803
  // ARM64 has native support for 64-bit multiplications, no need to emultate
46804
  answer.high = __umulh(value1, value2);
46805
  answer.low = value1 * value2;
46806
#else
46807
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
46808
#endif // _M_ARM64
46809
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
46810
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
46811
  answer.low = uint64_t(r);
46812
  answer.high = uint64_t(r >> 64);
46813
#endif
46814
  return answer;
46815
}
46816
46817
} // namespace numberparsing
46818
} // namespace haswell
46819
} // namespace simdjson
46820
46821
#define SIMDJSON_SWAR_NUMBER_PARSING 1
46822
46823
#endif // SIMDJSON_HASWELL_NUMBERPARSING_DEFS_H
46824
/* end file simdjson/haswell/numberparsing_defs.h */
46825
/* including simdjson/haswell/simd.h: #include "simdjson/haswell/simd.h" */
46826
/* begin file simdjson/haswell/simd.h */
46827
#ifndef SIMDJSON_HASWELL_SIMD_H
46828
#define SIMDJSON_HASWELL_SIMD_H
46829
46830
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
46831
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
46832
/* amalgamation skipped (editor-only): #include "simdjson/haswell/intrinsics.h" */
46833
/* amalgamation skipped (editor-only): #include "simdjson/haswell/bitmanipulation.h" */
46834
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
46835
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
46836
46837
namespace simdjson {
46838
namespace haswell {
46839
namespace {
46840
namespace simd {
46841
46842
  // Forward-declared so they can be used by splat and friends.
46843
  template<typename Child>
46844
  struct base {
46845
    __m256i value;
46846
46847
    // Zero constructor
46848
    simdjson_inline base() : value{__m256i()} {}
46849
46850
    // Conversion from SIMD register
46851
    simdjson_inline base(const __m256i _value) : value(_value) {}
46852
46853
    // Conversion to SIMD register
46854
    simdjson_inline operator const __m256i&() const { return this->value; }
46855
    simdjson_inline operator __m256i&() { return this->value; }
46856
46857
    // Bit operations
46858
    simdjson_inline Child operator|(const Child other) const { return _mm256_or_si256(*this, other); }
46859
    simdjson_inline Child operator&(const Child other) const { return _mm256_and_si256(*this, other); }
46860
    simdjson_inline Child operator^(const Child other) const { return _mm256_xor_si256(*this, other); }
46861
    simdjson_inline Child bit_andnot(const Child other) const { return _mm256_andnot_si256(other, *this); }
46862
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
46863
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
46864
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
46865
  };
46866
46867
  // Forward-declared so they can be used by splat and friends.
46868
  template<typename T>
46869
  struct simd8;
46870
46871
  template<typename T, typename Mask=simd8<bool>>
46872
  struct base8: base<simd8<T>> {
46873
    typedef uint32_t bitmask_t;
46874
    typedef uint64_t bitmask2_t;
46875
46876
    simdjson_inline base8() : base<simd8<T>>() {}
46877
    simdjson_inline base8(const __m256i _value) : base<simd8<T>>(_value) {}
46878
46879
    friend simdjson_really_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return _mm256_cmpeq_epi8(lhs, rhs); }
46880
46881
    static const int SIZE = sizeof(base<T>::value);
46882
46883
    template<int N=1>
46884
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
46885
      return _mm256_alignr_epi8(*this, _mm256_permute2x128_si256(prev_chunk, *this, 0x21), 16 - N);
46886
    }
46887
  };
46888
46889
  // SIMD byte mask type (returned by things like eq and gt)
46890
  template<>
46891
  struct simd8<bool>: base8<bool> {
46892
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm256_set1_epi8(uint8_t(-(!!_value))); }
46893
46894
    simdjson_inline simd8<bool>() : base8() {}
46895
    simdjson_inline simd8<bool>(const __m256i _value) : base8<bool>(_value) {}
46896
    // Splat constructor
46897
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
46898
46899
    simdjson_inline int to_bitmask() const { return _mm256_movemask_epi8(*this); }
46900
    simdjson_inline bool any() const { return !_mm256_testz_si256(*this, *this); }
46901
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
46902
  };
46903
46904
  template<typename T>
46905
  struct base8_numeric: base8<T> {
46906
    static simdjson_inline simd8<T> splat(T _value) { return _mm256_set1_epi8(_value); }
46907
    static simdjson_inline simd8<T> zero() { return _mm256_setzero_si256(); }
46908
    static simdjson_inline simd8<T> load(const T values[32]) {
46909
      return _mm256_loadu_si256(reinterpret_cast<const __m256i *>(values));
46910
    }
46911
    // Repeat 16 values as many times as necessary (usually for lookup tables)
46912
    static simdjson_inline simd8<T> repeat_16(
46913
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
46914
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
46915
    ) {
46916
      return simd8<T>(
46917
        v0, v1, v2, v3, v4, v5, v6, v7,
46918
        v8, v9, v10,v11,v12,v13,v14,v15,
46919
        v0, v1, v2, v3, v4, v5, v6, v7,
46920
        v8, v9, v10,v11,v12,v13,v14,v15
46921
      );
46922
    }
46923
46924
    simdjson_inline base8_numeric() : base8<T>() {}
46925
    simdjson_inline base8_numeric(const __m256i _value) : base8<T>(_value) {}
46926
46927
    // Store to array
46928
    simdjson_inline void store(T dst[32]) const { return _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst), *this); }
46929
46930
    // Addition/subtraction are the same for signed and unsigned
46931
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm256_add_epi8(*this, other); }
46932
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm256_sub_epi8(*this, other); }
46933
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
46934
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
46935
46936
    // Override to distinguish from bool version
46937
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
46938
46939
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
46940
    template<typename L>
46941
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
46942
      return _mm256_shuffle_epi8(lookup_table, *this);
46943
    }
46944
46945
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
46946
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
46947
    // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes
46948
    // get written.
46949
    // Design consideration: it seems like a function with the
46950
    // signature simd8<L> compress(uint32_t mask) would be
46951
    // sensible, but the AVX ISA makes this kind of approach difficult.
46952
    template<typename L>
46953
    simdjson_inline void compress(uint32_t mask, L * output) const {
46954
      using internal::thintable_epi8;
46955
      using internal::BitsSetTable256mul2;
46956
      using internal::pshufb_combine_table;
46957
      // this particular implementation was inspired by work done by @animetosho
46958
      // we do it in four steps, first 8 bytes and then second 8 bytes...
46959
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
46960
      uint8_t mask2 = uint8_t(mask >> 8); // second least significant 8 bits
46961
      uint8_t mask3 = uint8_t(mask >> 16); // ...
46962
      uint8_t mask4 = uint8_t(mask >> 24); // ...
46963
      // next line just loads the 64-bit values thintable_epi8[mask1] and
46964
      // thintable_epi8[mask2] into a 128-bit register, using only
46965
      // two instructions on most compilers.
46966
      __m256i shufmask =  _mm256_set_epi64x(thintable_epi8[mask4], thintable_epi8[mask3],
46967
        thintable_epi8[mask2], thintable_epi8[mask1]);
46968
      // we increment by 0x08 the second half of the mask and so forth
46969
      shufmask =
46970
      _mm256_add_epi8(shufmask, _mm256_set_epi32(0x18181818, 0x18181818,
46971
         0x10101010, 0x10101010, 0x08080808, 0x08080808, 0, 0));
46972
      // this is the version "nearly pruned"
46973
      __m256i pruned = _mm256_shuffle_epi8(*this, shufmask);
46974
      // we still need to put the  pieces back together.
46975
      // we compute the popcount of the first words:
46976
      int pop1 = BitsSetTable256mul2[mask1];
46977
      int pop3 = BitsSetTable256mul2[mask3];
46978
46979
      // then load the corresponding mask
46980
      // could be done with _mm256_loadu2_m128i but many standard libraries omit this intrinsic.
46981
      __m256i v256 = _mm256_castsi128_si256(
46982
        _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop1 * 8)));
46983
      __m256i compactmask = _mm256_insertf128_si256(v256,
46984
         _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop3 * 8)), 1);
46985
      __m256i almostthere =  _mm256_shuffle_epi8(pruned, compactmask);
46986
      // We just need to write out the result.
46987
      // This is the tricky bit that is hard to do
46988
      // if we want to return a SIMD register, since there
46989
      // is no single-instruction approach to recombine
46990
      // the two 128-bit lanes with an offset.
46991
      __m128i v128;
46992
      v128 = _mm256_castsi256_si128(almostthere);
46993
      _mm_storeu_si128( reinterpret_cast<__m128i *>(output), v128);
46994
      v128 = _mm256_extractf128_si256(almostthere, 1);
46995
      _mm_storeu_si128( reinterpret_cast<__m128i *>(output + 16 - count_ones(mask & 0xFFFF)), v128);
46996
    }
46997
46998
    template<typename L>
46999
    simdjson_inline simd8<L> lookup_16(
47000
        L replace0,  L replace1,  L replace2,  L replace3,
47001
        L replace4,  L replace5,  L replace6,  L replace7,
47002
        L replace8,  L replace9,  L replace10, L replace11,
47003
        L replace12, L replace13, L replace14, L replace15) const {
47004
      return lookup_16(simd8<L>::repeat_16(
47005
        replace0,  replace1,  replace2,  replace3,
47006
        replace4,  replace5,  replace6,  replace7,
47007
        replace8,  replace9,  replace10, replace11,
47008
        replace12, replace13, replace14, replace15
47009
      ));
47010
    }
47011
  };
47012
47013
  // Signed bytes
47014
  template<>
47015
  struct simd8<int8_t> : base8_numeric<int8_t> {
47016
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
47017
    simdjson_inline simd8(const __m256i _value) : base8_numeric<int8_t>(_value) {}
47018
    // Splat constructor
47019
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
47020
    // Array constructor
47021
    simdjson_inline simd8(const int8_t values[32]) : simd8(load(values)) {}
47022
    // Member-by-member initialization
47023
    simdjson_inline simd8(
47024
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
47025
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15,
47026
      int8_t v16, int8_t v17, int8_t v18, int8_t v19, int8_t v20, int8_t v21, int8_t v22, int8_t v23,
47027
      int8_t v24, int8_t v25, int8_t v26, int8_t v27, int8_t v28, int8_t v29, int8_t v30, int8_t v31
47028
    ) : simd8(_mm256_setr_epi8(
47029
      v0, v1, v2, v3, v4, v5, v6, v7,
47030
      v8, v9, v10,v11,v12,v13,v14,v15,
47031
      v16,v17,v18,v19,v20,v21,v22,v23,
47032
      v24,v25,v26,v27,v28,v29,v30,v31
47033
    )) {}
47034
    // Repeat 16 values as many times as necessary (usually for lookup tables)
47035
    simdjson_inline static simd8<int8_t> repeat_16(
47036
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
47037
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
47038
    ) {
47039
      return simd8<int8_t>(
47040
        v0, v1, v2, v3, v4, v5, v6, v7,
47041
        v8, v9, v10,v11,v12,v13,v14,v15,
47042
        v0, v1, v2, v3, v4, v5, v6, v7,
47043
        v8, v9, v10,v11,v12,v13,v14,v15
47044
      );
47045
    }
47046
47047
    // Order-sensitive comparisons
47048
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm256_max_epi8(*this, other); }
47049
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm256_min_epi8(*this, other); }
47050
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm256_cmpgt_epi8(*this, other); }
47051
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm256_cmpgt_epi8(other, *this); }
47052
  };
47053
47054
  // Unsigned bytes
47055
  template<>
47056
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
47057
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
47058
    simdjson_inline simd8(const __m256i _value) : base8_numeric<uint8_t>(_value) {}
47059
    // Splat constructor
47060
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
47061
    // Array constructor
47062
    simdjson_inline simd8(const uint8_t values[32]) : simd8(load(values)) {}
47063
    // Member-by-member initialization
47064
    simdjson_inline simd8(
47065
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
47066
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15,
47067
      uint8_t v16, uint8_t v17, uint8_t v18, uint8_t v19, uint8_t v20, uint8_t v21, uint8_t v22, uint8_t v23,
47068
      uint8_t v24, uint8_t v25, uint8_t v26, uint8_t v27, uint8_t v28, uint8_t v29, uint8_t v30, uint8_t v31
47069
    ) : simd8(_mm256_setr_epi8(
47070
      v0, v1, v2, v3, v4, v5, v6, v7,
47071
      v8, v9, v10,v11,v12,v13,v14,v15,
47072
      v16,v17,v18,v19,v20,v21,v22,v23,
47073
      v24,v25,v26,v27,v28,v29,v30,v31
47074
    )) {}
47075
    // Repeat 16 values as many times as necessary (usually for lookup tables)
47076
    simdjson_inline static simd8<uint8_t> repeat_16(
47077
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
47078
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
47079
    ) {
47080
      return simd8<uint8_t>(
47081
        v0, v1, v2, v3, v4, v5, v6, v7,
47082
        v8, v9, v10,v11,v12,v13,v14,v15,
47083
        v0, v1, v2, v3, v4, v5, v6, v7,
47084
        v8, v9, v10,v11,v12,v13,v14,v15
47085
      );
47086
    }
47087
47088
    // Saturated math
47089
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm256_adds_epu8(*this, other); }
47090
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm256_subs_epu8(*this, other); }
47091
47092
    // Order-specific operations
47093
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm256_max_epu8(*this, other); }
47094
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm256_min_epu8(other, *this); }
47095
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
47096
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
47097
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
47098
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
47099
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
47100
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
47101
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
47102
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->lt_bits(other).any_bits_set(); }
47103
47104
    // Bit-specific operations
47105
    simdjson_inline simd8<bool> bits_not_set() const { return *this == uint8_t(0); }
47106
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
47107
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
47108
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
47109
    simdjson_inline bool is_ascii() const { return _mm256_movemask_epi8(*this) == 0; }
47110
    simdjson_inline bool bits_not_set_anywhere() const { return _mm256_testz_si256(*this, *this); }
47111
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
47112
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return _mm256_testz_si256(*this, bits); }
47113
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
47114
    template<int N>
47115
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm256_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
47116
    template<int N>
47117
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm256_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
47118
    // Get one of the bits and make a bitmask out of it.
47119
    // e.g. value.get_bit<7>() gets the high bit
47120
    template<int N>
47121
    simdjson_inline int get_bit() const { return _mm256_movemask_epi8(_mm256_slli_epi16(*this, 7-N)); }
47122
  };
47123
47124
  template<typename T>
47125
  struct simd8x64 {
47126
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
47127
    static_assert(NUM_CHUNKS == 2, "Haswell kernel should use two registers per 64-byte block.");
47128
    const simd8<T> chunks[NUM_CHUNKS];
47129
47130
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
47131
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
47132
    simd8x64() = delete; // no default constructor allowed
47133
47134
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1) : chunks{chunk0, chunk1} {}
47135
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+32)} {}
47136
47137
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
47138
      uint32_t mask1 = uint32_t(mask);
47139
      uint32_t mask2 = uint32_t(mask >> 32);
47140
      this->chunks[0].compress(mask1, output);
47141
      this->chunks[1].compress(mask2, output + 32 - count_ones(mask1));
47142
      return 64 - count_ones(mask);
47143
    }
47144
47145
    simdjson_inline void store(T ptr[64]) const {
47146
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
47147
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
47148
    }
47149
47150
    simdjson_inline uint64_t to_bitmask() const {
47151
      uint64_t r_lo = uint32_t(this->chunks[0].to_bitmask());
47152
      uint64_t r_hi =                       this->chunks[1].to_bitmask();
47153
      return r_lo | (r_hi << 32);
47154
    }
47155
47156
    simdjson_inline simd8<T> reduce_or() const {
47157
      return this->chunks[0] | this->chunks[1];
47158
    }
47159
47160
    simdjson_inline simd8x64<T> bit_or(const T m) const {
47161
      const simd8<T> mask = simd8<T>::splat(m);
47162
      return simd8x64<T>(
47163
        this->chunks[0] | mask,
47164
        this->chunks[1] | mask
47165
      );
47166
    }
47167
47168
    simdjson_inline uint64_t eq(const T m) const {
47169
      const simd8<T> mask = simd8<T>::splat(m);
47170
      return  simd8x64<bool>(
47171
        this->chunks[0] == mask,
47172
        this->chunks[1] == mask
47173
      ).to_bitmask();
47174
    }
47175
47176
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
47177
      return  simd8x64<bool>(
47178
        this->chunks[0] == other.chunks[0],
47179
        this->chunks[1] == other.chunks[1]
47180
      ).to_bitmask();
47181
    }
47182
47183
    simdjson_inline uint64_t lteq(const T m) const {
47184
      const simd8<T> mask = simd8<T>::splat(m);
47185
      return  simd8x64<bool>(
47186
        this->chunks[0] <= mask,
47187
        this->chunks[1] <= mask
47188
      ).to_bitmask();
47189
    }
47190
  }; // struct simd8x64<T>
47191
47192
} // namespace simd
47193
47194
} // unnamed namespace
47195
} // namespace haswell
47196
} // namespace simdjson
47197
47198
#endif // SIMDJSON_HASWELL_SIMD_H
47199
/* end file simdjson/haswell/simd.h */
47200
/* including simdjson/haswell/stringparsing_defs.h: #include "simdjson/haswell/stringparsing_defs.h" */
47201
/* begin file simdjson/haswell/stringparsing_defs.h */
47202
#ifndef SIMDJSON_HASWELL_STRINGPARSING_DEFS_H
47203
#define SIMDJSON_HASWELL_STRINGPARSING_DEFS_H
47204
47205
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
47206
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
47207
/* amalgamation skipped (editor-only): #include "simdjson/haswell/simd.h" */
47208
/* amalgamation skipped (editor-only): #include "simdjson/haswell/bitmanipulation.h" */
47209
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
47210
47211
namespace simdjson {
47212
namespace haswell {
47213
namespace {
47214
47215
using namespace simd;
47216
47217
// Holds backslashes and quotes locations.
47218
struct backslash_and_quote {
47219
public:
47220
  static constexpr uint32_t BYTES_PROCESSED = 32;
47221
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
47222
47223
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
47224
  simdjson_inline bool has_backslash() { return ((quote_bits - 1) & bs_bits) != 0; }
47225
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
47226
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
47227
47228
  uint32_t bs_bits;
47229
  uint32_t quote_bits;
47230
}; // struct backslash_and_quote
47231
47232
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
47233
  // this can read up to 15 bytes beyond the buffer size, but we require
47234
  // SIMDJSON_PADDING of padding
47235
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
47236
  simd8<uint8_t> v(src);
47237
  // store to dest unconditionally - we can overwrite the bits we don't like later
47238
  v.store(dst);
47239
  return {
47240
      static_cast<uint32_t>((v == '\\').to_bitmask()),     // bs_bits
47241
      static_cast<uint32_t>((v == '"').to_bitmask()), // quote_bits
47242
  };
47243
}
47244
47245
} // unnamed namespace
47246
} // namespace haswell
47247
} // namespace simdjson
47248
47249
#endif // SIMDJSON_HASWELL_STRINGPARSING_DEFS_H
47250
/* end file simdjson/haswell/stringparsing_defs.h */
47251
/* end file simdjson/haswell/begin.h */
47252
/* including simdjson/generic/ondemand/amalgamated.h for haswell: #include "simdjson/generic/ondemand/amalgamated.h" */
47253
/* begin file simdjson/generic/ondemand/amalgamated.h for haswell */
47254
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
47255
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
47256
#endif
47257
47258
// Stuff other things depend on
47259
/* including simdjson/generic/ondemand/base.h for haswell: #include "simdjson/generic/ondemand/base.h" */
47260
/* begin file simdjson/generic/ondemand/base.h for haswell */
47261
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
47262
47263
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
47264
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_BASE_H */
47265
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
47266
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
47267
47268
namespace simdjson {
47269
namespace haswell {
47270
/**
47271
 * A fast, simple, DOM-like interface that parses JSON as you use it.
47272
 *
47273
 * Designed for maximum speed and a lower memory profile.
47274
 */
47275
namespace ondemand {
47276
47277
/** Represents the depth of a JSON value (number of nested arrays/objects). */
47278
using depth_t = int32_t;
47279
47280
/** @copydoc simdjson::haswell::number_type */
47281
using number_type = simdjson::haswell::number_type;
47282
47283
/** @private Position in the JSON buffer indexes */
47284
using token_position = const uint32_t *;
47285
47286
class array;
47287
class array_iterator;
47288
class document;
47289
class document_reference;
47290
class document_stream;
47291
class field;
47292
class json_iterator;
47293
enum class json_type;
47294
struct number;
47295
class object;
47296
class object_iterator;
47297
class parser;
47298
class raw_json_string;
47299
class token_iterator;
47300
class value;
47301
class value_iterator;
47302
47303
} // namespace ondemand
47304
} // namespace haswell
47305
} // namespace simdjson
47306
47307
#endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H
47308
/* end file simdjson/generic/ondemand/base.h for haswell */
47309
/* including simdjson/generic/ondemand/value_iterator.h for haswell: #include "simdjson/generic/ondemand/value_iterator.h" */
47310
/* begin file simdjson/generic/ondemand/value_iterator.h for haswell */
47311
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
47312
47313
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
47314
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H */
47315
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
47316
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
47317
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
47318
47319
namespace simdjson {
47320
namespace haswell {
47321
namespace ondemand {
47322
47323
/**
47324
 * Iterates through a single JSON value at a particular depth.
47325
 *
47326
 * Does not keep track of the type of value: provides methods for objects, arrays and scalars and expects
47327
 * the caller to call the right ones.
47328
 *
47329
 * @private This is not intended for external use.
47330
 */
47331
class value_iterator {
47332
protected:
47333
  /** The underlying JSON iterator */
47334
  json_iterator *_json_iter{};
47335
  /** The depth of this value */
47336
  depth_t _depth{};
47337
  /**
47338
   * The starting token index for this value
47339
   */
47340
  token_position _start_position{};
47341
47342
public:
47343
  simdjson_inline value_iterator() noexcept = default;
47344
47345
  /**
47346
   * Denote that we're starting a document.
47347
   */
47348
  simdjson_inline void start_document() noexcept;
47349
47350
  /**
47351
   * Skips a non-iterated or partially-iterated JSON value, whether it is a scalar, array or object.
47352
   *
47353
   * Optimized for scalars.
47354
   */
47355
  simdjson_warn_unused simdjson_inline error_code skip_child() noexcept;
47356
47357
  /**
47358
   * Tell whether the iterator is at the EOF mark
47359
   */
47360
  simdjson_inline bool at_end() const noexcept;
47361
47362
  /**
47363
   * Tell whether the iterator is at the start of the value
47364
   */
47365
  simdjson_inline bool at_start() const noexcept;
47366
47367
  /**
47368
   * Tell whether the value is open--if the value has not been used, or the array/object is still open.
47369
   */
47370
  simdjson_inline bool is_open() const noexcept;
47371
47372
  /**
47373
   * Tell whether the value is at an object's first field (just after the {).
47374
   */
47375
  simdjson_inline bool at_first_field() const noexcept;
47376
47377
  /**
47378
   * Abandon all iteration.
47379
   */
47380
  simdjson_inline void abandon() noexcept;
47381
47382
  /**
47383
   * Get the child value as a value_iterator.
47384
   */
47385
  simdjson_inline value_iterator child_value() const noexcept;
47386
47387
  /**
47388
   * Get the depth of this value.
47389
   */
47390
  simdjson_inline int32_t depth() const noexcept;
47391
47392
  /**
47393
   * Get the JSON type of this value.
47394
   *
47395
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
47396
   */
47397
  simdjson_inline simdjson_result<json_type> type() const noexcept;
47398
47399
  /**
47400
   * @addtogroup object Object iteration
47401
   *
47402
   * Methods to iterate and find object fields. These methods generally *assume* the value is
47403
   * actually an object; the caller is responsible for keeping track of that fact.
47404
   *
47405
   * @{
47406
   */
47407
47408
  /**
47409
   * Start an object iteration.
47410
   *
47411
   * @returns Whether the object had any fields (returns false for empty).
47412
   * @error INCORRECT_TYPE if there is no opening {
47413
   */
47414
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_object() noexcept;
47415
  /**
47416
   * Start an object iteration from the root.
47417
   *
47418
   * @returns Whether the object had any fields (returns false for empty).
47419
   * @error INCORRECT_TYPE if there is no opening {
47420
   * @error TAPE_ERROR if there is no matching } at end of document
47421
   */
47422
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_object() noexcept;
47423
  /**
47424
   * Checks whether an object could be started from the root. May be called by start_root_object.
47425
   *
47426
   * @returns SUCCESS if it is possible to safely start an object from the root (document level).
47427
   * @error INCORRECT_TYPE if there is no opening {
47428
   * @error TAPE_ERROR if there is no matching } at end of document
47429
   */
47430
  simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept;
47431
  /**
47432
   * Start an object iteration after the user has already checked and moved past the {.
47433
   *
47434
   * Does not move the iterator unless the object is empty ({}).
47435
   *
47436
   * @returns Whether the object had any fields (returns false for empty).
47437
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
47438
   *        array or object is incomplete).
47439
   */
47440
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_object() noexcept;
47441
  /**
47442
   * Start an object iteration from the root, after the user has already checked and moved past the {.
47443
   *
47444
   * Does not move the iterator unless the object is empty ({}).
47445
   *
47446
   * @returns Whether the object had any fields (returns false for empty).
47447
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
47448
   *        array or object is incomplete).
47449
   */
47450
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_object() noexcept;
47451
47452
  /**
47453
   * Moves to the next field in an object.
47454
   *
47455
   * Looks for , and }. If } is found, the object is finished and the iterator advances past it.
47456
   * Otherwise, it advances to the next value.
47457
   *
47458
   * @return whether there is another field in the object.
47459
   * @error TAPE_ERROR If there is a comma missing between fields.
47460
   * @error TAPE_ERROR If there is a comma, but not enough tokens remaining to have a key, :, and value.
47461
   */
47462
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_field() noexcept;
47463
47464
  /**
47465
   * Get the current field's key.
47466
   */
47467
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> field_key() noexcept;
47468
47469
  /**
47470
   * Pass the : in the field and move to its value.
47471
   */
47472
  simdjson_warn_unused simdjson_inline error_code field_value() noexcept;
47473
47474
  /**
47475
   * Find the next field with the given key.
47476
   *
47477
   * Assumes you have called next_field() or otherwise matched the previous value.
47478
   *
47479
   * This means the iterator must be sitting at the next key:
47480
   *
47481
   * ```
47482
   * { "a": 1, "b": 2 }
47483
   *           ^
47484
   * ```
47485
   *
47486
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
47487
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
47488
   * fail to match some keys with escapes (\u, \n, etc.).
47489
   */
47490
  simdjson_warn_unused simdjson_inline error_code find_field(const std::string_view key) noexcept;
47491
47492
  /**
47493
   * Find the next field with the given key, *without* unescaping. This assumes object order: it
47494
   * will not find the field if it was already passed when looking for some *other* field.
47495
   *
47496
   * Assumes you have called next_field() or otherwise matched the previous value.
47497
   *
47498
   * This means the iterator must be sitting at the next key:
47499
   *
47500
   * ```
47501
   * { "a": 1, "b": 2 }
47502
   *           ^
47503
   * ```
47504
   *
47505
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
47506
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
47507
   * fail to match some keys with escapes (\u, \n, etc.).
47508
   */
47509
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
47510
47511
  /**
47512
   * Find the field with the given key without regard to order, and *without* unescaping.
47513
   *
47514
   * This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
47515
   *
47516
   * Assumes you have called next_field() or otherwise matched the previous value.
47517
   *
47518
   * This means the iterator must be sitting at the next key:
47519
   *
47520
   * ```
47521
   * { "a": 1, "b": 2 }
47522
   *           ^
47523
   * ```
47524
   *
47525
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
47526
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
47527
   * fail to match some keys with escapes (\u, \n, etc.).
47528
   */
47529
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
47530
47531
  /** @} */
47532
47533
  /**
47534
   * @addtogroup array Array iteration
47535
   * Methods to iterate over array elements. These methods generally *assume* the value is actually
47536
   * an object; the caller is responsible for keeping track of that fact.
47537
   * @{
47538
   */
47539
47540
  /**
47541
   * Check for an opening [ and start an array iteration.
47542
   *
47543
   * @returns Whether the array had any elements (returns false for empty).
47544
   * @error INCORRECT_TYPE If there is no [.
47545
   */
47546
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_array() noexcept;
47547
  /**
47548
   * Check for an opening [ and start an array iteration while at the root.
47549
   *
47550
   * @returns Whether the array had any elements (returns false for empty).
47551
   * @error INCORRECT_TYPE If there is no [.
47552
   * @error TAPE_ERROR if there is no matching ] at end of document
47553
   */
47554
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_array() noexcept;
47555
  /**
47556
   * Checks whether an array could be started from the root. May be called by start_root_array.
47557
   *
47558
   * @returns SUCCESS if it is possible to safely start an array from the root (document level).
47559
   * @error INCORRECT_TYPE If there is no [.
47560
   * @error TAPE_ERROR if there is no matching ] at end of document
47561
   */
47562
  simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept;
47563
  /**
47564
   * Start an array iteration, after the user has already checked and moved past the [.
47565
   *
47566
   * Does not move the iterator unless the array is empty ([]).
47567
   *
47568
   * @returns Whether the array had any elements (returns false for empty).
47569
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
47570
   *        array or object is incomplete).
47571
   */
47572
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_array() noexcept;
47573
  /**
47574
   * Start an array iteration from the root, after the user has already checked and moved past the [.
47575
   *
47576
   * Does not move the iterator unless the array is empty ([]).
47577
   *
47578
   * @returns Whether the array had any elements (returns false for empty).
47579
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
47580
   *        array or object is incomplete).
47581
   */
47582
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_array() noexcept;
47583
47584
  /**
47585
   * Moves to the next element in an array.
47586
   *
47587
   * Looks for , and ]. If ] is found, the array is finished and the iterator advances past it.
47588
   * Otherwise, it advances to the next value.
47589
   *
47590
   * @return Whether there is another element in the array.
47591
   * @error TAPE_ERROR If there is a comma missing between elements.
47592
   */
47593
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_element() noexcept;
47594
47595
  /**
47596
   * Get a child value iterator.
47597
   */
47598
  simdjson_warn_unused simdjson_inline value_iterator child() const noexcept;
47599
47600
  /** @} */
47601
47602
  /**
47603
   * @defgroup scalar Scalar values
47604
   * @addtogroup scalar
47605
   * @{
47606
   */
47607
47608
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
47609
  template <typename string_type>
47610
  simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
47611
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
47612
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
47613
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
47614
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
47615
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
47616
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
47617
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
47618
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
47619
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
47620
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
47621
  simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
47622
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
47623
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
47624
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
47625
47626
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
47627
  template <typename string_type>
47628
  simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
47629
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
47630
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
47631
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
47632
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
47633
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
47634
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
47635
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
47636
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
47637
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
47638
  simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
47639
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
47640
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
47641
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
47642
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
47643
47644
  simdjson_inline error_code error() const noexcept;
47645
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
47646
  simdjson_inline const json_iterator &json_iter() const noexcept;
47647
  simdjson_inline json_iterator &json_iter() noexcept;
47648
47649
  simdjson_inline void assert_is_valid() const noexcept;
47650
  simdjson_inline bool is_valid() const noexcept;
47651
47652
  /** @} */
47653
protected:
47654
  /**
47655
   * Restarts an array iteration.
47656
   * @returns Whether the array has any elements (returns false for empty).
47657
   */
47658
  simdjson_inline simdjson_result<bool> reset_array() noexcept;
47659
  /**
47660
   * Restarts an object iteration.
47661
   * @returns Whether the object has any fields (returns false for empty).
47662
   */
47663
  simdjson_inline simdjson_result<bool> reset_object() noexcept;
47664
  /**
47665
   * move_at_start(): moves us so that we are pointing at the beginning of
47666
   * the container. It updates the index so that at_start() is true and it
47667
   * syncs the depth. The user can then create a new container instance.
47668
   *
47669
   * Usage: used with value::count_elements().
47670
   **/
47671
  simdjson_inline void move_at_start() noexcept;
47672
47673
  /**
47674
   * move_at_container_start(): moves us so that we are pointing at the beginning of
47675
   * the container so that assert_at_container_start() passes.
47676
   *
47677
   * Usage: used with reset_array() and reset_object().
47678
   **/
47679
   simdjson_inline void move_at_container_start() noexcept;
47680
  /* Useful for debugging and logging purposes. */
47681
  inline std::string to_string() const noexcept;
47682
  simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
47683
47684
  simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
47685
  simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
47686
  simdjson_inline const uint8_t *peek_start() const noexcept;
47687
  simdjson_inline uint32_t peek_start_length() const noexcept;
47688
  simdjson_inline uint32_t peek_root_length() const noexcept;
47689
47690
  /**
47691
   * The general idea of the advance_... methods and the peek_* methods
47692
   * is that you first peek and check that you have desired type. If you do,
47693
   * and only if you do, then you advance.
47694
   *
47695
   * We used to unconditionally advance. But this made reasoning about our
47696
   * current state difficult.
47697
   * Suppose you always advance. Look at the 'value' matching the key
47698
   * "shadowable" in the following example...
47699
   *
47700
   * ({"globals":{"a":{"shadowable":[}}}})
47701
   *
47702
   * If the user thinks it is a Boolean and asks for it, then we check the '[',
47703
   * decide it is not a Boolean, but still move into the next character ('}'). Now
47704
   * we are left pointing at '}' right after a '['. And we have not yet reported
47705
   * an error, only that we do not have a Boolean.
47706
   *
47707
   * If, instead, you just stand your ground until it is content that you know, then
47708
   * you will only even move beyond the '[' if the user tells you that you have an
47709
   * array. So you will be at the '}' character inside the array and, hopefully, you
47710
   * will then catch the error because an array cannot start with '}', but the code
47711
   * processing Boolean values does not know this.
47712
   *
47713
   * So the contract is: first call 'peek_...' and then call 'advance_...' only
47714
   * if you have determined that it is a type you can handle.
47715
   *
47716
   * Unfortunately, it makes the code more verbose, longer and maybe more error prone.
47717
   */
47718
47719
  simdjson_inline void advance_scalar(const char *type) noexcept;
47720
  simdjson_inline void advance_root_scalar(const char *type) noexcept;
47721
  simdjson_inline void advance_non_root_scalar(const char *type) noexcept;
47722
47723
  simdjson_inline const uint8_t *peek_scalar(const char *type) noexcept;
47724
  simdjson_inline const uint8_t *peek_root_scalar(const char *type) noexcept;
47725
  simdjson_inline const uint8_t *peek_non_root_scalar(const char *type) noexcept;
47726
47727
47728
  simdjson_inline error_code start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept;
47729
  simdjson_inline error_code end_container() noexcept;
47730
47731
  /**
47732
   * Advance to a place expecting a value (increasing depth).
47733
   *
47734
   * @return The current token (the one left behind).
47735
   * @error TAPE_ERROR If the document ended early.
47736
   */
47737
  simdjson_inline simdjson_result<const uint8_t *> advance_to_value() noexcept;
47738
47739
  simdjson_inline error_code incorrect_type_error(const char *message) const noexcept;
47740
  simdjson_inline error_code error_unless_more_tokens(uint32_t tokens=1) const noexcept;
47741
47742
  simdjson_inline bool is_at_start() const noexcept;
47743
  /**
47744
   * is_at_iterator_start() returns true on an array or object after it has just been
47745
   * created, whether the instance is empty or not.
47746
   *
47747
   * Usage: used by array::begin() in debug mode (SIMDJSON_DEVELOPMENT_CHECKS)
47748
   */
47749
  simdjson_inline bool is_at_iterator_start() const noexcept;
47750
47751
  /**
47752
   * Assuming that we are within an object, this returns true if we
47753
   * are pointing at a key.
47754
   *
47755
   * Usage: the skip_child() method should never be used while we are pointing
47756
   * at a key inside an object.
47757
   */
47758
  simdjson_inline bool is_at_key() const noexcept;
47759
47760
  inline void assert_at_start() const noexcept;
47761
  inline void assert_at_container_start() const noexcept;
47762
  inline void assert_at_root() const noexcept;
47763
  inline void assert_at_child() const noexcept;
47764
  inline void assert_at_next() const noexcept;
47765
  inline void assert_at_non_root_start() const noexcept;
47766
47767
  /** Get the starting position of this value */
47768
  simdjson_inline token_position start_position() const noexcept;
47769
47770
  /** @copydoc error_code json_iterator::position() const noexcept; */
47771
  simdjson_inline token_position position() const noexcept;
47772
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
47773
  simdjson_inline token_position last_position() const noexcept;
47774
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
47775
  simdjson_inline token_position end_position() const noexcept;
47776
  /** @copydoc error_code json_iterator::report_error(error_code error, const char *message) noexcept; */
47777
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
47778
47779
  friend class document;
47780
  friend class object;
47781
  friend class array;
47782
  friend class value;
47783
  friend class field;
47784
}; // value_iterator
47785
47786
} // namespace ondemand
47787
} // namespace haswell
47788
} // namespace simdjson
47789
47790
namespace simdjson {
47791
47792
template<>
47793
struct simdjson_result<haswell::ondemand::value_iterator> : public haswell::implementation_simdjson_result_base<haswell::ondemand::value_iterator> {
47794
public:
47795
  simdjson_inline simdjson_result(haswell::ondemand::value_iterator &&value) noexcept; ///< @private
47796
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
47797
  simdjson_inline simdjson_result() noexcept = default;
47798
};
47799
47800
} // namespace simdjson
47801
47802
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
47803
/* end file simdjson/generic/ondemand/value_iterator.h for haswell */
47804
/* including simdjson/generic/ondemand/value.h for haswell: #include "simdjson/generic/ondemand/value.h" */
47805
/* begin file simdjson/generic/ondemand/value.h for haswell */
47806
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H
47807
47808
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
47809
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_H */
47810
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
47811
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
47812
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
47813
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
47814
47815
namespace simdjson {
47816
namespace haswell {
47817
namespace ondemand {
47818
47819
/**
47820
 * An ephemeral JSON value returned during iteration. It is only valid for as long as you do
47821
 * not access more data in the JSON document.
47822
 */
47823
class value {
47824
public:
47825
  /**
47826
   * Create a new invalid value.
47827
   *
47828
   * Exists so you can declare a variable and later assign to it before use.
47829
   */
47830
  simdjson_inline value() noexcept = default;
47831
47832
  /**
47833
   * Get this value as the given type.
47834
   *
47835
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
47836
   *
47837
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
47838
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
47839
   *
47840
   * @returns A value of the given type, parsed from the JSON.
47841
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
47842
   */
47843
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
47844
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
47845
    // immediately fail.
47846
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
47847
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
47848
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
47849
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
47850
      " You may also add support for custom types, see our documentation.");
47851
  }
47852
47853
  /**
47854
   * Get this value as the given type.
47855
   *
47856
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
47857
   *
47858
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
47859
   * @returns INCORRECT_TYPE If the JSON value is not an object.
47860
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
47861
   */
47862
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
47863
47864
  /**
47865
   * Cast this JSON value to an array.
47866
   *
47867
   * @returns An object that can be used to iterate the array.
47868
   * @returns INCORRECT_TYPE If the JSON value is not an array.
47869
   */
47870
  simdjson_inline simdjson_result<array> get_array() noexcept;
47871
47872
  /**
47873
   * Cast this JSON value to an object.
47874
   *
47875
   * @returns An object that can be used to look up or iterate fields.
47876
   * @returns INCORRECT_TYPE If the JSON value is not an object.
47877
   */
47878
  simdjson_inline simdjson_result<object> get_object() noexcept;
47879
47880
  /**
47881
   * Cast this JSON value to an unsigned integer.
47882
   *
47883
   * @returns A unsigned 64-bit integer.
47884
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
47885
   */
47886
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
47887
47888
  /**
47889
   * Cast this JSON value (inside string) to a unsigned integer.
47890
   *
47891
   * @returns A unsigned 64-bit integer.
47892
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
47893
   */
47894
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
47895
47896
  /**
47897
   * Cast this JSON value to a signed integer.
47898
   *
47899
   * @returns A signed 64-bit integer.
47900
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
47901
   */
47902
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
47903
47904
  /**
47905
   * Cast this JSON value (inside string) to a signed integer.
47906
   *
47907
   * @returns A signed 64-bit integer.
47908
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
47909
   */
47910
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
47911
47912
  /**
47913
   * Cast this JSON value to a double.
47914
   *
47915
   * @returns A double.
47916
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
47917
   */
47918
  simdjson_inline simdjson_result<double> get_double() noexcept;
47919
47920
  /**
47921
   * Cast this JSON value (inside string) to a double
47922
   *
47923
   * @returns A double.
47924
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
47925
   */
47926
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
47927
47928
  /**
47929
   * Cast this JSON value to a string.
47930
   *
47931
   * The string is guaranteed to be valid UTF-8.
47932
   *
47933
   * Equivalent to get<std::string_view>().
47934
   *
47935
   * Important: a value should be consumed once. Calling get_string() twice on the same value
47936
   * is an error.
47937
   *
47938
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
47939
   *          time it parses a document or when it is destroyed.
47940
   * @returns INCORRECT_TYPE if the JSON value is not a string.
47941
   */
47942
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
47943
47944
  /**
47945
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
47946
   *
47947
   * The string is guaranteed to be valid UTF-8.
47948
   *
47949
   * Important: a value should be consumed once. Calling get_string() twice on the same value
47950
   * is an error.
47951
   *
47952
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
47953
   * We recommend you avoid allocating an std::string unless you need to.
47954
   *
47955
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
47956
   */
47957
  template <typename string_type>
47958
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
47959
47960
  /**
47961
   * Cast this JSON value to a "wobbly" string.
47962
   *
47963
   * The string is may not be a valid UTF-8 string.
47964
   * See https://simonsapin.github.io/wtf-8/
47965
   *
47966
   * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value
47967
   * is an error.
47968
   *
47969
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
47970
   *          time it parses a document or when it is destroyed.
47971
   * @returns INCORRECT_TYPE if the JSON value is not a string.
47972
   */
47973
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
47974
  /**
47975
   * Cast this JSON value to a raw_json_string.
47976
   *
47977
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
47978
   *
47979
   * @returns A pointer to the raw JSON for the given string.
47980
   * @returns INCORRECT_TYPE if the JSON value is not a string.
47981
   */
47982
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
47983
47984
  /**
47985
   * Cast this JSON value to a bool.
47986
   *
47987
   * @returns A bool value.
47988
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
47989
   */
47990
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
47991
47992
  /**
47993
   * Checks if this JSON value is null. If and only if the value is
47994
   * null, then it is consumed (we advance). If we find a token that
47995
   * begins with 'n' but is not 'null', then an error is returned.
47996
   *
47997
   * @returns Whether the value is null.
47998
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
47999
   */
48000
  simdjson_inline simdjson_result<bool> is_null() noexcept;
48001
48002
#if SIMDJSON_EXCEPTIONS
48003
  /**
48004
   * Cast this JSON value to an instance of type T. The programmer is responsible for
48005
   * providing an implementation of get<T> for the type T, if T is not one of the types
48006
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.).
48007
   *
48008
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
48009
   *
48010
   * @returns An instance of type T
48011
   */
48012
  template <class T>
48013
  explicit simdjson_inline operator T() noexcept(false);
48014
  /**
48015
   * Cast this JSON value to an array.
48016
   *
48017
   * @returns An object that can be used to iterate the array.
48018
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
48019
   */
48020
  simdjson_inline operator array() noexcept(false);
48021
  /**
48022
   * Cast this JSON value to an object.
48023
   *
48024
   * @returns An object that can be used to look up or iterate fields.
48025
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
48026
   */
48027
  simdjson_inline operator object() noexcept(false);
48028
  /**
48029
   * Cast this JSON value to an unsigned integer.
48030
   *
48031
   * @returns A signed 64-bit integer.
48032
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
48033
   */
48034
  simdjson_inline operator uint64_t() noexcept(false);
48035
  /**
48036
   * Cast this JSON value to a signed integer.
48037
   *
48038
   * @returns A signed 64-bit integer.
48039
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
48040
   */
48041
  simdjson_inline operator int64_t() noexcept(false);
48042
  /**
48043
   * Cast this JSON value to a double.
48044
   *
48045
   * @returns A double.
48046
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
48047
   */
48048
  simdjson_inline operator double() noexcept(false);
48049
  /**
48050
   * Cast this JSON value to a string.
48051
   *
48052
   * The string is guaranteed to be valid UTF-8.
48053
   *
48054
   * Equivalent to get<std::string_view>().
48055
   *
48056
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
48057
   *          time it parses a document or when it is destroyed.
48058
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
48059
   */
48060
  simdjson_inline operator std::string_view() noexcept(false);
48061
  /**
48062
   * Cast this JSON value to a raw_json_string.
48063
   *
48064
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
48065
   *
48066
   * @returns A pointer to the raw JSON for the given string.
48067
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
48068
   */
48069
  simdjson_inline operator raw_json_string() noexcept(false);
48070
  /**
48071
   * Cast this JSON value to a bool.
48072
   *
48073
   * @returns A bool value.
48074
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
48075
   */
48076
  simdjson_inline operator bool() noexcept(false);
48077
#endif
48078
48079
  /**
48080
   * Begin array iteration.
48081
   *
48082
   * Part of the std::iterable interface.
48083
   *
48084
   * @returns INCORRECT_TYPE If the JSON value is not an array.
48085
   */
48086
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
48087
  /**
48088
   * Sentinel representing the end of the array.
48089
   *
48090
   * Part of the std::iterable interface.
48091
   */
48092
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
48093
  /**
48094
   * This method scans the array and counts the number of elements.
48095
   * The count_elements method should always be called before you have begun
48096
   * iterating through the array: it is expected that you are pointing at
48097
   * the beginning of the array.
48098
   * The runtime complexity is linear in the size of the array. After
48099
   * calling this function, if successful, the array is 'rewinded' at its
48100
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
48101
   * there is a missing comma), then an error is returned and it is no longer
48102
   * safe to continue.
48103
   *
48104
   * Performance hint: You should only call count_elements() as a last
48105
   * resort as it may require scanning the document twice or more.
48106
   */
48107
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
48108
  /**
48109
   * This method scans the object and counts the number of key-value pairs.
48110
   * The count_fields method should always be called before you have begun
48111
   * iterating through the object: it is expected that you are pointing at
48112
   * the beginning of the object.
48113
   * The runtime complexity is linear in the size of the object. After
48114
   * calling this function, if successful, the object is 'rewinded' at its
48115
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
48116
   * there is a missing comma), then an error is returned and it is no longer
48117
   * safe to continue.
48118
   *
48119
   * To check that an object is empty, it is more performant to use
48120
   * the is_empty() method on the object instance.
48121
   *
48122
   * Performance hint: You should only call count_fields() as a last
48123
   * resort as it may require scanning the document twice or more.
48124
   */
48125
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
48126
  /**
48127
   * Get the value at the given index in the array. This function has linear-time complexity.
48128
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
48129
   *
48130
   * @return The value at the given index, or:
48131
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
48132
   */
48133
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
48134
  /**
48135
   * Look up a field by name on an object (order-sensitive).
48136
   *
48137
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
48138
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
48139
   *
48140
   * ```c++
48141
   * simdjson::ondemand::parser parser;
48142
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
48143
   * double z = obj.find_field("z");
48144
   * double y = obj.find_field("y");
48145
   * double x = obj.find_field("x");
48146
   * ```
48147
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
48148
   * that only one field is returned.
48149
48150
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
48151
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
48152
   *
48153
   * @param key The key to look up.
48154
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
48155
   */
48156
  simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept;
48157
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
48158
  simdjson_inline simdjson_result<value> find_field(const char *key) noexcept;
48159
48160
  /**
48161
   * Look up a field by name on an object, without regard to key order.
48162
   *
48163
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
48164
   * and often appears negligible. It starts out normally, starting out at the last field; but if
48165
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
48166
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
48167
   * in question is large. The fact that the extra code is there also bumps the executable size.
48168
   *
48169
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
48170
   * default behavior failed to look up a field just because it was in the wrong order--and many
48171
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
48172
   *
48173
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
48174
   * that only one field is returned.
48175
   *
48176
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
48177
   * field as not there when they are not in order).
48178
   *
48179
   * @param key The key to look up.
48180
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
48181
   */
48182
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
48183
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
48184
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
48185
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
48186
  simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept;
48187
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
48188
  simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
48189
48190
  /**
48191
   * Get the type of this JSON value. It does not validate or consume the value.
48192
   * E.g., you must still call "is_null()" to check that a value is null even if
48193
   * "type()" returns json_type::null.
48194
   *
48195
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
48196
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
48197
   * let it throw an exception).
48198
   *
48199
   * @return The type of JSON value (json_type::array, json_type::object, json_type::string,
48200
   *     json_type::number, json_type::boolean, or json_type::null).
48201
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
48202
   */
48203
  simdjson_inline simdjson_result<json_type> type() noexcept;
48204
48205
  /**
48206
   * Checks whether the value is a scalar (string, number, null, Boolean).
48207
   * Returns false when there it is an array or object.
48208
   *
48209
   * @returns true if the type is string, number, null, Boolean
48210
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
48211
   */
48212
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
48213
  /**
48214
   * Checks whether the value is a string.
48215
   *
48216
   * @returns true if the type is string
48217
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
48218
   */
48219
  simdjson_inline simdjson_result<bool> is_string() noexcept;
48220
48221
  /**
48222
   * Checks whether the value is a negative number.
48223
   *
48224
   * @returns true if the number if negative.
48225
   */
48226
  simdjson_inline bool is_negative() noexcept;
48227
  /**
48228
   * Checks whether the value is an integer number. Note that
48229
   * this requires to partially parse the number string. If
48230
   * the value is determined to be an integer, it may still
48231
   * not parse properly as an integer in subsequent steps
48232
   * (e.g., it might overflow).
48233
   *
48234
   * Performance note: if you call this function systematically
48235
   * before parsing a number, you may have fallen for a performance
48236
   * anti-pattern.
48237
   *
48238
   * @returns true if the number if negative.
48239
   */
48240
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
48241
  /**
48242
   * Determine the number type (integer or floating-point number) as quickly
48243
   * as possible. This function does not fully validate the input. It is
48244
   * useful when you only need to classify the numbers, without parsing them.
48245
   *
48246
   * If you are planning to retrieve the value or you need full validation,
48247
   * consider using the get_number() method instead: it will fully parse
48248
   * and validate the input, and give you access to the type:
48249
   * get_number().get_number_type().
48250
   *
48251
   * get_number_type() is number_type::unsigned_integer if we have
48252
   * an integer greater or equal to 9223372036854775808.
48253
   * get_number_type() is number_type::signed_integer if we have an
48254
   * integer that is less than 9223372036854775808.
48255
   * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits,
48256
   * in which case the digit_count is set to the length of the big integer string.
48257
   * Otherwise, get_number_type() has value number_type::floating_point_number.
48258
   *
48259
   * This function requires processing the number string, but it is expected
48260
   * to be faster than get_number().get_number_type() because it is does not
48261
   * parse the number value.
48262
   *
48263
   * @returns the type of the number
48264
   */
48265
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
48266
48267
  /**
48268
   * Attempt to parse an ondemand::number. An ondemand::number may
48269
   * contain an integer value or a floating-point value, the simdjson
48270
   * library will autodetect the type. Thus it is a dynamically typed
48271
   * number. Before accessing the value, you must determine the detected
48272
   * type.
48273
   *
48274
   * number.get_number_type() is number_type::signed_integer if we have
48275
   * an integer in [-9223372036854775808,9223372036854775808)
48276
   * You can recover the value by calling number.get_int64() and you
48277
   * have that number.is_int64() is true.
48278
   *
48279
   * number.get_number_type() is number_type::unsigned_integer if we have
48280
   * an integer in [9223372036854775808,18446744073709551616)
48281
   * You can recover the value by calling number.get_uint64() and you
48282
   * have that number.is_uint64() is true.
48283
   *
48284
   * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code.
48285
   *
48286
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
48287
   * and we have a binary64 number.
48288
   * You can recover the value by calling number.get_double() and you
48289
   * have that number.is_double() is true.
48290
   *
48291
   * You must check the type before accessing the value: it is an error
48292
   * to call "get_int64()" when number.get_number_type() is not
48293
   * number_type::signed_integer and when number.is_int64() is false.
48294
   *
48295
   * Performance note: this is designed with performance in mind. When
48296
   * calling 'get_number()', you scan the number string only once, determining
48297
   * efficiently the type and storing it in an efficient manner.
48298
   */
48299
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
48300
48301
  /**
48302
   * Get the raw JSON for this token.
48303
   *
48304
   * The string_view will always point into the input buffer.
48305
   *
48306
   * The string_view will start at the beginning of the token, and include the entire token
48307
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
48308
   * string token always begins with a " and is always terminated by the final ", possibly
48309
   * followed by a number of spaces.
48310
   *
48311
   * The string_view is *not* null-terminated. However, if this is a scalar (string, number,
48312
   * boolean, or null), the character after the end of the string_view is guaranteed to be
48313
   * a non-space token.
48314
   *
48315
   * Tokens include:
48316
   * - {
48317
   * - [
48318
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
48319
   * - -1.2e-100
48320
   * - true
48321
   * - false
48322
   * - null
48323
   *
48324
   * See also value::raw_json().
48325
   */
48326
  simdjson_inline std::string_view raw_json_token() noexcept;
48327
48328
  /**
48329
   * Get a string_view pointing at this value in the JSON document.
48330
   * If this element is an array or an object, it consumes the array or the object
48331
   * and returns a string_view instance corresponding to the
48332
   * array as represented in JSON. It points inside the original document.
48333
   * If this element is a scalar (string, number, Boolean, null), it returns what
48334
   * raw_json_token() would return.
48335
   */
48336
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
48337
48338
  /**
48339
   * Returns the current location in the document if in bounds.
48340
   */
48341
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
48342
48343
  /**
48344
   * Returns the current depth in the document if in bounds.
48345
   *
48346
   * E.g.,
48347
   *  0 = finished with document
48348
   *  1 = document root value (could be [ or {, not yet known)
48349
   *  2 = , or } inside root array/object
48350
   *  3 = key or value inside root array/object.
48351
   */
48352
  simdjson_inline int32_t current_depth() const noexcept;
48353
48354
  /**
48355
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
48356
   * https://tools.ietf.org/html/rfc6901 standard.
48357
   *
48358
   *   ondemand::parser parser;
48359
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
48360
   *   auto doc = parser.iterate(json);
48361
   *   doc.at_pointer("/foo/a/1") == 20
48362
   *
48363
   * It is allowed for a key to be the empty string:
48364
   *
48365
   *   ondemand::parser parser;
48366
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
48367
   *   auto doc = parser.iterate(json);
48368
   *   doc.at_pointer("//a/1") == 20
48369
   *
48370
   * Note that at_pointer() called on the document automatically calls the document's rewind
48371
   * method between each call. It invalidates all previously accessed arrays, objects and values
48372
   * that have not been consumed.
48373
   *
48374
   * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not
48375
   * standardized (by RFC 6901). We provide some experimental support for JSON pointers
48376
   * on non-document instances.  Yet it is not the case when calling at_pointer on an array
48377
   * or an object instance: there is no rewind and no invalidation.
48378
   *
48379
   * You may only call at_pointer on an array after it has been created, but before it has
48380
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
48381
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
48382
   * to call at_pointer on the same array.
48383
   *
48384
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
48385
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
48386
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
48387
   *
48388
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
48389
   *
48390
   * @return The value associated with the given JSON pointer, or:
48391
   *         - NO_SUCH_FIELD if a field does not exist in an object
48392
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
48393
   *         - INCORRECT_TYPE if a non-integer is used to access an array
48394
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
48395
   */
48396
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
48397
48398
  /**
48399
   * Get the value associated with the given JSONPath expression. We only support
48400
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
48401
   * names and array indices.
48402
   *
48403
   * @return The value associated with the given JSONPath expression, or:
48404
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
48405
   *         - NO_SUCH_FIELD if a field does not exist in an object
48406
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
48407
   *         - INCORRECT_TYPE if a non-integer is used to access an array
48408
   */
48409
  simdjson_inline simdjson_result<value> at_path(std::string_view at_path) noexcept;
48410
48411
48412
protected:
48413
  /**
48414
   * Create a value.
48415
   */
48416
  simdjson_inline value(const value_iterator &iter) noexcept;
48417
48418
  /**
48419
   * Skip this value, allowing iteration to continue.
48420
   */
48421
  simdjson_inline void skip() noexcept;
48422
48423
  /**
48424
   * Start a value at the current position.
48425
   *
48426
   * (It should already be started; this is just a self-documentation method.)
48427
   */
48428
  static simdjson_inline value start(const value_iterator &iter) noexcept;
48429
48430
  /**
48431
   * Resume a value.
48432
   */
48433
  static simdjson_inline value resume(const value_iterator &iter) noexcept;
48434
48435
  /**
48436
   * Get the object, starting or resuming it as necessary
48437
   */
48438
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
48439
48440
  // simdjson_inline void log_value(const char *type) const noexcept;
48441
  // simdjson_inline void log_error(const char *message) const noexcept;
48442
48443
  value_iterator iter{};
48444
48445
  friend class document;
48446
  friend class array_iterator;
48447
  friend class field;
48448
  friend class object;
48449
  friend struct simdjson_result<value>;
48450
  friend struct simdjson_result<field>;
48451
  friend class field;
48452
};
48453
48454
} // namespace ondemand
48455
} // namespace haswell
48456
} // namespace simdjson
48457
48458
namespace simdjson {
48459
48460
template<>
48461
struct simdjson_result<haswell::ondemand::value> : public haswell::implementation_simdjson_result_base<haswell::ondemand::value> {
48462
public:
48463
  simdjson_inline simdjson_result(haswell::ondemand::value &&value) noexcept; ///< @private
48464
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
48465
  simdjson_inline simdjson_result() noexcept = default;
48466
48467
  simdjson_inline simdjson_result<haswell::ondemand::array> get_array() noexcept;
48468
  simdjson_inline simdjson_result<haswell::ondemand::object> get_object() noexcept;
48469
48470
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
48471
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
48472
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
48473
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
48474
  simdjson_inline simdjson_result<double> get_double() noexcept;
48475
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
48476
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
48477
  template <typename string_type>
48478
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
48479
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
48480
  simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> get_raw_json_string() noexcept;
48481
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
48482
  simdjson_inline simdjson_result<bool> is_null() noexcept;
48483
48484
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
48485
48486
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
48487
48488
#if SIMDJSON_EXCEPTIONS
48489
  template <class T>
48490
  explicit simdjson_inline operator T() noexcept(false);
48491
  simdjson_inline operator haswell::ondemand::array() noexcept(false);
48492
  simdjson_inline operator haswell::ondemand::object() noexcept(false);
48493
  simdjson_inline operator uint64_t() noexcept(false);
48494
  simdjson_inline operator int64_t() noexcept(false);
48495
  simdjson_inline operator double() noexcept(false);
48496
  simdjson_inline operator std::string_view() noexcept(false);
48497
  simdjson_inline operator haswell::ondemand::raw_json_string() noexcept(false);
48498
  simdjson_inline operator bool() noexcept(false);
48499
#endif
48500
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
48501
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
48502
  simdjson_inline simdjson_result<haswell::ondemand::value> at(size_t index) noexcept;
48503
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> begin() & noexcept;
48504
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> end() & noexcept;
48505
48506
  /**
48507
   * Look up a field by name on an object (order-sensitive).
48508
   *
48509
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
48510
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
48511
   *
48512
   * ```c++
48513
   * simdjson::ondemand::parser parser;
48514
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
48515
   * double z = obj.find_field("z");
48516
   * double y = obj.find_field("y");
48517
   * double x = obj.find_field("x");
48518
   * ```
48519
   *
48520
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
48521
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
48522
   *
48523
   * @param key The key to look up.
48524
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
48525
   */
48526
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(std::string_view key) noexcept;
48527
  /** @overload simdjson_inline simdjson_result<haswell::ondemand::value> find_field(std::string_view key) noexcept; */
48528
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(const char *key) noexcept;
48529
48530
  /**
48531
   * Look up a field by name on an object, without regard to key order.
48532
   *
48533
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
48534
   * and often appears negligible. It starts out normally, starting out at the last field; but if
48535
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
48536
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
48537
   * in question is large. The fact that the extra code is there also bumps the executable size.
48538
   *
48539
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
48540
   * default behavior failed to look up a field just because it was in the wrong order--and many
48541
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
48542
   *
48543
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
48544
   * field as not there when they are not in order).
48545
   *
48546
   * @param key The key to look up.
48547
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
48548
   */
48549
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) noexcept;
48550
  /** @overload simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
48551
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(const char *key) noexcept;
48552
  /** @overload simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
48553
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](std::string_view key) noexcept;
48554
  /** @overload simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
48555
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](const char *key) noexcept;
48556
48557
  /**
48558
   * Get the type of this JSON value.
48559
   *
48560
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
48561
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
48562
   * let it throw an exception).
48563
   */
48564
  simdjson_inline simdjson_result<haswell::ondemand::json_type> type() noexcept;
48565
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
48566
  simdjson_inline simdjson_result<bool> is_string() noexcept;
48567
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
48568
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
48569
  simdjson_inline simdjson_result<haswell::number_type> get_number_type() noexcept;
48570
  simdjson_inline simdjson_result<haswell::ondemand::number> get_number() noexcept;
48571
48572
  /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
48573
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
48574
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
48575
48576
  /** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
48577
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
48578
  /** @copydoc simdjson_inline int32_t current_depth() const noexcept */
48579
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
48580
  simdjson_inline simdjson_result<haswell::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
48581
  simdjson_inline simdjson_result<haswell::ondemand::value> at_path(std::string_view json_path) noexcept;
48582
};
48583
48584
} // namespace simdjson
48585
48586
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H
48587
/* end file simdjson/generic/ondemand/value.h for haswell */
48588
/* including simdjson/generic/ondemand/logger.h for haswell: #include "simdjson/generic/ondemand/logger.h" */
48589
/* begin file simdjson/generic/ondemand/logger.h for haswell */
48590
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
48591
48592
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
48593
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_H */
48594
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
48595
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
48596
48597
namespace simdjson {
48598
namespace haswell {
48599
namespace ondemand {
48600
48601
// Logging should be free unless SIMDJSON_VERBOSE_LOGGING is set. Importantly, it is critical
48602
// that the call to the log functions be side-effect free. Thus, for example, you should not
48603
// create temporary std::string instances.
48604
namespace logger {
48605
48606
enum class log_level : int32_t {
48607
  info = 0,
48608
  error = 1
48609
};
48610
48611
#if SIMDJSON_VERBOSE_LOGGING
48612
  static constexpr const bool LOG_ENABLED = true;
48613
#else
48614
  static constexpr const bool LOG_ENABLED = false;
48615
#endif
48616
48617
// We do not want these functions to be 'really inlined' since real inlining is
48618
// for performance purposes and if you are using the loggers, you do not care about
48619
// performance (or should not).
48620
static inline void log_headers() noexcept;
48621
// If args are provided, title will be treated as format string
48622
template <typename... Args>
48623
static inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
48624
template <typename... Args>
48625
static inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
48626
static inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
48627
static inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
48628
static inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
48629
static inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
48630
static inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
48631
static inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
48632
48633
static inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail="") noexcept;
48634
static inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
48635
48636
static inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
48637
static inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
48638
static inline void log_start_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
48639
static inline void log_end_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
48640
static inline void log_error(const value_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
48641
48642
} // namespace logger
48643
} // namespace ondemand
48644
} // namespace haswell
48645
} // namespace simdjson
48646
48647
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
48648
/* end file simdjson/generic/ondemand/logger.h for haswell */
48649
/* including simdjson/generic/ondemand/token_iterator.h for haswell: #include "simdjson/generic/ondemand/token_iterator.h" */
48650
/* begin file simdjson/generic/ondemand/token_iterator.h for haswell */
48651
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
48652
48653
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
48654
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H */
48655
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
48656
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
48657
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
48658
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
48659
48660
namespace simdjson {
48661
namespace haswell {
48662
namespace ondemand {
48663
48664
/**
48665
 * Iterates through JSON tokens (`{` `}` `[` `]` `,` `:` `"<string>"` `123` `true` `false` `null`)
48666
 * detected by stage 1.
48667
 *
48668
 * @private This is not intended for external use.
48669
 */
48670
class token_iterator {
48671
public:
48672
  /**
48673
   * Create a new invalid token_iterator.
48674
   *
48675
   * Exists so you can declare a variable and later assign to it before use.
48676
   */
48677
  simdjson_inline token_iterator() noexcept = default;
48678
  simdjson_inline token_iterator(token_iterator &&other) noexcept = default;
48679
  simdjson_inline token_iterator &operator=(token_iterator &&other) noexcept = default;
48680
  simdjson_inline token_iterator(const token_iterator &other) noexcept = default;
48681
  simdjson_inline token_iterator &operator=(const token_iterator &other) noexcept = default;
48682
48683
  /**
48684
   * Advance to the next token (returning the current one).
48685
   */
48686
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
48687
  /**
48688
   * Reports the current offset in bytes from the start of the underlying buffer.
48689
   */
48690
  simdjson_inline uint32_t current_offset() const noexcept;
48691
  /**
48692
   * Get the JSON text for a given token (relative).
48693
   *
48694
   * This is not null-terminated; it is a view into the JSON.
48695
   *
48696
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
48697
   *              1 = next token, -1 = prev token.
48698
   *
48699
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
48700
   * it is not used...
48701
   */
48702
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
48703
  /**
48704
   * Get the maximum length of the JSON text for a given token.
48705
   *
48706
   * The length will include any whitespace at the end of the token.
48707
   *
48708
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
48709
   *              1 = next token, -1 = prev token.
48710
   */
48711
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
48712
48713
  /**
48714
   * Get the JSON text for a given token.
48715
   *
48716
   * This is not null-terminated; it is a view into the JSON.
48717
   *
48718
   * @param position The position of the token.
48719
   *
48720
   */
48721
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
48722
  /**
48723
   * Get the maximum length of the JSON text for a given token.
48724
   *
48725
   * The length will include any whitespace at the end of the token.
48726
   *
48727
   * @param position The position of the token.
48728
   */
48729
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
48730
  /**
48731
   * Get the maximum length of the JSON text for a root token.
48732
   *
48733
   * The length will include any whitespace at the end of the token.
48734
   *
48735
   * @param position The position of the token (start of the document).
48736
   */
48737
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
48738
  /**
48739
   * Return the current index.
48740
   */
48741
  simdjson_inline token_position position() const noexcept;
48742
  /**
48743
   * Reset to a previously saved index.
48744
   */
48745
  simdjson_inline void set_position(token_position target_position) noexcept;
48746
48747
  // NOTE: we don't support a full C++ iterator interface, because we expect people to make
48748
  // different calls to advance the iterator based on *their own* state.
48749
48750
  simdjson_inline bool operator==(const token_iterator &other) const noexcept;
48751
  simdjson_inline bool operator!=(const token_iterator &other) const noexcept;
48752
  simdjson_inline bool operator>(const token_iterator &other) const noexcept;
48753
  simdjson_inline bool operator>=(const token_iterator &other) const noexcept;
48754
  simdjson_inline bool operator<(const token_iterator &other) const noexcept;
48755
  simdjson_inline bool operator<=(const token_iterator &other) const noexcept;
48756
48757
protected:
48758
  simdjson_inline token_iterator(const uint8_t *buf, token_position position) noexcept;
48759
48760
  /**
48761
   * Get the index of the JSON text for a given token (relative).
48762
   *
48763
   * This is not null-terminated; it is a view into the JSON.
48764
   *
48765
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
48766
   *              1 = next token, -1 = prev token.
48767
   */
48768
  simdjson_inline uint32_t peek_index(int32_t delta=0) const noexcept;
48769
  /**
48770
   * Get the index of the JSON text for a given token.
48771
   *
48772
   * This is not null-terminated; it is a view into the JSON.
48773
   *
48774
   * @param position The position of the token.
48775
   *
48776
   */
48777
  simdjson_inline uint32_t peek_index(token_position position) const noexcept;
48778
48779
  const uint8_t *buf{};
48780
  token_position _position{};
48781
48782
  friend class json_iterator;
48783
  friend class value_iterator;
48784
  friend class object;
48785
  template <typename... Args>
48786
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
48787
  template <typename... Args>
48788
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
48789
};
48790
48791
} // namespace ondemand
48792
} // namespace haswell
48793
} // namespace simdjson
48794
48795
namespace simdjson {
48796
48797
template<>
48798
struct simdjson_result<haswell::ondemand::token_iterator> : public haswell::implementation_simdjson_result_base<haswell::ondemand::token_iterator> {
48799
public:
48800
  simdjson_inline simdjson_result(haswell::ondemand::token_iterator &&value) noexcept; ///< @private
48801
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
48802
  simdjson_inline simdjson_result() noexcept = default;
48803
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
48804
};
48805
48806
} // namespace simdjson
48807
48808
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
48809
/* end file simdjson/generic/ondemand/token_iterator.h for haswell */
48810
/* including simdjson/generic/ondemand/json_iterator.h for haswell: #include "simdjson/generic/ondemand/json_iterator.h" */
48811
/* begin file simdjson/generic/ondemand/json_iterator.h for haswell */
48812
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
48813
48814
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
48815
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H */
48816
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
48817
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
48818
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
48819
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
48820
48821
namespace simdjson {
48822
namespace haswell {
48823
namespace ondemand {
48824
48825
/**
48826
 * Iterates through JSON tokens, keeping track of depth and string buffer.
48827
 *
48828
 * @private This is not intended for external use.
48829
 */
48830
class json_iterator {
48831
protected:
48832
  token_iterator token{};
48833
  ondemand::parser *parser{};
48834
  /**
48835
   * Next free location in the string buffer.
48836
   *
48837
   * Used by raw_json_string::unescape() to have a place to unescape strings to.
48838
   */
48839
  uint8_t *_string_buf_loc{};
48840
  /**
48841
   * JSON error, if there is one.
48842
   *
48843
   * INCORRECT_TYPE and NO_SUCH_FIELD are *not* stored here, ever.
48844
   *
48845
   * PERF NOTE: we *hope* this will be elided into control flow, as it is only used (a) in the first
48846
   * iteration of the loop, or (b) for the final iteration after a missing comma is found in ++. If
48847
   * this is not elided, we should make sure it's at least not using up a register. Failing that,
48848
   * we should store it in document so there's only one of them.
48849
   */
48850
  error_code error{SUCCESS};
48851
  /**
48852
   * Depth of the current token in the JSON.
48853
   *
48854
   * - 0 = finished with document
48855
   * - 1 = document root value (could be [ or {, not yet known)
48856
   * - 2 = , or } inside root array/object
48857
   * - 3 = key or value inside root array/object.
48858
   */
48859
  depth_t _depth{};
48860
  /**
48861
   * Beginning of the document indexes.
48862
   * Normally we have root == parser->implementation->structural_indexes.get()
48863
   * but this may differ, especially in streaming mode (where we have several
48864
   * documents);
48865
   */
48866
  token_position _root{};
48867
  /**
48868
   * Normally, a json_iterator operates over a single document, but in
48869
   * some cases, we may have a stream of documents. This attribute is meant
48870
   * as meta-data: the json_iterator works the same irrespective of the
48871
   * value of this attribute.
48872
   */
48873
  bool _streaming{false};
48874
48875
public:
48876
  simdjson_inline json_iterator() noexcept = default;
48877
  simdjson_inline json_iterator(json_iterator &&other) noexcept;
48878
  simdjson_inline json_iterator &operator=(json_iterator &&other) noexcept;
48879
  simdjson_inline explicit json_iterator(const json_iterator &other) noexcept = default;
48880
  simdjson_inline json_iterator &operator=(const json_iterator &other) noexcept = default;
48881
  /**
48882
   * Skips a JSON value, whether it is a scalar, array or object.
48883
   */
48884
  simdjson_warn_unused simdjson_inline error_code skip_child(depth_t parent_depth) noexcept;
48885
48886
  /**
48887
   * Tell whether the iterator is still at the start
48888
   */
48889
  simdjson_inline bool at_root() const noexcept;
48890
48891
  /**
48892
   * Tell whether we should be expected to run in streaming
48893
   * mode (iterating over many documents). It is pure metadata
48894
   * that does not affect how the iterator works. It is used by
48895
   * start_root_array() and start_root_object().
48896
   */
48897
  simdjson_inline bool streaming() const noexcept;
48898
48899
  /**
48900
   * Get the root value iterator
48901
   */
48902
  simdjson_inline token_position root_position() const noexcept;
48903
  /**
48904
   * Assert that we are at the document depth (== 1)
48905
   */
48906
  simdjson_inline void assert_at_document_depth() const noexcept;
48907
  /**
48908
   * Assert that we are at the root of the document
48909
   */
48910
  simdjson_inline void assert_at_root() const noexcept;
48911
48912
  /**
48913
   * Tell whether the iterator is at the EOF mark
48914
   */
48915
  simdjson_inline bool at_end() const noexcept;
48916
48917
  /**
48918
   * Tell whether the iterator is live (has not been moved).
48919
   */
48920
  simdjson_inline bool is_alive() const noexcept;
48921
48922
  /**
48923
   * Abandon this iterator, setting depth to 0 (as if the document is finished).
48924
   */
48925
  simdjson_inline void abandon() noexcept;
48926
48927
  /**
48928
   * Advance the current token without modifying depth.
48929
   */
48930
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
48931
48932
  /**
48933
   * Returns true if there is a single token in the index (i.e., it is
48934
   * a JSON with a scalar value such as a single number).
48935
   *
48936
   * @return whether there is a single token
48937
   */
48938
  simdjson_inline bool is_single_token() const noexcept;
48939
48940
  /**
48941
   * Assert that there are at least the given number of tokens left.
48942
   *
48943
   * Has no effect in release builds.
48944
   */
48945
  simdjson_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
48946
  /**
48947
   * Assert that the given position addresses an actual token (is within bounds).
48948
   *
48949
   * Has no effect in release builds.
48950
   */
48951
  simdjson_inline void assert_valid_position(token_position position) const noexcept;
48952
  /**
48953
   * Get the JSON text for a given token (relative).
48954
   *
48955
   * This is not null-terminated; it is a view into the JSON.
48956
   *
48957
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
48958
   *
48959
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
48960
   * it is not used ...
48961
   */
48962
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
48963
  /**
48964
   * Get the maximum length of the JSON text for the current token (or relative).
48965
   *
48966
   * The length will include any whitespace at the end of the token.
48967
   *
48968
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
48969
   */
48970
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
48971
  /**
48972
   * Get a pointer to the current location in the input buffer.
48973
   *
48974
   * This is not null-terminated; it is a view into the JSON.
48975
   *
48976
   * You may be pointing outside of the input buffer: it is not generally
48977
   * safe to dereference this pointer.
48978
   */
48979
  simdjson_inline const uint8_t *unsafe_pointer() const noexcept;
48980
  /**
48981
   * Get the JSON text for a given token.
48982
   *
48983
   * This is not null-terminated; it is a view into the JSON.
48984
   *
48985
   * @param position The position of the token to retrieve.
48986
   *
48987
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
48988
   * it is not used ...
48989
   */
48990
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
48991
  /**
48992
   * Get the maximum length of the JSON text for the current token (or relative).
48993
   *
48994
   * The length will include any whitespace at the end of the token.
48995
   *
48996
   * @param position The position of the token to retrieve.
48997
   */
48998
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
48999
  /**
49000
   * Get the maximum length of the JSON text for the current root token.
49001
   *
49002
   * The length will include any whitespace at the end of the token.
49003
   *
49004
   * @param position The position of the token to retrieve.
49005
   */
49006
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
49007
  /**
49008
   * Get the JSON text for the last token in the document.
49009
   *
49010
   * This is not null-terminated; it is a view into the JSON.
49011
   *
49012
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
49013
   * it is not used ...
49014
   */
49015
  simdjson_inline const uint8_t *peek_last() const noexcept;
49016
49017
  /**
49018
   * Ascend one level.
49019
   *
49020
   * Validates that the depth - 1 == parent_depth.
49021
   *
49022
   * @param parent_depth the expected parent depth.
49023
   */
49024
  simdjson_inline void ascend_to(depth_t parent_depth) noexcept;
49025
49026
  /**
49027
   * Descend one level.
49028
   *
49029
   * Validates that the new depth == child_depth.
49030
   *
49031
   * @param child_depth the expected child depth.
49032
   */
49033
  simdjson_inline void descend_to(depth_t child_depth) noexcept;
49034
  simdjson_inline void descend_to(depth_t child_depth, int32_t delta) noexcept;
49035
49036
  /**
49037
   * Get current depth.
49038
   */
49039
  simdjson_inline depth_t depth() const noexcept;
49040
49041
  /**
49042
   * Get current (writeable) location in the string buffer.
49043
   */
49044
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
49045
49046
  /**
49047
   * Report an unrecoverable error, preventing further iteration.
49048
   *
49049
   * @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
49050
   * @param message An error message to report with the error.
49051
   */
49052
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
49053
49054
  /**
49055
   * Log error, but don't stop iteration.
49056
   * @param error The error to report. Must be INCORRECT_TYPE, or NO_SUCH_FIELD.
49057
   * @param message An error message to report with the error.
49058
   */
49059
  simdjson_inline error_code optional_error(error_code error, const char *message) noexcept;
49060
49061
  /**
49062
   * Take an input in json containing max_len characters and attempt to copy it over to tmpbuf, a buffer with
49063
   * N bytes of capacity. It will return false if N is too small (smaller than max_len) of if it is zero.
49064
   * The buffer (tmpbuf) is padded with space characters.
49065
   */
49066
  simdjson_warn_unused simdjson_inline bool copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept;
49067
49068
  simdjson_inline token_position position() const noexcept;
49069
  /**
49070
   * Write the raw_json_string to the string buffer and return a string_view.
49071
   * Each raw_json_string should be unescaped once, or else the string buffer might
49072
   * overflow.
49073
   */
49074
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
49075
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
49076
49077
  simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
49078
49079
  simdjson_inline error_code consume_character(char c) noexcept;
49080
#if SIMDJSON_DEVELOPMENT_CHECKS
49081
  simdjson_inline token_position start_position(depth_t depth) const noexcept;
49082
  simdjson_inline void set_start_position(depth_t depth, token_position position) noexcept;
49083
#endif
49084
49085
  /* Useful for debugging and logging purposes. */
49086
  inline std::string to_string() const noexcept;
49087
49088
  /**
49089
   * Returns the current location in the document if in bounds.
49090
   */
49091
  inline simdjson_result<const char *> current_location() const noexcept;
49092
49093
  /**
49094
   * Updates this json iterator so that it is back at the beginning of the document,
49095
   * as if it had just been created.
49096
   */
49097
  inline void rewind() noexcept;
49098
  /**
49099
   * This checks whether the {,},[,] are balanced so that the document
49100
   * ends with proper zero depth. This requires scanning the whole document
49101
   * and it may be expensive. It is expected that it will be rarely called.
49102
   * It does not attempt to match { with } and [ with ].
49103
   */
49104
  inline bool balanced() const noexcept;
49105
protected:
49106
  simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
49107
  /// The last token before the end
49108
  simdjson_inline token_position last_position() const noexcept;
49109
  /// The token *at* the end. This points at gibberish and should only be used for comparison.
49110
  simdjson_inline token_position end_position() const noexcept;
49111
  /// The end of the buffer.
49112
  simdjson_inline token_position end() const noexcept;
49113
49114
  friend class document;
49115
  friend class document_stream;
49116
  friend class object;
49117
  friend class array;
49118
  friend class value;
49119
  friend class raw_json_string;
49120
  friend class parser;
49121
  friend class value_iterator;
49122
  friend class field;
49123
  template <typename... Args>
49124
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
49125
  template <typename... Args>
49126
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
49127
}; // json_iterator
49128
49129
} // namespace ondemand
49130
} // namespace haswell
49131
} // namespace simdjson
49132
49133
namespace simdjson {
49134
49135
template<>
49136
struct simdjson_result<haswell::ondemand::json_iterator> : public haswell::implementation_simdjson_result_base<haswell::ondemand::json_iterator> {
49137
public:
49138
  simdjson_inline simdjson_result(haswell::ondemand::json_iterator &&value) noexcept; ///< @private
49139
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
49140
49141
  simdjson_inline simdjson_result() noexcept = default;
49142
};
49143
49144
} // namespace simdjson
49145
49146
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
49147
/* end file simdjson/generic/ondemand/json_iterator.h for haswell */
49148
/* including simdjson/generic/ondemand/json_type.h for haswell: #include "simdjson/generic/ondemand/json_type.h" */
49149
/* begin file simdjson/generic/ondemand/json_type.h for haswell */
49150
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
49151
49152
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
49153
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H */
49154
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
49155
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
49156
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
49157
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
49158
49159
namespace simdjson {
49160
namespace haswell {
49161
namespace ondemand {
49162
49163
/**
49164
 * The type of a JSON value.
49165
 */
49166
enum class json_type {
49167
    // Start at 1 to catch uninitialized / default values more easily
49168
    array=1, ///< A JSON array   ( [ 1, 2, 3 ... ] )
49169
    object,  ///< A JSON object  ( { "a": 1, "b" 2, ... } )
49170
    number,  ///< A JSON number  ( 1 or -2.3 or 4.5e6 ...)
49171
    string,  ///< A JSON string  ( "a" or "hello world\n" ...)
49172
    boolean, ///< A JSON boolean (true or false)
49173
    null     ///< A JSON null    (null)
49174
};
49175
49176
/**
49177
 * A type representing a JSON number.
49178
 * The design of the struct is deliberately straight-forward. All
49179
 * functions return standard values with no error check.
49180
 */
49181
struct number {
49182
49183
  /**
49184
   * return the automatically determined type of
49185
   * the number: number_type::floating_point_number,
49186
   * number_type::signed_integer or number_type::unsigned_integer.
49187
   *
49188
   *    enum class number_type {
49189
   *        floating_point_number=1, /// a binary64 number
49190
   *        signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
49191
   *        unsigned_integer         /// a positive integer larger or equal to 1<<63
49192
   *    };
49193
   */
49194
  simdjson_inline ondemand::number_type get_number_type() const noexcept;
49195
  /**
49196
   * return true if the automatically determined type of
49197
   * the number is number_type::unsigned_integer.
49198
   */
49199
  simdjson_inline bool is_uint64() const noexcept;
49200
  /**
49201
   * return the value as a uint64_t, only valid if is_uint64() is true.
49202
   */
49203
  simdjson_inline uint64_t get_uint64() const noexcept;
49204
  simdjson_inline operator uint64_t() const noexcept;
49205
49206
  /**
49207
   * return true if the automatically determined type of
49208
   * the number is number_type::signed_integer.
49209
   */
49210
  simdjson_inline bool is_int64() const noexcept;
49211
  /**
49212
   * return the value as a int64_t, only valid if is_int64() is true.
49213
   */
49214
  simdjson_inline int64_t get_int64() const noexcept;
49215
  simdjson_inline operator int64_t() const noexcept;
49216
49217
49218
  /**
49219
   * return true if the automatically determined type of
49220
   * the number is number_type::floating_point_number.
49221
   */
49222
  simdjson_inline bool is_double() const noexcept;
49223
  /**
49224
   * return the value as a double, only valid if is_double() is true.
49225
   */
49226
  simdjson_inline double get_double() const noexcept;
49227
  simdjson_inline operator double() const noexcept;
49228
49229
  /**
49230
   * Convert the number to a double. Though it always succeed, the conversion
49231
   * may be lossy if the number cannot be represented exactly.
49232
   */
49233
  simdjson_inline double as_double() const noexcept;
49234
49235
49236
protected:
49237
  /**
49238
   * The next block of declaration is designed so that we can call the number parsing
49239
   * functions on a number type. They are protected and should never be used outside
49240
   * of the core simdjson library.
49241
   */
49242
  friend class value_iterator;
49243
  template<typename W>
49244
  friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
49245
  template<typename W>
49246
  friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
49247
  /** Store a signed 64-bit value to the number. */
49248
  simdjson_inline void append_s64(int64_t value) noexcept;
49249
  /** Store an unsigned 64-bit value to the number. */
49250
  simdjson_inline void append_u64(uint64_t value) noexcept;
49251
  /** Store a double value to the number. */
49252
  simdjson_inline void append_double(double value) noexcept;
49253
  /** Specifies that the value is a double, but leave it undefined. */
49254
  simdjson_inline void skip_double() noexcept;
49255
  /**
49256
   * End of friend declarations.
49257
   */
49258
49259
  /**
49260
   * Our attributes are a union type (size = 64 bits)
49261
   * followed by a type indicator.
49262
   */
49263
  union {
49264
    double floating_point_number;
49265
    int64_t signed_integer;
49266
    uint64_t unsigned_integer;
49267
  } payload{0};
49268
  number_type type{number_type::signed_integer};
49269
};
49270
49271
/**
49272
 * Write the JSON type to the output stream
49273
 *
49274
 * @param out The output stream.
49275
 * @param type The json_type.
49276
 */
49277
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
49278
49279
#if SIMDJSON_EXCEPTIONS
49280
/**
49281
 * Send JSON type to an output stream.
49282
 *
49283
 * @param out The output stream.
49284
 * @param type The json_type.
49285
 * @throw simdjson_error if the result being printed has an error. If there is an error with the
49286
 *        underlying output stream, that error will be propagated (simdjson_error will not be
49287
 *        thrown).
49288
 */
49289
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false);
49290
#endif
49291
49292
} // namespace ondemand
49293
} // namespace haswell
49294
} // namespace simdjson
49295
49296
namespace simdjson {
49297
49298
template<>
49299
struct simdjson_result<haswell::ondemand::json_type> : public haswell::implementation_simdjson_result_base<haswell::ondemand::json_type> {
49300
public:
49301
  simdjson_inline simdjson_result(haswell::ondemand::json_type &&value) noexcept; ///< @private
49302
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
49303
  simdjson_inline simdjson_result() noexcept = default;
49304
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
49305
};
49306
49307
} // namespace simdjson
49308
49309
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
49310
/* end file simdjson/generic/ondemand/json_type.h for haswell */
49311
/* including simdjson/generic/ondemand/raw_json_string.h for haswell: #include "simdjson/generic/ondemand/raw_json_string.h" */
49312
/* begin file simdjson/generic/ondemand/raw_json_string.h for haswell */
49313
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
49314
49315
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
49316
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H */
49317
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
49318
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
49319
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
49320
49321
namespace simdjson {
49322
namespace haswell {
49323
namespace ondemand {
49324
49325
/**
49326
 * A string escaped per JSON rules, terminated with quote ("). They are used to represent
49327
 * unescaped keys inside JSON documents.
49328
 *
49329
 * (In other words, a pointer to the beginning of a string, just after the start quote, inside a
49330
 * JSON file.)
49331
 *
49332
 * This class is deliberately simplistic and has little functionality. You can
49333
 * compare a raw_json_string instance with an unescaped C string, but
49334
 * that is nearly all you can do.
49335
 *
49336
 * The raw_json_string is unescaped. If you wish to write an unescaped version of it to your own
49337
 * buffer, you may do so using the parser.unescape(string, buff) method, using an ondemand::parser
49338
 * instance. Doing so requires you to have a sufficiently large buffer.
49339
 *
49340
 * The raw_json_string instances originate typically from field instance which in turn represent
49341
 * key-value pairs from object instances. From a field instance, you get the raw_json_string
49342
 * instance by calling key(). You can, if you want a more usable string_view instance, call
49343
 * the unescaped_key() method on the field instance. You may also create a raw_json_string from
49344
 * any other string value, with the value.get_raw_json_string() method. Again, you can get
49345
 * a more usable string_view instance by calling get_string().
49346
 *
49347
 */
49348
class raw_json_string {
49349
public:
49350
  /**
49351
   * Create a new invalid raw_json_string.
49352
   *
49353
   * Exists so you can declare a variable and later assign to it before use.
49354
   */
49355
  simdjson_inline raw_json_string() noexcept = default;
49356
49357
  /**
49358
   * Create a new invalid raw_json_string pointed at the given location in the JSON.
49359
   *
49360
   * The given location must be just *after* the beginning quote (") in the JSON file.
49361
   *
49362
   * It *must* be terminated by a ", and be a valid JSON string.
49363
   */
49364
  simdjson_inline raw_json_string(const uint8_t * _buf) noexcept;
49365
  /**
49366
   * Get the raw pointer to the beginning of the string in the JSON (just after the ").
49367
   *
49368
   * It is possible for this function to return a null pointer if the instance
49369
   * has outlived its existence.
49370
   */
49371
  simdjson_inline const char * raw() const noexcept;
49372
49373
  /**
49374
   * This compares the current instance to the std::string_view target: returns true if
49375
   * they are byte-by-byte equal (no escaping is done) on target.size() characters,
49376
   * and if the raw_json_string instance has a quote character at byte index target.size().
49377
   * We never read more than length + 1 bytes in the raw_json_string instance.
49378
   * If length is smaller than target.size(), this will return false.
49379
   *
49380
   * The std::string_view instance may contain any characters. However, the caller
49381
   * is responsible for setting length so that length bytes may be read in the
49382
   * raw_json_string.
49383
   *
49384
   * Performance: the comparison may be done using memcmp which may be efficient
49385
   * for long strings.
49386
   */
49387
  simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept;
49388
49389
  /**
49390
   * This compares the current instance to the std::string_view target: returns true if
49391
   * they are byte-by-byte equal (no escaping is done).
49392
   * The std::string_view instance should not contain unescaped quote characters:
49393
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
49394
   *
49395
   * Performance: the comparison is done byte-by-byte which might be inefficient for
49396
   * long strings.
49397
   *
49398
   * If target is a compile-time constant, and your compiler likes you,
49399
   * you should be able to do the following without performance penalty...
49400
   *
49401
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
49402
   *   s.unsafe_is_equal(target);
49403
   */
49404
  simdjson_inline bool unsafe_is_equal(std::string_view target) const noexcept;
49405
49406
  /**
49407
   * This compares the current instance to the C string target: returns true if
49408
   * they are byte-by-byte equal (no escaping is done).
49409
   * The provided C string should not contain an unescaped quote character:
49410
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
49411
   *
49412
   * If target is a compile-time constant, and your compiler likes you,
49413
   * you should be able to do the following without performance penalty...
49414
   *
49415
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
49416
   *   s.unsafe_is_equal(target);
49417
   */
49418
  simdjson_inline bool unsafe_is_equal(const char* target) const noexcept;
49419
49420
  /**
49421
   * This compares the current instance to the std::string_view target: returns true if
49422
   * they are byte-by-byte equal (no escaping is done).
49423
   */
49424
  simdjson_inline bool is_equal(std::string_view target) const noexcept;
49425
49426
  /**
49427
   * This compares the current instance to the C string target: returns true if
49428
   * they are byte-by-byte equal (no escaping is done).
49429
   */
49430
  simdjson_inline bool is_equal(const char* target) const noexcept;
49431
49432
  /**
49433
   * Returns true if target is free from unescaped quote. If target is known at
49434
   * compile-time, we might expect the computation to happen at compile time with
49435
   * many compilers (not all!).
49436
   */
49437
  static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
49438
  static simdjson_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
49439
49440
private:
49441
49442
49443
  /**
49444
   * This will set the inner pointer to zero, effectively making
49445
   * this instance unusable.
49446
   */
49447
  simdjson_inline void consume() noexcept { buf = nullptr; }
49448
49449
  /**
49450
   * Checks whether the inner pointer is non-null and thus usable.
49451
   */
49452
  simdjson_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
49453
49454
  /**
49455
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
49456
   * The result will be a valid UTF-8.
49457
   *
49458
   * ## IMPORTANT: string_view lifetime
49459
   *
49460
   * The string_view is only valid until the next parse() call on the parser.
49461
   *
49462
   * @param iter A json_iterator, which contains a buffer where the string will be written.
49463
   * @param allow_replacement Whether we allow replacement of invalid surrogate pairs.
49464
   */
49465
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(json_iterator &iter, bool allow_replacement) const noexcept;
49466
49467
  /**
49468
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
49469
   * The result may not be a valid UTF-8. https://simonsapin.github.io/wtf-8/
49470
   *
49471
   * ## IMPORTANT: string_view lifetime
49472
   *
49473
   * The string_view is only valid until the next parse() call on the parser.
49474
   *
49475
   * @param iter A json_iterator, which contains a buffer where the string will be written.
49476
   */
49477
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(json_iterator &iter) const noexcept;
49478
  const uint8_t * buf{};
49479
  friend class object;
49480
  friend class field;
49481
  friend class parser;
49482
  friend struct simdjson_result<raw_json_string>;
49483
};
49484
49485
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &, const raw_json_string &) noexcept;
49486
49487
/**
49488
 * Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user is responsible
49489
 * for providing a string with no unescaped quote. Note that unescaped quotes cannot be present in valid JSON strings.
49490
 */
49491
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept;
49492
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept;
49493
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept;
49494
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept;
49495
49496
49497
} // namespace ondemand
49498
} // namespace haswell
49499
} // namespace simdjson
49500
49501
namespace simdjson {
49502
49503
template<>
49504
struct simdjson_result<haswell::ondemand::raw_json_string> : public haswell::implementation_simdjson_result_base<haswell::ondemand::raw_json_string> {
49505
public:
49506
  simdjson_inline simdjson_result(haswell::ondemand::raw_json_string &&value) noexcept; ///< @private
49507
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
49508
  simdjson_inline simdjson_result() noexcept = default;
49509
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
49510
49511
  simdjson_inline simdjson_result<const char *> raw() const noexcept;
49512
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(haswell::ondemand::json_iterator &iter, bool allow_replacement) const noexcept;
49513
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(haswell::ondemand::json_iterator &iter) const noexcept;
49514
};
49515
49516
} // namespace simdjson
49517
49518
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
49519
/* end file simdjson/generic/ondemand/raw_json_string.h for haswell */
49520
/* including simdjson/generic/ondemand/parser.h for haswell: #include "simdjson/generic/ondemand/parser.h" */
49521
/* begin file simdjson/generic/ondemand/parser.h for haswell */
49522
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_H
49523
49524
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
49525
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_H */
49526
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
49527
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
49528
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
49529
49530
#include <memory>
49531
49532
namespace simdjson {
49533
namespace haswell {
49534
namespace ondemand {
49535
49536
/**
49537
 * The default batch size for document_stream instances for this On Demand kernel.
49538
 * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value
49539
 * in the future.
49540
 */
49541
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
49542
/**
49543
 * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
49544
 * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
49545
 * most users will want a much larger batch size.
49546
 *
49547
 * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
49548
 * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
49549
 */
49550
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
49551
49552
/**
49553
 * A JSON fragment iterator.
49554
 *
49555
 * This holds the actual iterator as well as the buffer for writing strings.
49556
 */
49557
class parser {
49558
public:
49559
  /**
49560
   * Create a JSON parser.
49561
   *
49562
   * The new parser will have zero capacity.
49563
   */
49564
  inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
49565
49566
  inline parser(parser &&other) noexcept = default;
49567
  simdjson_inline parser(const parser &other) = delete;
49568
  simdjson_inline parser &operator=(const parser &other) = delete;
49569
  simdjson_inline parser &operator=(parser &&other) noexcept = default;
49570
49571
  /** Deallocate the JSON parser. */
49572
  inline ~parser() noexcept = default;
49573
49574
  /**
49575
   * Start iterating an on-demand JSON document.
49576
   *
49577
   *   ondemand::parser parser;
49578
   *   document doc = parser.iterate(json);
49579
   *
49580
   * It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
49581
   * Otherwise the iterate method may return an error. In particular, the whole input should be
49582
   * valid: we do not attempt to tolerate incorrect content either before or after a JSON
49583
   * document. If there is a UTF-8 BOM, the parser skips it.
49584
   *
49585
   * ### IMPORTANT: Validate what you use
49586
   *
49587
   * Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
49588
   * iterate does not parse and validate the whole document.
49589
   *
49590
   * ### IMPORTANT: Buffer Lifetime
49591
   *
49592
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
49593
   * long as the document iteration.
49594
   *
49595
   * ### IMPORTANT: Document Lifetime
49596
   *
49597
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
49598
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
49599
   * you call parse() again or destroy the parser.
49600
   *
49601
   * ### REQUIRED: Buffer Padding
49602
   *
49603
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
49604
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
49605
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
49606
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
49607
   *
49608
   * @param json The JSON to parse.
49609
   * @param len The length of the JSON.
49610
   * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
49611
   *
49612
   * @return The document, or an error:
49613
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
49614
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
49615
   *           allocation fails.
49616
   *         - EMPTY if the document is all whitespace.
49617
   *         - UTF8_ERROR if the document is not valid UTF-8.
49618
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
49619
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
49620
   */
49621
  simdjson_warn_unused simdjson_result<document> iterate(padded_string_view json) & noexcept;
49622
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49623
  simdjson_warn_unused simdjson_result<document> iterate(const char *json, size_t len, size_t capacity) & noexcept;
49624
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49625
  simdjson_warn_unused simdjson_result<document> iterate(const uint8_t *json, size_t len, size_t capacity) & noexcept;
49626
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49627
  simdjson_warn_unused simdjson_result<document> iterate(std::string_view json, size_t capacity) & noexcept;
49628
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49629
  simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
49630
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49631
  simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
49632
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49633
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
49634
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49635
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
49636
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
49637
  simdjson_warn_unused simdjson_result<document> iterate(padded_string &&json) & noexcept = delete;
49638
49639
  /**
49640
   * @private
49641
   *
49642
   * Start iterating an on-demand JSON document.
49643
   *
49644
   *   ondemand::parser parser;
49645
   *   json_iterator doc = parser.iterate(json);
49646
   *
49647
   * ### IMPORTANT: Buffer Lifetime
49648
   *
49649
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
49650
   * long as the document iteration.
49651
   *
49652
   * ### IMPORTANT: Document Lifetime
49653
   *
49654
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
49655
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
49656
   * you call parse() again or destroy the parser.
49657
   *
49658
   * The ondemand::document instance holds the iterator. The document must remain in scope
49659
   * while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
49660
   *
49661
   * ### REQUIRED: Buffer Padding
49662
   *
49663
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
49664
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
49665
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
49666
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
49667
   *
49668
   * @param json The JSON to parse.
49669
   *
49670
   * @return The iterator, or an error:
49671
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
49672
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
49673
   *           allocation fails.
49674
   *         - EMPTY if the document is all whitespace.
49675
   *         - UTF8_ERROR if the document is not valid UTF-8.
49676
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
49677
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
49678
   */
49679
  simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
49680
49681
49682
  /**
49683
   * Parse a buffer containing many JSON documents.
49684
   *
49685
   *   auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
49686
   *   ondemand::parser parser;
49687
   *   ondemand::document_stream docs = parser.iterate_many(json);
49688
   *   for (auto & doc : docs) {
49689
   *     std::cout << doc["foo"] << std::endl;
49690
   *   }
49691
   *   // Prints 1 2 3
49692
   *
49693
   * No copy of the input buffer is made.
49694
   *
49695
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
49696
   *
49697
   * The caller is responsabile to ensure that the input string data remains unchanged and is
49698
   * not deleted during the loop.
49699
   *
49700
   * ### Format
49701
   *
49702
   * The buffer must contain a series of one or more JSON documents, concatenated into a single
49703
   * buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
49704
   * then starts parsing the next document at that point. (It does this with more parallelism and
49705
   * lookahead than you might think, though.)
49706
   *
49707
   * documents that consist of an object or array may omit the whitespace between them, concatenating
49708
   * with no separator. Documents that consist of a single primitive (i.e. documents that are not
49709
   * arrays or objects) MUST be separated with ASCII whitespace.
49710
   *
49711
   * The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
49712
   * If there is a UTF-8 BOM, the parser skips it.
49713
   *
49714
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
49715
   * Setting batch_size to excessively large or excessively small values may impact negatively the
49716
   * performance.
49717
   *
49718
   * ### REQUIRED: Buffer Padding
49719
   *
49720
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
49721
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
49722
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
49723
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
49724
   *
49725
   * ### Threads
49726
   *
49727
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
49728
   * hood to do some lookahead.
49729
   *
49730
   * ### Parser Capacity
49731
   *
49732
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
49733
   * to handle it (up to max_capacity).
49734
   *
49735
   * @param buf The concatenated JSON to parse.
49736
   * @param len The length of the concatenated JSON.
49737
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
49738
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
49739
   *                   parse as many documents as possible in one tight loop.
49740
   *                   Defaults to 10MB, which has been a reasonable sweet spot in our tests.
49741
   * @param allow_comma_separated (defaults on false) This allows a mode where the documents are
49742
   *                   separated by commas instead of whitespace. It comes with a performance
49743
   *                   penalty because the entire document is indexed at once (and the document must be
49744
   *                   less than 4 GB), and there is no multithreading. In this mode, the batch_size parameter
49745
   *                   is effectively ignored, as it is set to at least the document size.
49746
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
49747
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails
49748
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
49749
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
49750
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
49751
   */
49752
  inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
49753
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
49754
  inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
49755
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
49756
  inline simdjson_result<document_stream> iterate_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
49757
  inline simdjson_result<document_stream> iterate_many(const std::string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
49758
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
49759
  inline simdjson_result<document_stream> iterate_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
49760
  inline simdjson_result<document_stream> iterate_many(const padded_string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
49761
49762
  /** @private We do not want to allow implicit conversion from C string to std::string. */
49763
  simdjson_result<document_stream> iterate_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
49764
49765
  /** The capacity of this parser (the largest document it can process). */
49766
  simdjson_inline size_t capacity() const noexcept;
49767
  /** The maximum capacity of this parser (the largest document it is allowed to process). */
49768
  simdjson_inline size_t max_capacity() const noexcept;
49769
  simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
49770
  /**
49771
   * The maximum depth of this parser (the most deeply nested objects and arrays it can process).
49772
   * This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
49773
   * The document's instance current_depth() method should be used to monitor the parsing
49774
   * depth and limit it if desired.
49775
   */
49776
  simdjson_inline size_t max_depth() const noexcept;
49777
49778
  /**
49779
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
49780
   * and `max_depth` depth.
49781
   *
49782
   * The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
49783
   * The document's instance current_depth() method should be used to monitor the parsing
49784
   * depth and limit it if desired.
49785
   *
49786
   * @param capacity The new capacity.
49787
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
49788
   * @return The error, if there is one.
49789
   */
49790
  simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
49791
49792
  #ifdef SIMDJSON_THREADS_ENABLED
49793
  /**
49794
   * The parser instance can use threads when they are available to speed up some
49795
   * operations. It is enabled by default. Changing this attribute will change the
49796
   * behavior of the parser for future operations.
49797
   */
49798
  bool threaded{true};
49799
  #endif
49800
49801
  /**
49802
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
49803
   * The result must be valid UTF-8.
49804
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
49805
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
49806
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
49807
   *
49808
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
49809
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
49810
   * instead of get_raw_json_string()).
49811
   *
49812
   * ## IMPORTANT: string_view lifetime
49813
   *
49814
   * The string_view is only valid as long as the bytes in dst.
49815
   *
49816
   * @param raw_json_string input
49817
   * @param dst A pointer to a buffer at least large enough to write this string as well as
49818
   *            an additional SIMDJSON_PADDING bytes.
49819
   * @param allow_replacement Whether we allow a replacement if the input string contains unmatched surrogate pairs.
49820
   * @return A string_view pointing at the unescaped string in dst
49821
   * @error STRING_ERROR if escapes are incorrect.
49822
   */
49823
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement = false) const noexcept;
49824
49825
  /**
49826
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
49827
   * The result may not be valid UTF-8. See https://simonsapin.github.io/wtf-8/
49828
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
49829
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
49830
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
49831
   *
49832
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
49833
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
49834
   * instead of get_raw_json_string()).
49835
   *
49836
   * ## IMPORTANT: string_view lifetime
49837
   *
49838
   * The string_view is only valid as long as the bytes in dst.
49839
   *
49840
   * @param raw_json_string input
49841
   * @param dst A pointer to a buffer at least large enough to write this string as well as
49842
   *            an additional SIMDJSON_PADDING bytes.
49843
   * @return A string_view pointing at the unescaped string in dst
49844
   * @error STRING_ERROR if escapes are incorrect.
49845
   */
49846
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept;
49847
49848
private:
49849
  /** @private [for benchmarking access] The implementation to use */
49850
  std::unique_ptr<internal::dom_parser_implementation> implementation{};
49851
  size_t _capacity{0};
49852
  size_t _max_capacity;
49853
  size_t _max_depth{DEFAULT_MAX_DEPTH};
49854
  std::unique_ptr<uint8_t[]> string_buf{};
49855
#if SIMDJSON_DEVELOPMENT_CHECKS
49856
  std::unique_ptr<token_position[]> start_positions{};
49857
#endif
49858
49859
  friend class json_iterator;
49860
  friend class document_stream;
49861
};
49862
49863
} // namespace ondemand
49864
} // namespace haswell
49865
} // namespace simdjson
49866
49867
namespace simdjson {
49868
49869
template<>
49870
struct simdjson_result<haswell::ondemand::parser> : public haswell::implementation_simdjson_result_base<haswell::ondemand::parser> {
49871
public:
49872
  simdjson_inline simdjson_result(haswell::ondemand::parser &&value) noexcept; ///< @private
49873
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
49874
  simdjson_inline simdjson_result() noexcept = default;
49875
};
49876
49877
} // namespace simdjson
49878
49879
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_H
49880
/* end file simdjson/generic/ondemand/parser.h for haswell */
49881
49882
// All other declarations
49883
/* including simdjson/generic/ondemand/array.h for haswell: #include "simdjson/generic/ondemand/array.h" */
49884
/* begin file simdjson/generic/ondemand/array.h for haswell */
49885
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
49886
49887
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
49888
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H */
49889
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
49890
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
49891
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
49892
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
49893
49894
namespace simdjson {
49895
namespace haswell {
49896
namespace ondemand {
49897
49898
/**
49899
 * A forward-only JSON array.
49900
 */
49901
class array {
49902
public:
49903
  /**
49904
   * Create a new invalid array.
49905
   *
49906
   * Exists so you can declare a variable and later assign to it before use.
49907
   */
49908
  simdjson_inline array() noexcept = default;
49909
49910
  /**
49911
   * Begin array iteration.
49912
   *
49913
   * Part of the std::iterable interface.
49914
   */
49915
  simdjson_inline simdjson_result<array_iterator> begin() noexcept;
49916
  /**
49917
   * Sentinel representing the end of the array.
49918
   *
49919
   * Part of the std::iterable interface.
49920
   */
49921
  simdjson_inline simdjson_result<array_iterator> end() noexcept;
49922
  /**
49923
   * This method scans the array and counts the number of elements.
49924
   * The count_elements method should always be called before you have begun
49925
   * iterating through the array: it is expected that you are pointing at
49926
   * the beginning of the array.
49927
   * The runtime complexity is linear in the size of the array. After
49928
   * calling this function, if successful, the array is 'rewinded' at its
49929
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
49930
   * there is a missing comma), then an error is returned and it is no longer
49931
   * safe to continue.
49932
   *
49933
   * To check that an array is empty, it is more performant to use
49934
   * the is_empty() method.
49935
   */
49936
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
49937
  /**
49938
   * This method scans the beginning of the array and checks whether the
49939
   * array is empty.
49940
   * The runtime complexity is constant time. After
49941
   * calling this function, if successful, the array is 'rewinded' at its
49942
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
49943
   * there is a missing comma), then an error is returned and it is no longer
49944
   * safe to continue.
49945
   */
49946
  simdjson_inline simdjson_result<bool> is_empty() & noexcept;
49947
  /**
49948
   * Reset the iterator so that we are pointing back at the
49949
   * beginning of the array. You should still consume values only once even if you
49950
   * can iterate through the array more than once. If you unescape a string
49951
   * within the array more than once, you have unsafe code. Note that rewinding
49952
   * an array means that you may need to reparse it anew: it is not a free
49953
   * operation.
49954
   *
49955
   * @returns true if the array contains some elements (not empty)
49956
   */
49957
  inline simdjson_result<bool> reset() & noexcept;
49958
  /**
49959
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
49960
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
49961
   * as the root of its own JSON document.
49962
   *
49963
   *   ondemand::parser parser;
49964
   *   auto json = R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded;
49965
   *   auto doc = parser.iterate(json);
49966
   *   doc.at_pointer("/0/foo/a/1") == 20
49967
   *
49968
   * Note that at_pointer() called on the document automatically calls the document's rewind
49969
   * method between each call. It invalidates all previously accessed arrays, objects and values
49970
   * that have not been consumed. Yet it is not the case when calling at_pointer on an array
49971
   * instance: there is no rewind and no invalidation.
49972
   *
49973
   * You may only call at_pointer on an array after it has been created, but before it has
49974
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
49975
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
49976
   * to call at_pointer on the same array.
49977
   *
49978
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
49979
   *
49980
   * @return The value associated with the given JSON pointer, or:
49981
   *         - NO_SUCH_FIELD if a field does not exist in an object
49982
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
49983
   *         - INCORRECT_TYPE if a non-integer is used to access an array
49984
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
49985
   */
49986
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
49987
49988
  /**
49989
   * Get the value associated with the given JSONPath expression. We only support
49990
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
49991
   * names and array indices.
49992
   *
49993
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
49994
   *
49995
   * @return The value associated with the given JSONPath expression, or:
49996
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
49997
   *         - NO_SUCH_FIELD if a field does not exist in an object
49998
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
49999
   *         - INCORRECT_TYPE if a non-integer is used to access an array
50000
  */
50001
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
50002
50003
  /**
50004
   * Consumes the array and returns a string_view instance corresponding to the
50005
   * array as represented in JSON. It points inside the original document.
50006
   */
50007
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
50008
50009
  /**
50010
   * Get the value at the given index. This function has linear-time complexity.
50011
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
50012
   *
50013
   * @return The value at the given index, or:
50014
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
50015
   */
50016
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
50017
protected:
50018
  /**
50019
   * Go to the end of the array, no matter where you are right now.
50020
   */
50021
  simdjson_inline error_code consume() noexcept;
50022
50023
  /**
50024
   * Begin array iteration.
50025
   *
50026
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
50027
   *        resulting array.
50028
   * @error INCORRECT_TYPE if the iterator is not at [.
50029
   */
50030
  static simdjson_inline simdjson_result<array> start(value_iterator &iter) noexcept;
50031
  /**
50032
   * Begin array iteration from the root.
50033
   *
50034
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
50035
   *        resulting array.
50036
   * @error INCORRECT_TYPE if the iterator is not at [.
50037
   * @error TAPE_ERROR if there is no closing ] at the end of the document.
50038
   */
50039
  static simdjson_inline simdjson_result<array> start_root(value_iterator &iter) noexcept;
50040
  /**
50041
   * Begin array iteration.
50042
   *
50043
   * This version of the method should be called after the initial [ has been verified, and is
50044
   * intended for use by switch statements that check the type of a value.
50045
   *
50046
   * @param iter The iterator. Must be after the initial [. Will be *moved* into the resulting array.
50047
   */
50048
  static simdjson_inline simdjson_result<array> started(value_iterator &iter) noexcept;
50049
50050
  /**
50051
   * Create an array at the given Internal array creation. Call array::start() or array::started() instead of this.
50052
   *
50053
   * @param iter The iterator. Must either be at the start of the first element with iter.is_alive()
50054
   *        == true, or past the [] with is_alive() == false if the array is empty. Will be *moved*
50055
   *        into the resulting array.
50056
   */
50057
  simdjson_inline array(const value_iterator &iter) noexcept;
50058
50059
  /**
50060
   * Iterator marking current position.
50061
   *
50062
   * iter.is_alive() == false indicates iteration is complete.
50063
   */
50064
  value_iterator iter{};
50065
50066
  friend class value;
50067
  friend class document;
50068
  friend struct simdjson_result<value>;
50069
  friend struct simdjson_result<array>;
50070
  friend class array_iterator;
50071
};
50072
50073
} // namespace ondemand
50074
} // namespace haswell
50075
} // namespace simdjson
50076
50077
namespace simdjson {
50078
50079
template<>
50080
struct simdjson_result<haswell::ondemand::array> : public haswell::implementation_simdjson_result_base<haswell::ondemand::array> {
50081
public:
50082
  simdjson_inline simdjson_result(haswell::ondemand::array &&value) noexcept; ///< @private
50083
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
50084
  simdjson_inline simdjson_result() noexcept = default;
50085
50086
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> begin() noexcept;
50087
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> end() noexcept;
50088
  inline simdjson_result<size_t> count_elements() & noexcept;
50089
  inline simdjson_result<bool> is_empty() & noexcept;
50090
  inline simdjson_result<bool> reset() & noexcept;
50091
  simdjson_inline simdjson_result<haswell::ondemand::value> at(size_t index) noexcept;
50092
  simdjson_inline simdjson_result<haswell::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
50093
  simdjson_inline simdjson_result<haswell::ondemand::value> at_path(std::string_view json_path) noexcept;
50094
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
50095
50096
};
50097
50098
} // namespace simdjson
50099
50100
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
50101
/* end file simdjson/generic/ondemand/array.h for haswell */
50102
/* including simdjson/generic/ondemand/array_iterator.h for haswell: #include "simdjson/generic/ondemand/array_iterator.h" */
50103
/* begin file simdjson/generic/ondemand/array_iterator.h for haswell */
50104
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
50105
50106
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
50107
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H */
50108
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
50109
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
50110
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
50111
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
50112
50113
50114
namespace simdjson {
50115
namespace haswell {
50116
namespace ondemand {
50117
50118
/**
50119
 * A forward-only JSON array.
50120
 *
50121
 * This is an input_iterator, meaning:
50122
 * - It is forward-only
50123
 * - * must be called exactly once per element.
50124
 * - ++ must be called exactly once in between each * (*, ++, *, ++, * ...)
50125
 */
50126
class array_iterator {
50127
public:
50128
  /** Create a new, invalid array iterator. */
50129
  simdjson_inline array_iterator() noexcept = default;
50130
50131
  //
50132
  // Iterator interface
50133
  //
50134
50135
  /**
50136
   * Get the current element.
50137
   *
50138
   * Part of the std::iterator interface.
50139
   */
50140
  simdjson_inline simdjson_result<value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
50141
  /**
50142
   * Check if we are at the end of the JSON.
50143
   *
50144
   * Part of the std::iterator interface.
50145
   *
50146
   * @return true if there are no more elements in the JSON array.
50147
   */
50148
  simdjson_inline bool operator==(const array_iterator &) const noexcept;
50149
  /**
50150
   * Check if there are more elements in the JSON array.
50151
   *
50152
   * Part of the std::iterator interface.
50153
   *
50154
   * @return true if there are more elements in the JSON array.
50155
   */
50156
  simdjson_inline bool operator!=(const array_iterator &) const noexcept;
50157
  /**
50158
   * Move to the next element.
50159
   *
50160
   * Part of the std::iterator interface.
50161
   */
50162
  simdjson_inline array_iterator &operator++() noexcept;
50163
50164
private:
50165
  value_iterator iter{};
50166
50167
  simdjson_inline array_iterator(const value_iterator &iter) noexcept;
50168
50169
  friend class array;
50170
  friend class value;
50171
  friend struct simdjson_result<array_iterator>;
50172
};
50173
50174
} // namespace ondemand
50175
} // namespace haswell
50176
} // namespace simdjson
50177
50178
namespace simdjson {
50179
50180
template<>
50181
struct simdjson_result<haswell::ondemand::array_iterator> : public haswell::implementation_simdjson_result_base<haswell::ondemand::array_iterator> {
50182
public:
50183
  simdjson_inline simdjson_result(haswell::ondemand::array_iterator &&value) noexcept; ///< @private
50184
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
50185
  simdjson_inline simdjson_result() noexcept = default;
50186
50187
  //
50188
  // Iterator interface
50189
  //
50190
50191
  simdjson_inline simdjson_result<haswell::ondemand::value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
50192
  simdjson_inline bool operator==(const simdjson_result<haswell::ondemand::array_iterator> &) const noexcept;
50193
  simdjson_inline bool operator!=(const simdjson_result<haswell::ondemand::array_iterator> &) const noexcept;
50194
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> &operator++() noexcept;
50195
};
50196
50197
} // namespace simdjson
50198
50199
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
50200
/* end file simdjson/generic/ondemand/array_iterator.h for haswell */
50201
/* including simdjson/generic/ondemand/document.h for haswell: #include "simdjson/generic/ondemand/document.h" */
50202
/* begin file simdjson/generic/ondemand/document.h for haswell */
50203
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
50204
50205
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
50206
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */
50207
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
50208
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
50209
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
50210
50211
namespace simdjson {
50212
namespace haswell {
50213
namespace ondemand {
50214
50215
/**
50216
 * A JSON document. It holds a json_iterator instance.
50217
 *
50218
 * Used by tokens to get text, and string buffer location.
50219
 *
50220
 * You must keep the document around during iteration.
50221
 */
50222
class document {
50223
public:
50224
  /**
50225
   * Create a new invalid document.
50226
   *
50227
   * Exists so you can declare a variable and later assign to it before use.
50228
   */
50229
  simdjson_inline document() noexcept = default;
50230
  simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
50231
  simdjson_inline document(document &&other) noexcept = default;
50232
  simdjson_inline document &operator=(const document &other) noexcept = delete;
50233
  simdjson_inline document &operator=(document &&other) noexcept = default;
50234
50235
  /**
50236
   * Cast this JSON value to an array.
50237
   *
50238
   * @returns An object that can be used to iterate the array.
50239
   * @returns INCORRECT_TYPE If the JSON value is not an array.
50240
   */
50241
  simdjson_inline simdjson_result<array> get_array() & noexcept;
50242
  /**
50243
   * Cast this JSON value to an object.
50244
   *
50245
   * @returns An object that can be used to look up or iterate fields.
50246
   * @returns INCORRECT_TYPE If the JSON value is not an object.
50247
   */
50248
  simdjson_inline simdjson_result<object> get_object() & noexcept;
50249
  /**
50250
   * Cast this JSON value to an unsigned integer.
50251
   *
50252
   * @returns A signed 64-bit integer.
50253
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
50254
   */
50255
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
50256
  /**
50257
   * Cast this JSON value (inside string) to an unsigned integer.
50258
   *
50259
   * @returns A signed 64-bit integer.
50260
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
50261
   */
50262
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
50263
  /**
50264
   * Cast this JSON value to a signed integer.
50265
   *
50266
   * @returns A signed 64-bit integer.
50267
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
50268
   */
50269
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
50270
  /**
50271
   * Cast this JSON value (inside string) to a signed integer.
50272
   *
50273
   * @returns A signed 64-bit integer.
50274
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
50275
   */
50276
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
50277
  /**
50278
   * Cast this JSON value to a double.
50279
   *
50280
   * @returns A double.
50281
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
50282
   */
50283
  simdjson_inline simdjson_result<double> get_double() noexcept;
50284
50285
  /**
50286
   * Cast this JSON value (inside string) to a double.
50287
   *
50288
   * @returns A double.
50289
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
50290
   */
50291
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
50292
  /**
50293
   * Cast this JSON value to a string.
50294
   *
50295
   * The string is guaranteed to be valid UTF-8.
50296
   *
50297
   * Important: Calling get_string() twice on the same document is an error.
50298
   *
50299
   * @param Whether to allow a replacement character for unmatched surrogate pairs.
50300
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
50301
   *          time it parses a document or when it is destroyed.
50302
   * @returns INCORRECT_TYPE if the JSON value is not a string.
50303
   */
50304
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
50305
  /**
50306
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
50307
   *
50308
   * The string is guaranteed to be valid UTF-8.
50309
   *
50310
   * Important: a value should be consumed once. Calling get_string() twice on the same value
50311
   * is an error.
50312
   *
50313
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
50314
   * We recommend you avoid allocating an std::string unless you need to.
50315
   *
50316
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
50317
   */
50318
  template <typename string_type>
50319
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
50320
  /**
50321
   * Cast this JSON value to a string.
50322
   *
50323
   * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/
50324
   *
50325
   * Important: Calling get_wobbly_string() twice on the same document is an error.
50326
   *
50327
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
50328
   *          time it parses a document or when it is destroyed.
50329
   * @returns INCORRECT_TYPE if the JSON value is not a string.
50330
   */
50331
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
50332
  /**
50333
   * Cast this JSON value to a raw_json_string.
50334
   *
50335
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
50336
   *
50337
   * @returns A pointer to the raw JSON for the given string.
50338
   * @returns INCORRECT_TYPE if the JSON value is not a string.
50339
   */
50340
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
50341
  /**
50342
   * Cast this JSON value to a bool.
50343
   *
50344
   * @returns A bool value.
50345
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
50346
   */
50347
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
50348
  /**
50349
   * Cast this JSON value to a value when the document is an object or an array.
50350
   *
50351
   * You must not have begun iterating through the object or array. When
50352
   * SIMDJSON_DEVELOPMENT_CHECKS is set to 1 (which is the case when building in Debug mode
50353
   * by default), and you have already begun iterating,
50354
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
50355
   * rewind() to reset the document to its initial state before calling this method.
50356
   *
50357
   * @returns A value if a JSON array or object cannot be found.
50358
   * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
50359
   */
50360
  simdjson_inline simdjson_result<value> get_value() noexcept;
50361
50362
  /**
50363
   * Checks if this JSON value is null.  If and only if the value is
50364
   * null, then it is consumed (we advance). If we find a token that
50365
   * begins with 'n' but is not 'null', then an error is returned.
50366
   *
50367
   * @returns Whether the value is null.
50368
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
50369
   */
50370
  simdjson_inline simdjson_result<bool> is_null() noexcept;
50371
50372
  /**
50373
   * Get this value as the given type.
50374
   *
50375
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
50376
   *
50377
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
50378
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
50379
   *
50380
   * @returns A value of the given type, parsed from the JSON.
50381
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
50382
   */
50383
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
50384
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
50385
    // immediately fail.
50386
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
50387
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
50388
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
50389
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
50390
      " You may also add support for custom types, see our documentation.");
50391
  }
50392
  /** @overload template<typename T> simdjson_result<T> get() & noexcept */
50393
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
50394
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
50395
    // immediately fail.
50396
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
50397
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
50398
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
50399
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
50400
      " You may also add support for custom types, see our documentation.");
50401
  }
50402
50403
  /**
50404
   * Get this value as the given type.
50405
   *
50406
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
50407
   *
50408
   * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
50409
   *
50410
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
50411
   * @returns INCORRECT_TYPE If the JSON value is not an object.
50412
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
50413
   */
50414
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
50415
  /** @overload template<typename T> error_code get(T &out) & noexcept */
50416
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
50417
50418
#if SIMDJSON_EXCEPTIONS
50419
  /**
50420
   * Cast this JSON value to an instance of type T. The programmer is responsible for
50421
   * providing an implementation of get<T> for the type T, if T is not one of the types
50422
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.)
50423
   *
50424
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
50425
   *
50426
   * @returns An instance of type T
50427
   */
50428
  template <class T>
50429
  explicit simdjson_inline operator T() noexcept(false);
50430
  /**
50431
   * Cast this JSON value to an array.
50432
   *
50433
   * @returns An object that can be used to iterate the array.
50434
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
50435
   */
50436
  simdjson_inline operator array() & noexcept(false);
50437
  /**
50438
   * Cast this JSON value to an object.
50439
   *
50440
   * @returns An object that can be used to look up or iterate fields.
50441
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
50442
   */
50443
  simdjson_inline operator object() & noexcept(false);
50444
  /**
50445
   * Cast this JSON value to an unsigned integer.
50446
   *
50447
   * @returns A signed 64-bit integer.
50448
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
50449
   */
50450
  simdjson_inline operator uint64_t() noexcept(false);
50451
  /**
50452
   * Cast this JSON value to a signed integer.
50453
   *
50454
   * @returns A signed 64-bit integer.
50455
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
50456
   */
50457
  simdjson_inline operator int64_t() noexcept(false);
50458
  /**
50459
   * Cast this JSON value to a double.
50460
   *
50461
   * @returns A double.
50462
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
50463
   */
50464
  simdjson_inline operator double() noexcept(false);
50465
  /**
50466
   * Cast this JSON value to a string.
50467
   *
50468
   * The string is guaranteed to be valid UTF-8.
50469
   *
50470
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
50471
   *          time it parses a document or when it is destroyed.
50472
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
50473
   */
50474
  simdjson_inline operator std::string_view() noexcept(false);
50475
  /**
50476
   * Cast this JSON value to a raw_json_string.
50477
   *
50478
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
50479
   *
50480
   * @returns A pointer to the raw JSON for the given string.
50481
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
50482
   */
50483
  simdjson_inline operator raw_json_string() noexcept(false);
50484
  /**
50485
   * Cast this JSON value to a bool.
50486
   *
50487
   * @returns A bool value.
50488
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
50489
   */
50490
  simdjson_inline operator bool() noexcept(false);
50491
  /**
50492
   * Cast this JSON value to a value when the document is an object or an array.
50493
   *
50494
   * You must not have begun iterating through the object or array. When
50495
   * SIMDJSON_DEVELOPMENT_CHECKS is defined, and you have already begun iterating,
50496
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
50497
   * rewind() to reset the document to its initial state before calling this method.
50498
   *
50499
   * @returns A value value if a JSON array or object cannot be found.
50500
   * @exception SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
50501
   */
50502
  simdjson_inline operator value() noexcept(false);
50503
#endif
50504
  /**
50505
   * This method scans the array and counts the number of elements.
50506
   * The count_elements method should always be called before you have begun
50507
   * iterating through the array: it is expected that you are pointing at
50508
   * the beginning of the array.
50509
   * The runtime complexity is linear in the size of the array. After
50510
   * calling this function, if successful, the array is 'rewinded' at its
50511
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
50512
   * there is a missing comma), then an error is returned and it is no longer
50513
   * safe to continue.
50514
   */
50515
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
50516
   /**
50517
   * This method scans the object and counts the number of key-value pairs.
50518
   * The count_fields method should always be called before you have begun
50519
   * iterating through the object: it is expected that you are pointing at
50520
   * the beginning of the object.
50521
   * The runtime complexity is linear in the size of the object. After
50522
   * calling this function, if successful, the object is 'rewinded' at its
50523
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
50524
   * there is a missing comma), then an error is returned and it is no longer
50525
   * safe to continue.
50526
   *
50527
   * To check that an object is empty, it is more performant to use
50528
   * the is_empty() method.
50529
   */
50530
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
50531
  /**
50532
   * Get the value at the given index in the array. This function has linear-time complexity.
50533
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
50534
   *
50535
   * @return The value at the given index, or:
50536
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
50537
   */
50538
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
50539
  /**
50540
   * Begin array iteration.
50541
   *
50542
   * Part of the std::iterable interface.
50543
   */
50544
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
50545
  /**
50546
   * Sentinel representing the end of the array.
50547
   *
50548
   * Part of the std::iterable interface.
50549
   */
50550
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
50551
50552
  /**
50553
   * Look up a field by name on an object (order-sensitive).
50554
   *
50555
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
50556
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
50557
   *
50558
   * ```c++
50559
   * simdjson::ondemand::parser parser;
50560
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
50561
   * double z = obj.find_field("z");
50562
   * double y = obj.find_field("y");
50563
   * double x = obj.find_field("x");
50564
   * ```
50565
   *
50566
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
50567
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
50568
   *
50569
   *
50570
   * You must consume the fields on an object one at a time. A request for a new key
50571
   * invalidates previous field values: it makes them unsafe. E.g., the array
50572
   * given by content["bids"].get_array() should not be accessed after you have called
50573
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
50574
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
50575
   * OUT_OF_ORDER_ITERATION error is generated.
50576
   *
50577
   * You are expected to access keys only once. You should access the value corresponding to
50578
   * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
50579
   * is an error.
50580
   *
50581
   * @param key The key to look up.
50582
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
50583
   */
50584
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
50585
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
50586
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
50587
50588
  /**
50589
   * Look up a field by name on an object, without regard to key order.
50590
   *
50591
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
50592
   * and often appears negligible. It starts out normally, starting out at the last field; but if
50593
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
50594
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
50595
   * in question is large. The fact that the extra code is there also bumps the executable size.
50596
   *
50597
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
50598
   * default behavior failed to look up a field just because it was in the wrong order--and many
50599
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
50600
   *
50601
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
50602
   * field was not there when they are not in order).
50603
   *
50604
   * You must consume the fields on an object one at a time. A request for a new key
50605
   * invalidates previous field values: it makes them unsafe. E.g., the array
50606
   * given by content["bids"].get_array() should not be accessed after you have called
50607
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
50608
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
50609
   * OUT_OF_ORDER_ITERATION error is generated.
50610
   *
50611
   * You are expected to access keys only once. You should access the value corresponding to a key
50612
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
50613
   * is an error.
50614
   *
50615
   * @param key The key to look up.
50616
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
50617
   */
50618
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
50619
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
50620
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
50621
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
50622
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
50623
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
50624
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
50625
50626
  /**
50627
   * Get the type of this JSON value. It does not validate or consume the value.
50628
   * E.g., you must still call "is_null()" to check that a value is null even if
50629
   * "type()" returns json_type::null.
50630
   *
50631
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
50632
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
50633
   * let it throw an exception).
50634
   *
50635
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
50636
   */
50637
  simdjson_inline simdjson_result<json_type> type() noexcept;
50638
50639
  /**
50640
   * Checks whether the document is a scalar (string, number, null, Boolean).
50641
   * Returns false when there it is an array or object.
50642
   *
50643
   * @returns true if the type is string, number, null, Boolean
50644
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
50645
   */
50646
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
50647
50648
  /**
50649
   * Checks whether the document is a string.
50650
   *
50651
   * @returns true if the type is string
50652
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
50653
   */
50654
  simdjson_inline simdjson_result<bool> is_string() noexcept;
50655
50656
  /**
50657
   * Checks whether the document is a negative number.
50658
   *
50659
   * @returns true if the number if negative.
50660
   */
50661
  simdjson_inline bool is_negative() noexcept;
50662
  /**
50663
   * Checks whether the document is an integer number. Note that
50664
   * this requires to partially parse the number string. If
50665
   * the value is determined to be an integer, it may still
50666
   * not parse properly as an integer in subsequent steps
50667
   * (e.g., it might overflow).
50668
   *
50669
   * @returns true if the number if negative.
50670
   */
50671
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
50672
  /**
50673
   * Determine the number type (integer or floating-point number) as quickly
50674
   * as possible. This function does not fully validate the input. It is
50675
   * useful when you only need to classify the numbers, without parsing them.
50676
   *
50677
   * If you are planning to retrieve the value or you need full validation,
50678
   * consider using the get_number() method instead: it will fully parse
50679
   * and validate the input, and give you access to the type:
50680
   * get_number().get_number_type().
50681
   *
50682
   * get_number_type() is number_type::unsigned_integer if we have
50683
   * an integer greater or equal to 9223372036854775808 and no larger than 18446744073709551615.
50684
   * get_number_type() is number_type::signed_integer if we have an
50685
   * integer that is less than 9223372036854775808 and greater or equal to -9223372036854775808.
50686
   * get_number_type() is number_type::big_integer if we have an integer outside
50687
   * of those ranges (either larger than 18446744073709551615 or smaller than -9223372036854775808).
50688
   * Otherwise, get_number_type() has value number_type::floating_point_number
50689
   *
50690
   * This function requires processing the number string, but it is expected
50691
   * to be faster than get_number().get_number_type() because it is does not
50692
   * parse the number value.
50693
   *
50694
   * @returns the type of the number
50695
   */
50696
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
50697
50698
  /**
50699
   * Attempt to parse an ondemand::number. An ondemand::number may
50700
   * contain an integer value or a floating-point value, the simdjson
50701
   * library will autodetect the type. Thus it is a dynamically typed
50702
   * number. Before accessing the value, you must determine the detected
50703
   * type.
50704
   *
50705
   * number.get_number_type() is number_type::signed_integer if we have
50706
   * an integer in [-9223372036854775808,9223372036854775808)
50707
   * You can recover the value by calling number.get_int64() and you
50708
   * have that number.is_int64() is true.
50709
   *
50710
   * number.get_number_type() is number_type::unsigned_integer if we have
50711
   * an integer in [9223372036854775808,18446744073709551616)
50712
   * You can recover the value by calling number.get_uint64() and you
50713
   * have that number.is_uint64() is true.
50714
   *
50715
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
50716
   * and we have a binary64 number.
50717
   * You can recover the value by calling number.get_double() and you
50718
   * have that number.is_double() is true.
50719
   *
50720
   * You must check the type before accessing the value: it is an error
50721
   * to call "get_int64()" when number.get_number_type() is not
50722
   * number_type::signed_integer and when number.is_int64() is false.
50723
   */
50724
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
50725
50726
  /**
50727
   * Get the raw JSON for this token.
50728
   *
50729
   * The string_view will always point into the input buffer.
50730
   *
50731
   * The string_view will start at the beginning of the token, and include the entire token
50732
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
50733
   * string token always begins with a " and is always terminated by the final ", possibly
50734
   * followed by a number of spaces.
50735
   *
50736
   * The string_view is *not* null-terminated. If this is a scalar (string, number,
50737
   * boolean, or null), the character after the end of the string_view may be the padded buffer.
50738
   *
50739
   * Tokens include:
50740
   * - {
50741
   * - [
50742
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
50743
   * - -1.2e-100
50744
   * - true
50745
   * - false
50746
   * - null
50747
   */
50748
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
50749
50750
  /**
50751
   * Reset the iterator inside the document instance so we are pointing back at the
50752
   * beginning of the document, as if it had just been created. It invalidates all
50753
   * values, objects and arrays that you have created so far (including unescaped strings).
50754
   */
50755
  inline void rewind() noexcept;
50756
  /**
50757
   * Returns debugging information.
50758
   */
50759
  inline std::string to_debug_string() noexcept;
50760
  /**
50761
   * Some unrecoverable error conditions may render the document instance unusable.
50762
   * The is_alive() method returns true when the document is still suitable.
50763
   */
50764
  inline bool is_alive() noexcept;
50765
50766
  /**
50767
   * Returns the current location in the document if in bounds.
50768
   */
50769
  inline simdjson_result<const char *> current_location() const noexcept;
50770
50771
  /**
50772
   * Returns true if this document has been fully parsed.
50773
   * If you have consumed the whole document and at_end() returns
50774
   * false, then there may be trailing content.
50775
   */
50776
  inline bool at_end() const noexcept;
50777
50778
  /**
50779
   * Returns the current depth in the document if in bounds.
50780
   *
50781
   * E.g.,
50782
   *  0 = finished with document
50783
   *  1 = document root value (could be [ or {, not yet known)
50784
   *  2 = , or } inside root array/object
50785
   *  3 = key or value inside root array/object.
50786
   */
50787
  simdjson_inline int32_t current_depth() const noexcept;
50788
50789
  /**
50790
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
50791
   * https://tools.ietf.org/html/rfc6901 standard.
50792
   *
50793
   *   ondemand::parser parser;
50794
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
50795
   *   auto doc = parser.iterate(json);
50796
   *   doc.at_pointer("/foo/a/1") == 20
50797
   *
50798
   * It is allowed for a key to be the empty string:
50799
   *
50800
   *   ondemand::parser parser;
50801
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
50802
   *   auto doc = parser.iterate(json);
50803
   *   doc.at_pointer("//a/1") == 20
50804
   *
50805
   * Key values are matched exactly, without unescaping or Unicode normalization.
50806
   * We do a byte-by-byte comparison. E.g.
50807
   *
50808
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
50809
   *   auto doc = parser.iterate(json);
50810
   *   doc.at_pointer("/\\u00E9") == 123
50811
   *   doc.at_pointer((const char*)u8"/\u00E9") returns an error (NO_SUCH_FIELD)
50812
   *
50813
   * Note that at_pointer() automatically calls rewind between each call. Thus
50814
   * all values, objects and arrays that you have created so far (including unescaped strings)
50815
   * are invalidated. After calling at_pointer, you need to consume the result: string values
50816
   * should be stored in your own variables, arrays should be decoded and stored in your own array-like
50817
   * structures and so forth.
50818
   *
50819
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
50820
   *
50821
   * @return The value associated with the given JSON pointer, or:
50822
   *         - NO_SUCH_FIELD if a field does not exist in an object
50823
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
50824
   *         - INCORRECT_TYPE if a non-integer is used to access an array
50825
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
50826
   *         - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
50827
   */
50828
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
50829
50830
  /**
50831
   * Get the value associated with the given JSONPath expression. We only support
50832
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
50833
   * names and array indices.
50834
   *
50835
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
50836
   *
50837
   * Key values are matched exactly, without unescaping or Unicode normalization.
50838
   * We do a byte-by-byte comparison. E.g.
50839
   *
50840
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
50841
   *   auto doc = parser.iterate(json);
50842
   *   doc.at_path(".\\u00E9") == 123
50843
   *   doc.at_path((const char*)u8".\u00E9") returns an error (NO_SUCH_FIELD)
50844
   *
50845
   * @return The value associated with the given JSONPath expression, or:
50846
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
50847
   *         - NO_SUCH_FIELD if a field does not exist in an object
50848
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
50849
   *         - INCORRECT_TYPE if a non-integer is used to access an array
50850
   */
50851
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
50852
50853
  /**
50854
   * Consumes the document and returns a string_view instance corresponding to the
50855
   * document as represented in JSON. It points inside the original byte array containing
50856
   * the JSON document.
50857
   */
50858
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
50859
protected:
50860
  /**
50861
   * Consumes the document.
50862
   */
50863
  simdjson_inline error_code consume() noexcept;
50864
50865
  simdjson_inline document(ondemand::json_iterator &&iter) noexcept;
50866
  simdjson_inline const uint8_t *text(uint32_t idx) const noexcept;
50867
50868
  simdjson_inline value_iterator resume_value_iterator() noexcept;
50869
  simdjson_inline value_iterator get_root_value_iterator() noexcept;
50870
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
50871
  static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept;
50872
50873
  //
50874
  // Fields
50875
  //
50876
  json_iterator iter{}; ///< Current position in the document
50877
  static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0
50878
50879
  friend class array_iterator;
50880
  friend class value;
50881
  friend class ondemand::parser;
50882
  friend class object;
50883
  friend class array;
50884
  friend class field;
50885
  friend class token;
50886
  friend class document_stream;
50887
  friend class document_reference;
50888
};
50889
50890
50891
/**
50892
 * A document_reference is a thin wrapper around a document reference instance.
50893
 */
50894
class document_reference {
50895
public:
50896
  simdjson_inline document_reference() noexcept;
50897
  simdjson_inline document_reference(document &d) noexcept;
50898
  simdjson_inline document_reference(const document_reference &other) noexcept = default;
50899
  simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default;
50900
  simdjson_inline void rewind() noexcept;
50901
  simdjson_inline simdjson_result<array> get_array() & noexcept;
50902
  simdjson_inline simdjson_result<object> get_object() & noexcept;
50903
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
50904
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
50905
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
50906
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
50907
  simdjson_inline simdjson_result<double> get_double() noexcept;
50908
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
50909
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
50910
  template <typename string_type>
50911
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
50912
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
50913
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
50914
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
50915
  simdjson_inline simdjson_result<value> get_value() noexcept;
50916
50917
  simdjson_inline simdjson_result<bool> is_null() noexcept;
50918
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
50919
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
50920
  simdjson_inline operator document&() const noexcept;
50921
#if SIMDJSON_EXCEPTIONS
50922
  template <class T>
50923
  explicit simdjson_inline operator T() noexcept(false);
50924
  simdjson_inline operator array() & noexcept(false);
50925
  simdjson_inline operator object() & noexcept(false);
50926
  simdjson_inline operator uint64_t() noexcept(false);
50927
  simdjson_inline operator int64_t() noexcept(false);
50928
  simdjson_inline operator double() noexcept(false);
50929
  simdjson_inline operator std::string_view() noexcept(false);
50930
  simdjson_inline operator raw_json_string() noexcept(false);
50931
  simdjson_inline operator bool() noexcept(false);
50932
  simdjson_inline operator value() noexcept(false);
50933
#endif
50934
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
50935
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
50936
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
50937
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
50938
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
50939
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
50940
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
50941
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
50942
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
50943
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
50944
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
50945
50946
  simdjson_inline simdjson_result<json_type> type() noexcept;
50947
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
50948
  simdjson_inline simdjson_result<bool> is_string() noexcept;
50949
50950
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
50951
  simdjson_inline int32_t current_depth() const noexcept;
50952
  simdjson_inline bool is_negative() noexcept;
50953
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
50954
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
50955
  simdjson_inline simdjson_result<number> get_number() noexcept;
50956
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
50957
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
50958
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
50959
50960
private:
50961
  document *doc{nullptr};
50962
};
50963
} // namespace ondemand
50964
} // namespace haswell
50965
} // namespace simdjson
50966
50967
namespace simdjson {
50968
50969
template<>
50970
struct simdjson_result<haswell::ondemand::document> : public haswell::implementation_simdjson_result_base<haswell::ondemand::document> {
50971
public:
50972
  simdjson_inline simdjson_result(haswell::ondemand::document &&value) noexcept; ///< @private
50973
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
50974
  simdjson_inline simdjson_result() noexcept = default;
50975
  simdjson_inline error_code rewind() noexcept;
50976
50977
  simdjson_inline simdjson_result<haswell::ondemand::array> get_array() & noexcept;
50978
  simdjson_inline simdjson_result<haswell::ondemand::object> get_object() & noexcept;
50979
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
50980
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
50981
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
50982
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
50983
  simdjson_inline simdjson_result<double> get_double() noexcept;
50984
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
50985
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
50986
  template <typename string_type>
50987
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
50988
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
50989
  simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> get_raw_json_string() noexcept;
50990
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
50991
  simdjson_inline simdjson_result<haswell::ondemand::value> get_value() noexcept;
50992
  simdjson_inline simdjson_result<bool> is_null() noexcept;
50993
50994
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
50995
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept;
50996
50997
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
50998
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
50999
#if SIMDJSON_EXCEPTIONS
51000
  template <class T, typename std::enable_if<std::is_same<T, haswell::ondemand::document>::value == false>::type>
51001
  explicit simdjson_inline operator T() noexcept(false);
51002
  simdjson_inline operator haswell::ondemand::array() & noexcept(false);
51003
  simdjson_inline operator haswell::ondemand::object() & noexcept(false);
51004
  simdjson_inline operator uint64_t() noexcept(false);
51005
  simdjson_inline operator int64_t() noexcept(false);
51006
  simdjson_inline operator double() noexcept(false);
51007
  simdjson_inline operator std::string_view() noexcept(false);
51008
  simdjson_inline operator haswell::ondemand::raw_json_string() noexcept(false);
51009
  simdjson_inline operator bool() noexcept(false);
51010
  simdjson_inline operator haswell::ondemand::value() noexcept(false);
51011
#endif
51012
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
51013
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
51014
  simdjson_inline simdjson_result<haswell::ondemand::value> at(size_t index) & noexcept;
51015
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> begin() & noexcept;
51016
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> end() & noexcept;
51017
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(std::string_view key) & noexcept;
51018
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(const char *key) & noexcept;
51019
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](std::string_view key) & noexcept;
51020
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](const char *key) & noexcept;
51021
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
51022
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(const char *key) & noexcept;
51023
  simdjson_inline simdjson_result<haswell::ondemand::json_type> type() noexcept;
51024
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
51025
  simdjson_inline simdjson_result<bool> is_string() noexcept;
51026
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
51027
  simdjson_inline int32_t current_depth() const noexcept;
51028
  simdjson_inline bool at_end() const noexcept;
51029
  simdjson_inline bool is_negative() noexcept;
51030
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
51031
  simdjson_inline simdjson_result<haswell::number_type> get_number_type() noexcept;
51032
  simdjson_inline simdjson_result<haswell::ondemand::number> get_number() noexcept;
51033
  /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */
51034
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
51035
51036
  simdjson_inline simdjson_result<haswell::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
51037
  simdjson_inline simdjson_result<haswell::ondemand::value> at_path(std::string_view json_path) noexcept;
51038
};
51039
51040
51041
} // namespace simdjson
51042
51043
51044
51045
namespace simdjson {
51046
51047
template<>
51048
struct simdjson_result<haswell::ondemand::document_reference> : public haswell::implementation_simdjson_result_base<haswell::ondemand::document_reference> {
51049
public:
51050
  simdjson_inline simdjson_result(haswell::ondemand::document_reference value, error_code error) noexcept;
51051
  simdjson_inline simdjson_result() noexcept = default;
51052
  simdjson_inline error_code rewind() noexcept;
51053
51054
  simdjson_inline simdjson_result<haswell::ondemand::array> get_array() & noexcept;
51055
  simdjson_inline simdjson_result<haswell::ondemand::object> get_object() & noexcept;
51056
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
51057
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
51058
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
51059
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
51060
  simdjson_inline simdjson_result<double> get_double() noexcept;
51061
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
51062
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
51063
  template <typename string_type>
51064
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
51065
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
51066
  simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> get_raw_json_string() noexcept;
51067
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
51068
  simdjson_inline simdjson_result<haswell::ondemand::value> get_value() noexcept;
51069
  simdjson_inline simdjson_result<bool> is_null() noexcept;
51070
#if SIMDJSON_EXCEPTIONS
51071
  template <class T, typename std::enable_if<std::is_same<T, haswell::ondemand::document_reference>::value == false>::type>
51072
  explicit simdjson_inline operator T() noexcept(false);
51073
  simdjson_inline operator haswell::ondemand::array() & noexcept(false);
51074
  simdjson_inline operator haswell::ondemand::object() & noexcept(false);
51075
  simdjson_inline operator uint64_t() noexcept(false);
51076
  simdjson_inline operator int64_t() noexcept(false);
51077
  simdjson_inline operator double() noexcept(false);
51078
  simdjson_inline operator std::string_view() noexcept(false);
51079
  simdjson_inline operator haswell::ondemand::raw_json_string() noexcept(false);
51080
  simdjson_inline operator bool() noexcept(false);
51081
  simdjson_inline operator haswell::ondemand::value() noexcept(false);
51082
#endif
51083
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
51084
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
51085
  simdjson_inline simdjson_result<haswell::ondemand::value> at(size_t index) & noexcept;
51086
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> begin() & noexcept;
51087
  simdjson_inline simdjson_result<haswell::ondemand::array_iterator> end() & noexcept;
51088
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(std::string_view key) & noexcept;
51089
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(const char *key) & noexcept;
51090
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](std::string_view key) & noexcept;
51091
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](const char *key) & noexcept;
51092
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
51093
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(const char *key) & noexcept;
51094
  simdjson_inline simdjson_result<haswell::ondemand::json_type> type() noexcept;
51095
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
51096
  simdjson_inline simdjson_result<bool> is_string() noexcept;
51097
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
51098
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
51099
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
51100
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
51101
  simdjson_inline simdjson_result<haswell::number_type> get_number_type() noexcept;
51102
  simdjson_inline simdjson_result<haswell::ondemand::number> get_number() noexcept;
51103
  /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */
51104
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
51105
51106
  simdjson_inline simdjson_result<haswell::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
51107
  simdjson_inline simdjson_result<haswell::ondemand::value> at_path(std::string_view json_path) noexcept;
51108
};
51109
51110
51111
} // namespace simdjson
51112
51113
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
51114
/* end file simdjson/generic/ondemand/document.h for haswell */
51115
/* including simdjson/generic/ondemand/document_stream.h for haswell: #include "simdjson/generic/ondemand/document_stream.h" */
51116
/* begin file simdjson/generic/ondemand/document_stream.h for haswell */
51117
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
51118
51119
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
51120
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H */
51121
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
51122
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
51123
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
51124
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
51125
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
51126
51127
#ifdef SIMDJSON_THREADS_ENABLED
51128
#include <thread>
51129
#include <mutex>
51130
#include <condition_variable>
51131
#endif
51132
51133
namespace simdjson {
51134
namespace haswell {
51135
namespace ondemand {
51136
51137
#ifdef SIMDJSON_THREADS_ENABLED
51138
/** @private Custom worker class **/
51139
struct stage1_worker {
51140
  stage1_worker() noexcept = default;
51141
  stage1_worker(const stage1_worker&) = delete;
51142
  stage1_worker(stage1_worker&&) = delete;
51143
  stage1_worker operator=(const stage1_worker&) = delete;
51144
  ~stage1_worker();
51145
  /**
51146
   * We only start the thread when it is needed, not at object construction, this may throw.
51147
   * You should only call this once.
51148
   **/
51149
  void start_thread();
51150
  /**
51151
   * Start a stage 1 job. You should first call 'run', then 'finish'.
51152
   * You must call start_thread once before.
51153
   */
51154
  void run(document_stream * ds, parser * stage1, size_t next_batch_start);
51155
  /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
51156
  void finish();
51157
51158
private:
51159
51160
  /**
51161
   * Normally, we would never stop the thread. But we do in the destructor.
51162
   * This function is only safe assuming that you are not waiting for results. You
51163
   * should have called run, then finish, and be done.
51164
   **/
51165
  void stop_thread();
51166
51167
  std::thread thread{};
51168
  /** These three variables define the work done by the thread. **/
51169
  ondemand::parser * stage1_thread_parser{};
51170
  size_t _next_batch_start{};
51171
  document_stream * owner{};
51172
  /**
51173
   * We have two state variables. This could be streamlined to one variable in the future but
51174
   * we use two for clarity.
51175
   */
51176
  bool has_work{false};
51177
  bool can_work{true};
51178
51179
  /**
51180
   * We lock using a mutex.
51181
   */
51182
  std::mutex locking_mutex{};
51183
  std::condition_variable cond_var{};
51184
51185
  friend class document_stream;
51186
};
51187
#endif  // SIMDJSON_THREADS_ENABLED
51188
51189
/**
51190
 * A forward-only stream of documents.
51191
 *
51192
 * Produced by parser::iterate_many.
51193
 *
51194
 */
51195
class document_stream {
51196
public:
51197
  /**
51198
   * Construct an uninitialized document_stream.
51199
   *
51200
   *  ```c++
51201
   *  document_stream docs;
51202
   *  auto error = parser.iterate_many(json).get(docs);
51203
   *  ```
51204
   */
51205
  simdjson_inline document_stream() noexcept;
51206
  /** Move one document_stream to another. */
51207
  simdjson_inline document_stream(document_stream &&other) noexcept = default;
51208
  /** Move one document_stream to another. */
51209
  simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
51210
51211
  simdjson_inline ~document_stream() noexcept;
51212
51213
  /**
51214
   * Returns the input size in bytes.
51215
   */
51216
  inline size_t size_in_bytes() const noexcept;
51217
51218
  /**
51219
   * After iterating through the stream, this method
51220
   * returns the number of bytes that were not parsed at the end
51221
   * of the stream. If truncated_bytes() differs from zero,
51222
   * then the input was truncated maybe because incomplete JSON
51223
   * documents were found at the end of the stream. You
51224
   * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
51225
   *
51226
   * You should only call truncated_bytes() after streaming through all
51227
   * documents, like so:
51228
   *
51229
   *   document_stream stream = parser.iterate_many(json,window);
51230
   *   for(auto & doc : stream) {
51231
   *      // do something with doc
51232
   *   }
51233
   *   size_t truncated = stream.truncated_bytes();
51234
   *
51235
   */
51236
  inline size_t truncated_bytes() const noexcept;
51237
51238
  class iterator {
51239
  public:
51240
    using value_type = simdjson_result<document>;
51241
    using reference  = simdjson_result<ondemand::document_reference>;
51242
    using pointer    = void;
51243
    using difference_type   = std::ptrdiff_t;
51244
    using iterator_category = std::input_iterator_tag;
51245
51246
    /**
51247
     * Default constructor.
51248
     */
51249
    simdjson_inline iterator() noexcept;
51250
    /**
51251
     * Get the current document (or error).
51252
     */
51253
    simdjson_inline reference operator*() noexcept;
51254
    /**
51255
     * Advance to the next document (prefix).
51256
     */
51257
    inline iterator& operator++() noexcept;
51258
    /**
51259
     * Check if we're at the end yet.
51260
     * @param other the end iterator to compare to.
51261
     */
51262
    simdjson_inline bool operator!=(const iterator &other) const noexcept;
51263
    /**
51264
     * @private
51265
     *
51266
     * Gives the current index in the input document in bytes.
51267
     *
51268
     *   document_stream stream = parser.parse_many(json,window);
51269
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
51270
     *      auto doc = *i;
51271
     *      size_t index = i.current_index();
51272
     *   }
51273
     *
51274
     * This function (current_index()) is experimental and the usage
51275
     * may change in future versions of simdjson: we find the API somewhat
51276
     * awkward and we would like to offer something friendlier.
51277
     */
51278
     simdjson_inline size_t current_index() const noexcept;
51279
51280
     /**
51281
     * @private
51282
     *
51283
     * Gives a view of the current document at the current position.
51284
     *
51285
     *   document_stream stream = parser.iterate_many(json,window);
51286
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
51287
     *      std::string_view v = i.source();
51288
     *   }
51289
     *
51290
     * The returned string_view instance is simply a map to the (unparsed)
51291
     * source string: it may thus include white-space characters and all manner
51292
     * of padding.
51293
     *
51294
     * This function (source()) is experimental and the usage
51295
     * may change in future versions of simdjson: we find the API somewhat
51296
     * awkward and we would like to offer something friendlier.
51297
     *
51298
     */
51299
     simdjson_inline std::string_view source() const noexcept;
51300
51301
    /**
51302
     * Returns error of the stream (if any).
51303
     */
51304
     inline error_code error() const noexcept;
51305
51306
  private:
51307
    simdjson_inline iterator(document_stream *s, bool finished) noexcept;
51308
    /** The document_stream we're iterating through. */
51309
    document_stream* stream;
51310
    /** Whether we're finished or not. */
51311
    bool finished;
51312
51313
    friend class document;
51314
    friend class document_stream;
51315
    friend class json_iterator;
51316
  };
51317
51318
  /**
51319
   * Start iterating the documents in the stream.
51320
   */
51321
  simdjson_inline iterator begin() noexcept;
51322
  /**
51323
   * The end of the stream, for iterator comparison purposes.
51324
   */
51325
  simdjson_inline iterator end() noexcept;
51326
51327
private:
51328
51329
  document_stream &operator=(const document_stream &) = delete; // Disallow copying
51330
  document_stream(const document_stream &other) = delete; // Disallow copying
51331
51332
  /**
51333
   * Construct a document_stream. Does not allocate or parse anything until the iterator is
51334
   * used.
51335
   *
51336
   * @param parser is a reference to the parser instance used to generate this document_stream
51337
   * @param buf is the raw byte buffer we need to process
51338
   * @param len is the length of the raw byte buffer in bytes
51339
   * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
51340
   */
51341
  simdjson_inline document_stream(
51342
    ondemand::parser &parser,
51343
    const uint8_t *buf,
51344
    size_t len,
51345
    size_t batch_size,
51346
    bool allow_comma_separated
51347
  ) noexcept;
51348
51349
  /**
51350
   * Parse the first document in the buffer. Used by begin(), to handle allocation and
51351
   * initialization.
51352
   */
51353
  inline void start() noexcept;
51354
51355
  /**
51356
   * Parse the next document found in the buffer previously given to document_stream.
51357
   *
51358
   * The content should be a valid JSON document encoded as UTF-8. If there is a
51359
   * UTF-8 BOM, the parser skips it.
51360
   *
51361
   * You do NOT need to pre-allocate a parser.  This function takes care of
51362
   * pre-allocating a capacity defined by the batch_size defined when creating the
51363
   * document_stream object.
51364
   *
51365
   * The function returns simdjson::EMPTY if there is no more data to be parsed.
51366
   *
51367
   * The function returns simdjson::SUCCESS (as integer = 0) in case of success
51368
   * and indicates that the buffer has successfully been parsed to the end.
51369
   * Every document it contained has been parsed without error.
51370
   *
51371
   * The function returns an error code from simdjson/simdjson.h in case of failure
51372
   * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
51373
   * the simdjson::error_message function converts these error codes into a string).
51374
   *
51375
   * You can also check validity by calling parser.is_valid(). The same parser can
51376
   * and should be reused for the other documents in the buffer.
51377
   */
51378
  inline void next() noexcept;
51379
51380
  /** Move the json_iterator of the document to the location of the next document in the stream. */
51381
  inline void next_document() noexcept;
51382
51383
  /** Get the next document index. */
51384
  inline size_t next_batch_start() const noexcept;
51385
51386
  /** Pass the next batch through stage 1 with the given parser. */
51387
  inline error_code run_stage1(ondemand::parser &p, size_t batch_start) noexcept;
51388
51389
  // Fields
51390
  ondemand::parser *parser;
51391
  const uint8_t *buf;
51392
  size_t len;
51393
  size_t batch_size;
51394
  bool allow_comma_separated;
51395
  /**
51396
   * We are going to use just one document instance. The document owns
51397
   * the json_iterator. It implies that we only ever pass a reference
51398
   * to the document to the users.
51399
   */
51400
  document doc{};
51401
  /** The error (or lack thereof) from the current document. */
51402
  error_code error;
51403
  size_t batch_start{0};
51404
  size_t doc_index{};
51405
51406
  #ifdef SIMDJSON_THREADS_ENABLED
51407
  /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
51408
  bool use_thread;
51409
51410
  inline void load_from_stage1_thread() noexcept;
51411
51412
  /** Start a thread to run stage 1 on the next batch. */
51413
  inline void start_stage1_thread() noexcept;
51414
51415
  /** Wait for the stage 1 thread to finish and capture the results. */
51416
  inline void finish_stage1_thread() noexcept;
51417
51418
  /** The error returned from the stage 1 thread. */
51419
  error_code stage1_thread_error{UNINITIALIZED};
51420
  /** The thread used to run stage 1 against the next batch in the background. */
51421
  std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
51422
  /**
51423
   * The parser used to run stage 1 in the background. Will be swapped
51424
   * with the regular parser when finished.
51425
   */
51426
  ondemand::parser stage1_thread_parser{};
51427
51428
  friend struct stage1_worker;
51429
  #endif // SIMDJSON_THREADS_ENABLED
51430
51431
  friend class parser;
51432
  friend class document;
51433
  friend class json_iterator;
51434
  friend struct simdjson_result<ondemand::document_stream>;
51435
  friend struct internal::simdjson_result_base<ondemand::document_stream>;
51436
};  // document_stream
51437
51438
} // namespace ondemand
51439
} // namespace haswell
51440
} // namespace simdjson
51441
51442
namespace simdjson {
51443
template<>
51444
struct simdjson_result<haswell::ondemand::document_stream> : public haswell::implementation_simdjson_result_base<haswell::ondemand::document_stream> {
51445
public:
51446
  simdjson_inline simdjson_result(haswell::ondemand::document_stream &&value) noexcept; ///< @private
51447
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
51448
  simdjson_inline simdjson_result() noexcept = default;
51449
};
51450
51451
} // namespace simdjson
51452
51453
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
51454
/* end file simdjson/generic/ondemand/document_stream.h for haswell */
51455
/* including simdjson/generic/ondemand/field.h for haswell: #include "simdjson/generic/ondemand/field.h" */
51456
/* begin file simdjson/generic/ondemand/field.h for haswell */
51457
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
51458
51459
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
51460
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_H */
51461
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
51462
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
51463
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
51464
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
51465
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
51466
51467
namespace simdjson {
51468
namespace haswell {
51469
namespace ondemand {
51470
51471
/**
51472
 * A JSON field (key/value pair) in an object.
51473
 *
51474
 * Returned from object iteration.
51475
 *
51476
 * Extends from std::pair<raw_json_string, value> so you can use C++ algorithms that rely on pairs.
51477
 */
51478
class field : public std::pair<raw_json_string, value> {
51479
public:
51480
  /**
51481
   * Create a new invalid field.
51482
   *
51483
   * Exists so you can declare a variable and later assign to it before use.
51484
   */
51485
  simdjson_inline field() noexcept;
51486
51487
  /**
51488
   * Get the key as a string_view (for higher speed, consider raw_key).
51489
   * We deliberately use a more cumbersome name (unescaped_key) to force users
51490
   * to think twice about using it.
51491
   *
51492
   * This consumes the key: once you have called unescaped_key(), you cannot
51493
   * call it again nor can you call key().
51494
   */
51495
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescaped_key(bool allow_replacement) noexcept;
51496
  /**
51497
   * Get the key as a raw_json_string. Can be used for direct comparison with
51498
   * an unescaped C string: e.g., key() == "test".
51499
   */
51500
  simdjson_inline raw_json_string key() const noexcept;
51501
  /**
51502
   * Get the unprocessed key as a string_view. This includes the quotes and may include
51503
   * some spaces after the last quote.
51504
   */
51505
  simdjson_inline std::string_view key_raw_json_token() const noexcept;
51506
  /**
51507
   * Get the field value.
51508
   */
51509
  simdjson_inline ondemand::value &value() & noexcept;
51510
  /**
51511
   * @overload ondemand::value &ondemand::value() & noexcept
51512
   */
51513
  simdjson_inline ondemand::value value() && noexcept;
51514
51515
protected:
51516
  simdjson_inline field(raw_json_string key, ondemand::value &&value) noexcept;
51517
  static simdjson_inline simdjson_result<field> start(value_iterator &parent_iter) noexcept;
51518
  static simdjson_inline simdjson_result<field> start(const value_iterator &parent_iter, raw_json_string key) noexcept;
51519
  friend struct simdjson_result<field>;
51520
  friend class object_iterator;
51521
};
51522
51523
} // namespace ondemand
51524
} // namespace haswell
51525
} // namespace simdjson
51526
51527
namespace simdjson {
51528
51529
template<>
51530
struct simdjson_result<haswell::ondemand::field> : public haswell::implementation_simdjson_result_base<haswell::ondemand::field> {
51531
public:
51532
  simdjson_inline simdjson_result(haswell::ondemand::field &&value) noexcept; ///< @private
51533
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
51534
  simdjson_inline simdjson_result() noexcept = default;
51535
51536
  simdjson_inline simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
51537
  simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> key() noexcept;
51538
  simdjson_inline simdjson_result<std::string_view> key_raw_json_token() noexcept;
51539
  simdjson_inline simdjson_result<haswell::ondemand::value> value() noexcept;
51540
};
51541
51542
} // namespace simdjson
51543
51544
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_H
51545
/* end file simdjson/generic/ondemand/field.h for haswell */
51546
/* including simdjson/generic/ondemand/object.h for haswell: #include "simdjson/generic/ondemand/object.h" */
51547
/* begin file simdjson/generic/ondemand/object.h for haswell */
51548
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
51549
51550
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
51551
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_H */
51552
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
51553
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
51554
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
51555
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
51556
51557
namespace simdjson {
51558
namespace haswell {
51559
namespace ondemand {
51560
51561
/**
51562
 * A forward-only JSON object field iterator.
51563
 */
51564
class object {
51565
public:
51566
  /**
51567
   * Create a new invalid object.
51568
   *
51569
   * Exists so you can declare a variable and later assign to it before use.
51570
   */
51571
  simdjson_inline object() noexcept = default;
51572
51573
  simdjson_inline simdjson_result<object_iterator> begin() noexcept;
51574
  simdjson_inline simdjson_result<object_iterator> end() noexcept;
51575
  /**
51576
   * Look up a field by name on an object (order-sensitive).
51577
   *
51578
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
51579
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
51580
   *
51581
   * ```c++
51582
   * simdjson::ondemand::parser parser;
51583
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
51584
   * double z = obj.find_field("z");
51585
   * double y = obj.find_field("y");
51586
   * double x = obj.find_field("x");
51587
   * ```
51588
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
51589
   * that only one field is returned.
51590
   *
51591
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
51592
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
51593
   *
51594
   * You must consume the fields on an object one at a time. A request for a new key
51595
   * invalidates previous field values: it makes them unsafe. The value instance you get
51596
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
51597
   * given by content["bids"].get_array() should not be accessed after you have called
51598
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
51599
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
51600
   * OUT_OF_ORDER_ITERATION error is generated.
51601
   *
51602
   * You are expected to access keys only once. You should access the value corresponding to a
51603
   * key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
51604
   * is an error.
51605
   *
51606
   * @param key The key to look up.
51607
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
51608
   */
51609
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
51610
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
51611
  simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
51612
51613
  /**
51614
   * Look up a field by name on an object, without regard to key order.
51615
   *
51616
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
51617
   * and often appears negligible. It starts out normally, starting out at the last field; but if
51618
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
51619
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
51620
   * in question is large. The fact that the extra code is there also bumps the executable size.
51621
   *
51622
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
51623
   * default behavior failed to look up a field just because it was in the wrong order--and many
51624
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
51625
   *
51626
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
51627
   * field was not there when they are not in order).
51628
   *
51629
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
51630
   * that only one field is returned.
51631
   *
51632
   * You must consume the fields on an object one at a time. A request for a new key
51633
   * invalidates previous field values: it makes them unsafe. The value instance you get
51634
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
51635
   * given by content["bids"].get_array() should not be accessed after you have called
51636
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
51637
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
51638
   * OUT_OF_ORDER_ITERATION error is generated.
51639
   *
51640
   * You are expected to access keys only once. You should access the value corresponding to a key
51641
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
51642
   *
51643
   * @param key The key to look up.
51644
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
51645
   */
51646
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
51647
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
51648
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
51649
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
51650
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
51651
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
51652
  simdjson_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
51653
51654
  /**
51655
   * Get the value associated with the given JSON pointer. We use the RFC 6901
51656
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
51657
   * as the root of its own JSON document.
51658
   *
51659
   *   ondemand::parser parser;
51660
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
51661
   *   auto doc = parser.iterate(json);
51662
   *   doc.at_pointer("/foo/a/1") == 20
51663
   *
51664
   * It is allowed for a key to be the empty string:
51665
   *
51666
   *   ondemand::parser parser;
51667
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
51668
   *   auto doc = parser.iterate(json);
51669
   *   doc.at_pointer("//a/1") == 20
51670
   *
51671
   * Note that at_pointer() called on the document automatically calls the document's rewind
51672
   * method between each call. It invalidates all previously accessed arrays, objects and values
51673
   * that have not been consumed. Yet it is not the case when calling at_pointer on an object
51674
   * instance: there is no rewind and no invalidation.
51675
   *
51676
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
51677
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
51678
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
51679
   *
51680
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
51681
   *
51682
   * @return The value associated with the given JSON pointer, or:
51683
   *         - NO_SUCH_FIELD if a field does not exist in an object
51684
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
51685
   *         - INCORRECT_TYPE if a non-integer is used to access an array
51686
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
51687
   */
51688
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
51689
51690
  /**
51691
   * Get the value associated with the given JSONPath expression. We only support
51692
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
51693
   * names and array indices.
51694
   *
51695
   * @return The value associated with the given JSONPath expression, or:
51696
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
51697
   *         - NO_SUCH_FIELD if a field does not exist in an object
51698
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
51699
   *         - INCORRECT_TYPE if a non-integer is used to access an array
51700
   */
51701
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
51702
51703
  /**
51704
   * Reset the iterator so that we are pointing back at the
51705
   * beginning of the object. You should still consume values only once even if you
51706
   * can iterate through the object more than once. If you unescape a string within
51707
   * the object more than once, you have unsafe code. Note that rewinding an object
51708
   * means that you may need to reparse it anew: it is not a free operation.
51709
   *
51710
   * @returns true if the object contains some elements (not empty)
51711
   */
51712
  inline simdjson_result<bool> reset() & noexcept;
51713
  /**
51714
   * This method scans the beginning of the object and checks whether the
51715
   * object is empty.
51716
   * The runtime complexity is constant time. After
51717
   * calling this function, if successful, the object is 'rewinded' at its
51718
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
51719
   * there is a missing comma), then an error is returned and it is no longer
51720
   * safe to continue.
51721
   */
51722
  inline simdjson_result<bool> is_empty() & noexcept;
51723
  /**
51724
   * This method scans the object and counts the number of key-value pairs.
51725
   * The count_fields method should always be called before you have begun
51726
   * iterating through the object: it is expected that you are pointing at
51727
   * the beginning of the object.
51728
   * The runtime complexity is linear in the size of the object. After
51729
   * calling this function, if successful, the object is 'rewinded' at its
51730
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
51731
   * there is a missing comma), then an error is returned and it is no longer
51732
   * safe to continue.
51733
   *
51734
   * To check that an object is empty, it is more performant to use
51735
   * the is_empty() method.
51736
   *
51737
   * Performance hint: You should only call count_fields() as a last
51738
   * resort as it may require scanning the document twice or more.
51739
   */
51740
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
51741
  /**
51742
   * Consumes the object and returns a string_view instance corresponding to the
51743
   * object as represented in JSON. It points inside the original byte array containing
51744
   * the JSON document.
51745
   */
51746
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
51747
51748
protected:
51749
  /**
51750
   * Go to the end of the object, no matter where you are right now.
51751
   */
51752
  simdjson_inline error_code consume() noexcept;
51753
  static simdjson_inline simdjson_result<object> start(value_iterator &iter) noexcept;
51754
  static simdjson_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
51755
  static simdjson_inline simdjson_result<object> started(value_iterator &iter) noexcept;
51756
  static simdjson_inline object resume(const value_iterator &iter) noexcept;
51757
  simdjson_inline object(const value_iterator &iter) noexcept;
51758
51759
  simdjson_warn_unused simdjson_inline error_code find_field_raw(const std::string_view key) noexcept;
51760
51761
  value_iterator iter{};
51762
51763
  friend class value;
51764
  friend class document;
51765
  friend struct simdjson_result<object>;
51766
};
51767
51768
} // namespace ondemand
51769
} // namespace haswell
51770
} // namespace simdjson
51771
51772
namespace simdjson {
51773
51774
template<>
51775
struct simdjson_result<haswell::ondemand::object> : public haswell::implementation_simdjson_result_base<haswell::ondemand::object> {
51776
public:
51777
  simdjson_inline simdjson_result(haswell::ondemand::object &&value) noexcept; ///< @private
51778
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
51779
  simdjson_inline simdjson_result() noexcept = default;
51780
51781
  simdjson_inline simdjson_result<haswell::ondemand::object_iterator> begin() noexcept;
51782
  simdjson_inline simdjson_result<haswell::ondemand::object_iterator> end() noexcept;
51783
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(std::string_view key) & noexcept;
51784
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field(std::string_view key) && noexcept;
51785
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
51786
  simdjson_inline simdjson_result<haswell::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
51787
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](std::string_view key) & noexcept;
51788
  simdjson_inline simdjson_result<haswell::ondemand::value> operator[](std::string_view key) && noexcept;
51789
  simdjson_inline simdjson_result<haswell::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
51790
  simdjson_inline simdjson_result<haswell::ondemand::value> at_path(std::string_view json_path) noexcept;
51791
51792
  inline simdjson_result<bool> reset() noexcept;
51793
  inline simdjson_result<bool> is_empty() noexcept;
51794
  inline simdjson_result<size_t> count_fields() & noexcept;
51795
  inline simdjson_result<std::string_view> raw_json() noexcept;
51796
51797
};
51798
51799
} // namespace simdjson
51800
51801
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
51802
/* end file simdjson/generic/ondemand/object.h for haswell */
51803
/* including simdjson/generic/ondemand/object_iterator.h for haswell: #include "simdjson/generic/ondemand/object_iterator.h" */
51804
/* begin file simdjson/generic/ondemand/object_iterator.h for haswell */
51805
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
51806
51807
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
51808
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H */
51809
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
51810
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
51811
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
51812
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
51813
51814
namespace simdjson {
51815
namespace haswell {
51816
namespace ondemand {
51817
51818
class object_iterator {
51819
public:
51820
  /**
51821
   * Create a new invalid object_iterator.
51822
   *
51823
   * Exists so you can declare a variable and later assign to it before use.
51824
   */
51825
  simdjson_inline object_iterator() noexcept = default;
51826
51827
  //
51828
  // Iterator interface
51829
  //
51830
51831
  // Reads key and value, yielding them to the user.
51832
  // MUST ONLY BE CALLED ONCE PER ITERATION.
51833
  simdjson_inline simdjson_result<field> operator*() noexcept;
51834
  // Assumes it's being compared with the end. true if depth < iter->depth.
51835
  simdjson_inline bool operator==(const object_iterator &) const noexcept;
51836
  // Assumes it's being compared with the end. true if depth >= iter->depth.
51837
  simdjson_inline bool operator!=(const object_iterator &) const noexcept;
51838
  // Checks for ']' and ','
51839
  simdjson_inline object_iterator &operator++() noexcept;
51840
51841
private:
51842
  /**
51843
   * The underlying JSON iterator.
51844
   *
51845
   * PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
51846
   * is first used, and never changes afterwards.
51847
   */
51848
  value_iterator iter{};
51849
51850
  simdjson_inline object_iterator(const value_iterator &iter) noexcept;
51851
  friend struct simdjson_result<object_iterator>;
51852
  friend class object;
51853
};
51854
51855
} // namespace ondemand
51856
} // namespace haswell
51857
} // namespace simdjson
51858
51859
namespace simdjson {
51860
51861
template<>
51862
struct simdjson_result<haswell::ondemand::object_iterator> : public haswell::implementation_simdjson_result_base<haswell::ondemand::object_iterator> {
51863
public:
51864
  simdjson_inline simdjson_result(haswell::ondemand::object_iterator &&value) noexcept; ///< @private
51865
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
51866
  simdjson_inline simdjson_result() noexcept = default;
51867
51868
  //
51869
  // Iterator interface
51870
  //
51871
51872
  // Reads key and value, yielding them to the user.
51873
  simdjson_inline simdjson_result<haswell::ondemand::field> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
51874
  // Assumes it's being compared with the end. true if depth < iter->depth.
51875
  simdjson_inline bool operator==(const simdjson_result<haswell::ondemand::object_iterator> &) const noexcept;
51876
  // Assumes it's being compared with the end. true if depth >= iter->depth.
51877
  simdjson_inline bool operator!=(const simdjson_result<haswell::ondemand::object_iterator> &) const noexcept;
51878
  // Checks for ']' and ','
51879
  simdjson_inline simdjson_result<haswell::ondemand::object_iterator> &operator++() noexcept;
51880
};
51881
51882
} // namespace simdjson
51883
51884
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
51885
/* end file simdjson/generic/ondemand/object_iterator.h for haswell */
51886
/* including simdjson/generic/ondemand/serialization.h for haswell: #include "simdjson/generic/ondemand/serialization.h" */
51887
/* begin file simdjson/generic/ondemand/serialization.h for haswell */
51888
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
51889
51890
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
51891
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H */
51892
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
51893
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
51894
51895
namespace simdjson {
51896
/**
51897
 * Create a string-view instance out of a document instance. The string-view instance
51898
 * contains JSON text that is suitable to be parsed as JSON again. It does not
51899
 * validate the content.
51900
 */
51901
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::document& x) noexcept;
51902
/**
51903
 * Create a string-view instance out of a value instance. The string-view instance
51904
 * contains JSON text that is suitable to be parsed as JSON again. The value must
51905
 * not have been accessed previously. It does not
51906
 * validate the content.
51907
 */
51908
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::value& x) noexcept;
51909
/**
51910
 * Create a string-view instance out of an object instance. The string-view instance
51911
 * contains JSON text that is suitable to be parsed as JSON again. It does not
51912
 * validate the content.
51913
 */
51914
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::object& x) noexcept;
51915
/**
51916
 * Create a string-view instance out of an array instance. The string-view instance
51917
 * contains JSON text that is suitable to be parsed as JSON again. It does not
51918
 * validate the content.
51919
 */
51920
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::array& x) noexcept;
51921
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::document> x);
51922
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::value> x);
51923
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::object> x);
51924
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::array> x);
51925
} // namespace simdjson
51926
51927
/**
51928
 * We want to support argument-dependent lookup (ADL).
51929
 * Hence we should define operator<< in the namespace
51930
 * where the argument (here value, object, etc.) resides.
51931
 * Credit: @madhur4127
51932
 * See https://github.com/simdjson/simdjson/issues/1768
51933
 */
51934
namespace simdjson { namespace haswell { namespace ondemand {
51935
51936
/**
51937
 * Print JSON to an output stream.  It does not
51938
 * validate the content.
51939
 *
51940
 * @param out The output stream.
51941
 * @param value The element.
51942
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
51943
 */
51944
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::value x);
51945
#if SIMDJSON_EXCEPTIONS
51946
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::value> x);
51947
#endif
51948
/**
51949
 * Print JSON to an output stream. It does not
51950
 * validate the content.
51951
 *
51952
 * @param out The output stream.
51953
 * @param value The array.
51954
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
51955
 */
51956
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::array value);
51957
#if SIMDJSON_EXCEPTIONS
51958
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::array> x);
51959
#endif
51960
/**
51961
 * Print JSON to an output stream. It does not
51962
 * validate the content.
51963
 *
51964
 * @param out The output stream.
51965
 * @param value The array.
51966
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
51967
 */
51968
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::document& value);
51969
#if SIMDJSON_EXCEPTIONS
51970
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::document>&& x);
51971
#endif
51972
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::document_reference& value);
51973
#if SIMDJSON_EXCEPTIONS
51974
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::document_reference>&& x);
51975
#endif
51976
/**
51977
 * Print JSON to an output stream. It does not
51978
 * validate the content.
51979
 *
51980
 * @param out The output stream.
51981
 * @param value The object.
51982
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
51983
 */
51984
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::object value);
51985
#if SIMDJSON_EXCEPTIONS
51986
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::object> x);
51987
#endif
51988
}}} // namespace simdjson::haswell::ondemand
51989
51990
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
51991
/* end file simdjson/generic/ondemand/serialization.h for haswell */
51992
51993
// Inline definitions
51994
/* including simdjson/generic/ondemand/array-inl.h for haswell: #include "simdjson/generic/ondemand/array-inl.h" */
51995
/* begin file simdjson/generic/ondemand/array-inl.h for haswell */
51996
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
51997
51998
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
51999
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H */
52000
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
52001
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
52002
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator-inl.h" */
52003
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
52004
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
52005
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
52006
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
52007
52008
namespace simdjson {
52009
namespace haswell {
52010
namespace ondemand {
52011
52012
//
52013
// ### Live States
52014
//
52015
// While iterating or looking up values, depth >= iter->depth. at_start may vary. Error is
52016
// always SUCCESS:
52017
//
52018
// - Start: This is the state when the array is first found and the iterator is just past the `{`.
52019
//   In this state, at_start == true.
52020
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
52021
//   iterate over, the iterator is at the `,` before the next value (or `]`). In this state,
52022
//   depth == iter->depth, at_start == false, and error == SUCCESS.
52023
// - Unfinished Business: When we hand an array/object to the user which they do not fully
52024
//   iterate over, we need to finish that iteration by skipping child values until we reach the
52025
//   Next state. In this state, depth > iter->depth, at_start == false, and error == SUCCESS.
52026
//
52027
// ## Error States
52028
//
52029
// In error states, we will yield exactly one more value before stopping. iter->depth == depth
52030
// and at_start is always false. We decrement after yielding the error, moving to the Finished
52031
// state.
52032
//
52033
// - Chained Error: When the array iterator is part of an error chain--for example, in
52034
//   `for (auto tweet : doc["tweets"])`, where the tweet element may be missing or not be an
52035
//   array--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
52036
//   iter->depth == depth, and at_start == false. We decrement depth when we yield the error.
52037
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between elements,
52038
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
52039
//   error == TAPE_ERROR, iter->depth == depth, and at_start == false.
52040
//
52041
// ## Terminal State
52042
//
52043
// The terminal state has iter->depth < depth. at_start is always false.
52044
//
52045
// - Finished: When we have reached a `]` or have reported an error, we are finished. We signal this
52046
//   by decrementing depth. In this state, iter->depth < depth, at_start == false, and
52047
//   error == SUCCESS.
52048
//
52049
52050
simdjson_inline array::array(const value_iterator &_iter) noexcept
52051
  : iter{_iter}
52052
{
52053
}
52054
52055
simdjson_inline simdjson_result<array> array::start(value_iterator &iter) noexcept {
52056
  // We don't need to know if the array is empty to start iteration, but we do want to know if there
52057
  // is an error--thus `simdjson_unused`.
52058
  simdjson_unused bool has_value;
52059
  SIMDJSON_TRY( iter.start_array().get(has_value) );
52060
  return array(iter);
52061
}
52062
simdjson_inline simdjson_result<array> array::start_root(value_iterator &iter) noexcept {
52063
  simdjson_unused bool has_value;
52064
  SIMDJSON_TRY( iter.start_root_array().get(has_value) );
52065
  return array(iter);
52066
}
52067
simdjson_inline simdjson_result<array> array::started(value_iterator &iter) noexcept {
52068
  bool has_value;
52069
  SIMDJSON_TRY(iter.started_array().get(has_value));
52070
  return array(iter);
52071
}
52072
52073
simdjson_inline simdjson_result<array_iterator> array::begin() noexcept {
52074
#if SIMDJSON_DEVELOPMENT_CHECKS
52075
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
52076
#endif
52077
  return array_iterator(iter);
52078
}
52079
simdjson_inline simdjson_result<array_iterator> array::end() noexcept {
52080
  return array_iterator(iter);
52081
}
52082
simdjson_inline error_code array::consume() noexcept {
52083
  auto error = iter.json_iter().skip_child(iter.depth()-1);
52084
  if(error) { iter.abandon(); }
52085
  return error;
52086
}
52087
52088
simdjson_inline simdjson_result<std::string_view> array::raw_json() noexcept {
52089
  const uint8_t * starting_point{iter.peek_start()};
52090
  auto error = consume();
52091
  if(error) { return error; }
52092
  // After 'consume()', we could be left pointing just beyond the document, but that
52093
  // is ok because we are not going to dereference the final pointer position, we just
52094
  // use it to compute the length in bytes.
52095
  const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
52096
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
52097
}
52098
52099
SIMDJSON_PUSH_DISABLE_WARNINGS
52100
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
52101
simdjson_inline simdjson_result<size_t> array::count_elements() & noexcept {
52102
  size_t count{0};
52103
  // Important: we do not consume any of the values.
52104
  for(simdjson_unused auto v : *this) { count++; }
52105
  // The above loop will always succeed, but we want to report errors.
52106
  if(iter.error()) { return iter.error(); }
52107
  // We need to move back at the start because we expect users to iterate through
52108
  // the array after counting the number of elements.
52109
  iter.reset_array();
52110
  return count;
52111
}
52112
SIMDJSON_POP_DISABLE_WARNINGS
52113
52114
simdjson_inline simdjson_result<bool> array::is_empty() & noexcept {
52115
  bool is_not_empty;
52116
  auto error = iter.reset_array().get(is_not_empty);
52117
  if(error) { return error; }
52118
  return !is_not_empty;
52119
}
52120
52121
inline simdjson_result<bool> array::reset() & noexcept {
52122
  return iter.reset_array();
52123
}
52124
52125
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
52126
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
52127
  json_pointer = json_pointer.substr(1);
52128
  // - means "the append position" or "the element after the end of the array"
52129
  // We don't support this, because we're returning a real element, not a position.
52130
  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
52131
52132
  // Read the array index
52133
  size_t array_index = 0;
52134
  size_t i;
52135
  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
52136
    uint8_t digit = uint8_t(json_pointer[i] - '0');
52137
    // Check for non-digit in array index. If it's there, we're trying to get a field in an object
52138
    if (digit > 9) { return INCORRECT_TYPE; }
52139
    array_index = array_index*10 + digit;
52140
  }
52141
52142
  // 0 followed by other digits is invalid
52143
  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
52144
52145
  // Empty string is invalid; so is a "/" with no digits before it
52146
  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
52147
  // Get the child
52148
  auto child = at(array_index);
52149
  // If there is an error, it ends here
52150
  if(child.error()) {
52151
    return child;
52152
  }
52153
52154
  // If there is a /, we're not done yet, call recursively.
52155
  if (i < json_pointer.length()) {
52156
    child = child.at_pointer(json_pointer.substr(i));
52157
  }
52158
  return child;
52159
}
52160
52161
inline std::string json_path_to_pointer_conversion(std::string_view json_path) {
52162
  if (json_path.empty() || (json_path.front() != '.' &&
52163
      json_path.front() != '[')) {
52164
    return "-1"; // This is just a sentinel value, the caller should check for this and return an error.
52165
  }
52166
52167
  std::string result;
52168
  // Reserve space to reduce allocations, adjusting for potential increases due
52169
  // to escaping.
52170
  result.reserve(json_path.size() * 2);
52171
52172
  size_t i = 0;
52173
52174
  while (i < json_path.length()) {
52175
    if (json_path[i] == '.') {
52176
      result += '/';
52177
    } else if (json_path[i] == '[') {
52178
      result += '/';
52179
      ++i; // Move past the '['
52180
      while (i < json_path.length() && json_path[i] != ']') {
52181
          if (json_path[i] == '~') {
52182
            result += "~0";
52183
          } else if (json_path[i] == '/') {
52184
            result += "~1";
52185
          } else {
52186
            result += json_path[i];
52187
          }
52188
          ++i;
52189
      }
52190
      if (i == json_path.length() || json_path[i] != ']') {
52191
          return "-1"; // Using sentinel value that will be handled as an error by the caller.
52192
      }
52193
    } else {
52194
      if (json_path[i] == '~') {
52195
          result += "~0";
52196
      } else if (json_path[i] == '/') {
52197
          result += "~1";
52198
      } else {
52199
          result += json_path[i];
52200
      }
52201
    }
52202
    ++i;
52203
  }
52204
52205
  return result;
52206
}
52207
52208
inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept {
52209
  auto json_pointer = json_path_to_pointer_conversion(json_path);
52210
  if (json_pointer == "-1") { return INVALID_JSON_POINTER; }
52211
  return at_pointer(json_pointer);
52212
}
52213
52214
simdjson_inline simdjson_result<value> array::at(size_t index) noexcept {
52215
  size_t i = 0;
52216
  for (auto value : *this) {
52217
    if (i == index) { return value; }
52218
    i++;
52219
  }
52220
  return INDEX_OUT_OF_BOUNDS;
52221
}
52222
52223
} // namespace ondemand
52224
} // namespace haswell
52225
} // namespace simdjson
52226
52227
namespace simdjson {
52228
52229
simdjson_inline simdjson_result<haswell::ondemand::array>::simdjson_result(
52230
  haswell::ondemand::array &&value
52231
) noexcept
52232
  : implementation_simdjson_result_base<haswell::ondemand::array>(
52233
      std::forward<haswell::ondemand::array>(value)
52234
    )
52235
{
52236
}
52237
simdjson_inline simdjson_result<haswell::ondemand::array>::simdjson_result(
52238
  error_code error
52239
) noexcept
52240
  : implementation_simdjson_result_base<haswell::ondemand::array>(error)
52241
{
52242
}
52243
52244
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::array>::begin() noexcept {
52245
  if (error()) { return error(); }
52246
  return first.begin();
52247
}
52248
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::array>::end() noexcept {
52249
  if (error()) { return error(); }
52250
  return first.end();
52251
}
52252
simdjson_inline  simdjson_result<size_t> simdjson_result<haswell::ondemand::array>::count_elements() & noexcept {
52253
  if (error()) { return error(); }
52254
  return first.count_elements();
52255
}
52256
simdjson_inline  simdjson_result<bool> simdjson_result<haswell::ondemand::array>::is_empty() & noexcept {
52257
  if (error()) { return error(); }
52258
  return first.is_empty();
52259
}
52260
simdjson_inline  simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::array>::at(size_t index) noexcept {
52261
  if (error()) { return error(); }
52262
  return first.at(index);
52263
}
52264
simdjson_inline  simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::array>::at_pointer(std::string_view json_pointer) noexcept {
52265
  if (error()) { return error(); }
52266
  return first.at_pointer(json_pointer);
52267
}
52268
simdjson_inline  simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::array>::at_path(std::string_view json_path) noexcept {
52269
  if (error()) { return error(); }
52270
  return first.at_path(json_path);
52271
}
52272
simdjson_inline  simdjson_result<std::string_view> simdjson_result<haswell::ondemand::array>::raw_json() noexcept {
52273
  if (error()) { return error(); }
52274
  return first.raw_json();
52275
}
52276
} // namespace simdjson
52277
52278
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
52279
/* end file simdjson/generic/ondemand/array-inl.h for haswell */
52280
/* including simdjson/generic/ondemand/array_iterator-inl.h for haswell: #include "simdjson/generic/ondemand/array_iterator-inl.h" */
52281
/* begin file simdjson/generic/ondemand/array_iterator-inl.h for haswell */
52282
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
52283
52284
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
52285
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H */
52286
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
52287
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
52288
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
52289
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
52290
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
52291
52292
namespace simdjson {
52293
namespace haswell {
52294
namespace ondemand {
52295
52296
simdjson_inline array_iterator::array_iterator(const value_iterator &_iter) noexcept
52297
  : iter{_iter}
52298
{}
52299
52300
simdjson_inline simdjson_result<value> array_iterator::operator*() noexcept {
52301
  if (iter.error()) { iter.abandon(); return iter.error(); }
52302
  return value(iter.child());
52303
}
52304
simdjson_inline bool array_iterator::operator==(const array_iterator &other) const noexcept {
52305
  return !(*this != other);
52306
}
52307
simdjson_inline bool array_iterator::operator!=(const array_iterator &) const noexcept {
52308
  return iter.is_open();
52309
}
52310
simdjson_inline array_iterator &array_iterator::operator++() noexcept {
52311
  error_code error;
52312
  // PERF NOTE this is a safety rail ... users should exit loops as soon as they receive an error, so we'll never get here.
52313
  // However, it does not seem to make a perf difference, so we add it out of an abundance of caution.
52314
  if (( error = iter.error() )) { return *this; }
52315
  if (( error = iter.skip_child() )) { return *this; }
52316
  if (( error = iter.has_next_element().error() )) { return *this; }
52317
  return *this;
52318
}
52319
52320
} // namespace ondemand
52321
} // namespace haswell
52322
} // namespace simdjson
52323
52324
namespace simdjson {
52325
52326
simdjson_inline simdjson_result<haswell::ondemand::array_iterator>::simdjson_result(
52327
  haswell::ondemand::array_iterator &&value
52328
) noexcept
52329
  : haswell::implementation_simdjson_result_base<haswell::ondemand::array_iterator>(std::forward<haswell::ondemand::array_iterator>(value))
52330
{
52331
  first.iter.assert_is_valid();
52332
}
52333
simdjson_inline simdjson_result<haswell::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
52334
  : haswell::implementation_simdjson_result_base<haswell::ondemand::array_iterator>({}, error)
52335
{
52336
}
52337
52338
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::array_iterator>::operator*() noexcept {
52339
  if (error()) { return error(); }
52340
  return *first;
52341
}
52342
simdjson_inline bool simdjson_result<haswell::ondemand::array_iterator>::operator==(const simdjson_result<haswell::ondemand::array_iterator> &other) const noexcept {
52343
  if (!first.iter.is_valid()) { return !error(); }
52344
  return first == other.first;
52345
}
52346
simdjson_inline bool simdjson_result<haswell::ondemand::array_iterator>::operator!=(const simdjson_result<haswell::ondemand::array_iterator> &other) const noexcept {
52347
  if (!first.iter.is_valid()) { return error(); }
52348
  return first != other.first;
52349
}
52350
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> &simdjson_result<haswell::ondemand::array_iterator>::operator++() noexcept {
52351
  // Clear the error if there is one, so we don't yield it twice
52352
  if (error()) { second = SUCCESS; return *this; }
52353
  ++(first);
52354
  return *this;
52355
}
52356
52357
} // namespace simdjson
52358
52359
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
52360
/* end file simdjson/generic/ondemand/array_iterator-inl.h for haswell */
52361
/* including simdjson/generic/ondemand/document-inl.h for haswell: #include "simdjson/generic/ondemand/document-inl.h" */
52362
/* begin file simdjson/generic/ondemand/document-inl.h for haswell */
52363
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
52364
52365
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
52366
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */
52367
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
52368
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */
52369
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
52370
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
52371
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
52372
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
52373
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
52374
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
52375
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */
52376
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
52377
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
52378
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
52379
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
52380
52381
namespace simdjson {
52382
namespace haswell {
52383
namespace ondemand {
52384
52385
simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept
52386
  : iter{std::forward<json_iterator>(_iter)}
52387
{
52388
  logger::log_start_value(iter, "document");
52389
}
52390
52391
simdjson_inline document document::start(json_iterator &&iter) noexcept {
52392
  return document(std::forward<json_iterator>(iter));
52393
}
52394
52395
inline void document::rewind() noexcept {
52396
  iter.rewind();
52397
}
52398
52399
inline std::string document::to_debug_string() noexcept {
52400
  return iter.to_string();
52401
}
52402
52403
inline simdjson_result<const char *> document::current_location() const noexcept {
52404
  return iter.current_location();
52405
}
52406
52407
inline int32_t document::current_depth() const noexcept {
52408
  return iter.depth();
52409
}
52410
52411
inline bool document::at_end() const noexcept {
52412
  return iter.at_end();
52413
}
52414
52415
52416
inline bool document::is_alive() noexcept {
52417
  return iter.is_alive();
52418
}
52419
simdjson_inline value_iterator document::resume_value_iterator() noexcept {
52420
  return value_iterator(&iter, 1, iter.root_position());
52421
}
52422
simdjson_inline value_iterator document::get_root_value_iterator() noexcept {
52423
  return resume_value_iterator();
52424
}
52425
simdjson_inline simdjson_result<object> document::start_or_resume_object() noexcept {
52426
  if (iter.at_root()) {
52427
    return get_object();
52428
  } else {
52429
    return object::resume(resume_value_iterator());
52430
  }
52431
}
52432
simdjson_inline simdjson_result<value> document::get_value() noexcept {
52433
  // Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
52434
  // gets called.
52435
52436
  // It is the convention throughout the code that  the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether
52437
  // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error.
52438
#if SIMDJSON_DEVELOPMENT_CHECKS
52439
  if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; }
52440
#endif
52441
  // assert_at_root() serves two purposes: in Debug mode, whether or not
52442
  // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of
52443
  // the document (this will typically be redundant). In release mode, it generates
52444
  // SIMDJSON_ASSUME statements to allow the compiler to make assumptions.
52445
  iter.assert_at_root();
52446
  switch (*iter.peek()) {
52447
    case '[': {
52448
      // The following lines check that the document ends with ].
52449
      auto value_iterator = get_root_value_iterator();
52450
      auto error = value_iterator.check_root_array();
52451
      if(error) { return error; }
52452
      return value(get_root_value_iterator());
52453
    }
52454
    case '{': {
52455
      // The following lines would check that the document ends with }.
52456
      auto value_iterator = get_root_value_iterator();
52457
      auto error = value_iterator.check_root_object();
52458
      if(error) { return error; }
52459
      return value(get_root_value_iterator());
52460
    }
52461
    default:
52462
      // Unfortunately, scalar documents are a special case in simdjson and they cannot
52463
      // be safely converted to value instances.
52464
      return SCALAR_DOCUMENT_AS_VALUE;
52465
  }
52466
}
52467
simdjson_inline simdjson_result<array> document::get_array() & noexcept {
52468
  auto value = get_root_value_iterator();
52469
  return array::start_root(value);
52470
}
52471
simdjson_inline simdjson_result<object> document::get_object() & noexcept {
52472
  auto value = get_root_value_iterator();
52473
  return object::start_root(value);
52474
}
52475
52476
/**
52477
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
52478
 * give an error, so we check for trailing content. We want to disallow trailing
52479
 * content.
52480
 * Thus, in several implementations below, we pass a 'true' parameter value to
52481
 * a get_root_value_iterator() method: this indicates that we disallow trailing content.
52482
 */
52483
52484
simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
52485
  return get_root_value_iterator().get_root_uint64(true);
52486
}
52487
simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
52488
  return get_root_value_iterator().get_root_uint64_in_string(true);
52489
}
52490
simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
52491
  return get_root_value_iterator().get_root_int64(true);
52492
}
52493
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
52494
  return get_root_value_iterator().get_root_int64_in_string(true);
52495
}
52496
simdjson_inline simdjson_result<double> document::get_double() noexcept {
52497
  return get_root_value_iterator().get_root_double(true);
52498
}
52499
simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
52500
  return get_root_value_iterator().get_root_double_in_string(true);
52501
}
52502
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
52503
  return get_root_value_iterator().get_root_string(true, allow_replacement);
52504
}
52505
template <typename string_type>
52506
simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
52507
  return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
52508
}
52509
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
52510
  return get_root_value_iterator().get_root_wobbly_string(true);
52511
}
52512
simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
52513
  return get_root_value_iterator().get_root_raw_json_string(true);
52514
}
52515
simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
52516
  return get_root_value_iterator().get_root_bool(true);
52517
}
52518
simdjson_inline simdjson_result<bool> document::is_null() noexcept {
52519
  return get_root_value_iterator().is_root_null(true);
52520
}
52521
52522
template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
52523
template<> simdjson_inline simdjson_result<object> document::get() & noexcept { return get_object(); }
52524
template<> simdjson_inline simdjson_result<raw_json_string> document::get() & noexcept { return get_raw_json_string(); }
52525
template<> simdjson_inline simdjson_result<std::string_view> document::get() & noexcept { return get_string(false); }
52526
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
52527
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
52528
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
52529
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
52530
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
52531
52532
template<> simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
52533
template<> simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
52534
template<> simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
52535
template<> simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
52536
template<> simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
52537
template<> simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
52538
template<> simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
52539
52540
template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
52541
  return get<T>().get(out);
52542
}
52543
template<typename T> simdjson_inline error_code document::get(T &out) && noexcept {
52544
  return std::forward<document>(*this).get<T>().get(out);
52545
}
52546
52547
#if SIMDJSON_EXCEPTIONS
52548
template <class T>
52549
simdjson_inline document::operator T() noexcept(false) { return get<T>(); }
52550
simdjson_inline document::operator array() & noexcept(false) { return get_array(); }
52551
simdjson_inline document::operator object() & noexcept(false) { return get_object(); }
52552
simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); }
52553
simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); }
52554
simdjson_inline document::operator double() noexcept(false) { return get_double(); }
52555
simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); }
52556
simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
52557
simdjson_inline document::operator bool() noexcept(false) { return get_bool(); }
52558
simdjson_inline document::operator value() noexcept(false) { return get_value(); }
52559
52560
#endif
52561
simdjson_inline simdjson_result<size_t> document::count_elements() & noexcept {
52562
  auto a = get_array();
52563
  simdjson_result<size_t> answer = a.count_elements();
52564
  /* If there was an array, we are now left pointing at its first element. */
52565
  if(answer.error() == SUCCESS) { rewind(); }
52566
  return answer;
52567
}
52568
simdjson_inline simdjson_result<size_t> document::count_fields() & noexcept {
52569
  auto a = get_object();
52570
  simdjson_result<size_t> answer = a.count_fields();
52571
  /* If there was an object, we are now left pointing at its first element. */
52572
  if(answer.error() == SUCCESS) { rewind(); }
52573
  return answer;
52574
}
52575
simdjson_inline simdjson_result<value> document::at(size_t index) & noexcept {
52576
  auto a = get_array();
52577
  return a.at(index);
52578
}
52579
simdjson_inline simdjson_result<array_iterator> document::begin() & noexcept {
52580
  return get_array().begin();
52581
}
52582
simdjson_inline simdjson_result<array_iterator> document::end() & noexcept {
52583
  return {};
52584
}
52585
52586
simdjson_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
52587
  return start_or_resume_object().find_field(key);
52588
}
52589
simdjson_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
52590
  return start_or_resume_object().find_field(key);
52591
}
52592
simdjson_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
52593
  return start_or_resume_object().find_field_unordered(key);
52594
}
52595
simdjson_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
52596
  return start_or_resume_object().find_field_unordered(key);
52597
}
52598
simdjson_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
52599
  return start_or_resume_object()[key];
52600
}
52601
simdjson_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
52602
  return start_or_resume_object()[key];
52603
}
52604
52605
simdjson_inline error_code document::consume() noexcept {
52606
  auto error = iter.skip_child(0);
52607
  if(error) { iter.abandon(); }
52608
  return error;
52609
}
52610
52611
simdjson_inline simdjson_result<std::string_view> document::raw_json() noexcept {
52612
  auto _iter = get_root_value_iterator();
52613
  const uint8_t * starting_point{_iter.peek_start()};
52614
  auto error = consume();
52615
  if(error) { return error; }
52616
  // After 'consume()', we could be left pointing just beyond the document, but that
52617
  // is ok because we are not going to dereference the final pointer position, we just
52618
  // use it to compute the length in bytes.
52619
  const uint8_t * final_point{iter.unsafe_pointer()};
52620
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
52621
}
52622
52623
simdjson_inline simdjson_result<json_type> document::type() noexcept {
52624
  return get_root_value_iterator().type();
52625
}
52626
52627
simdjson_inline simdjson_result<bool> document::is_scalar() noexcept {
52628
  json_type this_type;
52629
  auto error = type().get(this_type);
52630
  if(error) { return error; }
52631
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
52632
}
52633
52634
simdjson_inline simdjson_result<bool> document::is_string() noexcept {
52635
  json_type this_type;
52636
  auto error = type().get(this_type);
52637
  if(error) { return error; }
52638
  return (this_type == json_type::string);
52639
}
52640
52641
simdjson_inline bool document::is_negative() noexcept {
52642
  return get_root_value_iterator().is_root_negative();
52643
}
52644
52645
simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
52646
  return get_root_value_iterator().is_root_integer(true);
52647
}
52648
52649
simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
52650
  return get_root_value_iterator().get_root_number_type(true);
52651
}
52652
52653
simdjson_inline simdjson_result<number> document::get_number() noexcept {
52654
  return get_root_value_iterator().get_root_number(true);
52655
}
52656
52657
52658
simdjson_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
52659
  auto _iter = get_root_value_iterator();
52660
  return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_root_length());
52661
}
52662
52663
simdjson_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
52664
  rewind(); // Rewind the document each time at_pointer is called
52665
  if (json_pointer.empty()) {
52666
    return this->get_value();
52667
  }
52668
  json_type t;
52669
  SIMDJSON_TRY(type().get(t));
52670
  switch (t)
52671
  {
52672
    case json_type::array:
52673
      return (*this).get_array().at_pointer(json_pointer);
52674
    case json_type::object:
52675
      return (*this).get_object().at_pointer(json_pointer);
52676
    default:
52677
      return INVALID_JSON_POINTER;
52678
  }
52679
}
52680
52681
simdjson_inline simdjson_result<value> document::at_path(std::string_view json_path) noexcept {
52682
  rewind(); // Rewind the document each time at_pointer is called
52683
  if (json_path.empty()) {
52684
      return this->get_value();
52685
  }
52686
  json_type t;
52687
  SIMDJSON_TRY(type().get(t));
52688
  switch (t) {
52689
  case json_type::array:
52690
      return (*this).get_array().at_path(json_path);
52691
  case json_type::object:
52692
      return (*this).get_object().at_path(json_path);
52693
  default:
52694
      return INVALID_JSON_POINTER;
52695
  }
52696
}
52697
52698
} // namespace ondemand
52699
} // namespace haswell
52700
} // namespace simdjson
52701
52702
namespace simdjson {
52703
52704
simdjson_inline simdjson_result<haswell::ondemand::document>::simdjson_result(
52705
  haswell::ondemand::document &&value
52706
) noexcept :
52707
    implementation_simdjson_result_base<haswell::ondemand::document>(
52708
      std::forward<haswell::ondemand::document>(value)
52709
    )
52710
{
52711
}
52712
simdjson_inline simdjson_result<haswell::ondemand::document>::simdjson_result(
52713
  error_code error
52714
) noexcept :
52715
    implementation_simdjson_result_base<haswell::ondemand::document>(
52716
      error
52717
    )
52718
{
52719
}
52720
simdjson_inline simdjson_result<size_t> simdjson_result<haswell::ondemand::document>::count_elements() & noexcept {
52721
  if (error()) { return error(); }
52722
  return first.count_elements();
52723
}
52724
simdjson_inline simdjson_result<size_t> simdjson_result<haswell::ondemand::document>::count_fields() & noexcept {
52725
  if (error()) { return error(); }
52726
  return first.count_fields();
52727
}
52728
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::at(size_t index) & noexcept {
52729
  if (error()) { return error(); }
52730
  return first.at(index);
52731
}
52732
simdjson_inline error_code simdjson_result<haswell::ondemand::document>::rewind() noexcept {
52733
  if (error()) { return error(); }
52734
  first.rewind();
52735
  return SUCCESS;
52736
}
52737
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::document>::begin() & noexcept {
52738
  if (error()) { return error(); }
52739
  return first.begin();
52740
}
52741
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::document>::end() & noexcept {
52742
  return {};
52743
}
52744
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
52745
  if (error()) { return error(); }
52746
  return first.find_field_unordered(key);
52747
}
52748
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::find_field_unordered(const char *key) & noexcept {
52749
  if (error()) { return error(); }
52750
  return first.find_field_unordered(key);
52751
}
52752
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::operator[](std::string_view key) & noexcept {
52753
  if (error()) { return error(); }
52754
  return first[key];
52755
}
52756
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::operator[](const char *key) & noexcept {
52757
  if (error()) { return error(); }
52758
  return first[key];
52759
}
52760
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::find_field(std::string_view key) & noexcept {
52761
  if (error()) { return error(); }
52762
  return first.find_field(key);
52763
}
52764
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::find_field(const char *key) & noexcept {
52765
  if (error()) { return error(); }
52766
  return first.find_field(key);
52767
}
52768
simdjson_inline simdjson_result<haswell::ondemand::array> simdjson_result<haswell::ondemand::document>::get_array() & noexcept {
52769
  if (error()) { return error(); }
52770
  return first.get_array();
52771
}
52772
simdjson_inline simdjson_result<haswell::ondemand::object> simdjson_result<haswell::ondemand::document>::get_object() & noexcept {
52773
  if (error()) { return error(); }
52774
  return first.get_object();
52775
}
52776
simdjson_inline simdjson_result<uint64_t> simdjson_result<haswell::ondemand::document>::get_uint64() noexcept {
52777
  if (error()) { return error(); }
52778
  return first.get_uint64();
52779
}
52780
simdjson_inline simdjson_result<uint64_t> simdjson_result<haswell::ondemand::document>::get_uint64_in_string() noexcept {
52781
  if (error()) { return error(); }
52782
  return first.get_uint64_in_string();
52783
}
52784
simdjson_inline simdjson_result<int64_t> simdjson_result<haswell::ondemand::document>::get_int64() noexcept {
52785
  if (error()) { return error(); }
52786
  return first.get_int64();
52787
}
52788
simdjson_inline simdjson_result<int64_t> simdjson_result<haswell::ondemand::document>::get_int64_in_string() noexcept {
52789
  if (error()) { return error(); }
52790
  return first.get_int64_in_string();
52791
}
52792
simdjson_inline simdjson_result<double> simdjson_result<haswell::ondemand::document>::get_double() noexcept {
52793
  if (error()) { return error(); }
52794
  return first.get_double();
52795
}
52796
simdjson_inline simdjson_result<double> simdjson_result<haswell::ondemand::document>::get_double_in_string() noexcept {
52797
  if (error()) { return error(); }
52798
  return first.get_double_in_string();
52799
}
52800
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::document>::get_string(bool allow_replacement) noexcept {
52801
  if (error()) { return error(); }
52802
  return first.get_string(allow_replacement);
52803
}
52804
template <typename string_type>
52805
simdjson_inline error_code simdjson_result<haswell::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
52806
  if (error()) { return error(); }
52807
  return first.get_string(receiver, allow_replacement);
52808
}
52809
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::document>::get_wobbly_string() noexcept {
52810
  if (error()) { return error(); }
52811
  return first.get_wobbly_string();
52812
}
52813
simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> simdjson_result<haswell::ondemand::document>::get_raw_json_string() noexcept {
52814
  if (error()) { return error(); }
52815
  return first.get_raw_json_string();
52816
}
52817
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document>::get_bool() noexcept {
52818
  if (error()) { return error(); }
52819
  return first.get_bool();
52820
}
52821
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::get_value() noexcept {
52822
  if (error()) { return error(); }
52823
  return first.get_value();
52824
}
52825
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document>::is_null() noexcept {
52826
  if (error()) { return error(); }
52827
  return first.is_null();
52828
}
52829
52830
template<typename T>
52831
simdjson_inline simdjson_result<T> simdjson_result<haswell::ondemand::document>::get() & noexcept {
52832
  if (error()) { return error(); }
52833
  return first.get<T>();
52834
}
52835
template<typename T>
52836
simdjson_inline simdjson_result<T> simdjson_result<haswell::ondemand::document>::get() && noexcept {
52837
  if (error()) { return error(); }
52838
  return std::forward<haswell::ondemand::document>(first).get<T>();
52839
}
52840
template<typename T>
52841
simdjson_inline error_code simdjson_result<haswell::ondemand::document>::get(T &out) & noexcept {
52842
  if (error()) { return error(); }
52843
  return first.get<T>(out);
52844
}
52845
template<typename T>
52846
simdjson_inline error_code simdjson_result<haswell::ondemand::document>::get(T &out) && noexcept {
52847
  if (error()) { return error(); }
52848
  return std::forward<haswell::ondemand::document>(first).get<T>(out);
52849
}
52850
52851
template<> simdjson_inline simdjson_result<haswell::ondemand::document> simdjson_result<haswell::ondemand::document>::get<haswell::ondemand::document>() & noexcept = delete;
52852
template<> simdjson_inline simdjson_result<haswell::ondemand::document> simdjson_result<haswell::ondemand::document>::get<haswell::ondemand::document>() && noexcept {
52853
  if (error()) { return error(); }
52854
  return std::forward<haswell::ondemand::document>(first);
52855
}
52856
template<> simdjson_inline error_code simdjson_result<haswell::ondemand::document>::get<haswell::ondemand::document>(haswell::ondemand::document &out) & noexcept = delete;
52857
template<> simdjson_inline error_code simdjson_result<haswell::ondemand::document>::get<haswell::ondemand::document>(haswell::ondemand::document &out) && noexcept {
52858
  if (error()) { return error(); }
52859
  out = std::forward<haswell::ondemand::document>(first);
52860
  return SUCCESS;
52861
}
52862
52863
simdjson_inline simdjson_result<haswell::ondemand::json_type> simdjson_result<haswell::ondemand::document>::type() noexcept {
52864
  if (error()) { return error(); }
52865
  return first.type();
52866
}
52867
52868
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document>::is_scalar() noexcept {
52869
  if (error()) { return error(); }
52870
  return first.is_scalar();
52871
}
52872
52873
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document>::is_string() noexcept {
52874
  if (error()) { return error(); }
52875
  return first.is_string();
52876
}
52877
52878
simdjson_inline bool simdjson_result<haswell::ondemand::document>::is_negative() noexcept {
52879
  if (error()) { return error(); }
52880
  return first.is_negative();
52881
}
52882
52883
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document>::is_integer() noexcept {
52884
  if (error()) { return error(); }
52885
  return first.is_integer();
52886
}
52887
52888
simdjson_inline simdjson_result<haswell::number_type> simdjson_result<haswell::ondemand::document>::get_number_type() noexcept {
52889
  if (error()) { return error(); }
52890
  return first.get_number_type();
52891
}
52892
52893
simdjson_inline simdjson_result<haswell::ondemand::number> simdjson_result<haswell::ondemand::document>::get_number() noexcept {
52894
  if (error()) { return error(); }
52895
  return first.get_number();
52896
}
52897
52898
52899
#if SIMDJSON_EXCEPTIONS
52900
template <class T, typename std::enable_if<std::is_same<T, haswell::ondemand::document>::value == false>::type>
52901
simdjson_inline simdjson_result<haswell::ondemand::document>::operator T() noexcept(false) {
52902
  if (error()) { throw simdjson_error(error()); }
52903
  return first;
52904
}
52905
simdjson_inline simdjson_result<haswell::ondemand::document>::operator haswell::ondemand::array() & noexcept(false) {
52906
  if (error()) { throw simdjson_error(error()); }
52907
  return first;
52908
}
52909
simdjson_inline simdjson_result<haswell::ondemand::document>::operator haswell::ondemand::object() & noexcept(false) {
52910
  if (error()) { throw simdjson_error(error()); }
52911
  return first;
52912
}
52913
simdjson_inline simdjson_result<haswell::ondemand::document>::operator uint64_t() noexcept(false) {
52914
  if (error()) { throw simdjson_error(error()); }
52915
  return first;
52916
}
52917
simdjson_inline simdjson_result<haswell::ondemand::document>::operator int64_t() noexcept(false) {
52918
  if (error()) { throw simdjson_error(error()); }
52919
  return first;
52920
}
52921
simdjson_inline simdjson_result<haswell::ondemand::document>::operator double() noexcept(false) {
52922
  if (error()) { throw simdjson_error(error()); }
52923
  return first;
52924
}
52925
simdjson_inline simdjson_result<haswell::ondemand::document>::operator std::string_view() noexcept(false) {
52926
  if (error()) { throw simdjson_error(error()); }
52927
  return first;
52928
}
52929
simdjson_inline simdjson_result<haswell::ondemand::document>::operator haswell::ondemand::raw_json_string() noexcept(false) {
52930
  if (error()) { throw simdjson_error(error()); }
52931
  return first;
52932
}
52933
simdjson_inline simdjson_result<haswell::ondemand::document>::operator bool() noexcept(false) {
52934
  if (error()) { throw simdjson_error(error()); }
52935
  return first;
52936
}
52937
simdjson_inline simdjson_result<haswell::ondemand::document>::operator haswell::ondemand::value() noexcept(false) {
52938
  if (error()) { throw simdjson_error(error()); }
52939
  return first;
52940
}
52941
#endif
52942
52943
52944
simdjson_inline simdjson_result<const char *> simdjson_result<haswell::ondemand::document>::current_location() noexcept {
52945
  if (error()) { return error(); }
52946
  return first.current_location();
52947
}
52948
52949
simdjson_inline bool simdjson_result<haswell::ondemand::document>::at_end() const noexcept {
52950
  if (error()) { return error(); }
52951
  return first.at_end();
52952
}
52953
52954
52955
simdjson_inline int32_t simdjson_result<haswell::ondemand::document>::current_depth() const noexcept {
52956
  if (error()) { return error(); }
52957
  return first.current_depth();
52958
}
52959
52960
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::document>::raw_json_token() noexcept {
52961
  if (error()) { return error(); }
52962
  return first.raw_json_token();
52963
}
52964
52965
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::at_pointer(std::string_view json_pointer) noexcept {
52966
  if (error()) { return error(); }
52967
  return first.at_pointer(json_pointer);
52968
}
52969
52970
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document>::at_path(std::string_view json_path) noexcept {
52971
  if (error()) { return error(); }
52972
  return first.at_path(json_path);
52973
}
52974
52975
} // namespace simdjson
52976
52977
52978
namespace simdjson {
52979
namespace haswell {
52980
namespace ondemand {
52981
52982
simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {}
52983
simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
52984
simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
52985
simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
52986
simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
52987
/**
52988
 * The document_reference instances are used primarily/solely for streams of JSON
52989
 * documents.
52990
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
52991
 * give an error, so we check for trailing content.
52992
 *
52993
 * However, for streams of JSON documents, we want to be able to start from
52994
 * "321" "321" "321"
52995
 * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
52996
 * successfully each time.
52997
 *
52998
 * To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
52999
 * this indicates that we allow trailing content.
53000
 */
53001
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
53002
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
53003
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
53004
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
53005
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
53006
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
53007
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
53008
template <typename string_type>
53009
simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
53010
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
53011
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
53012
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
53013
simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
53014
simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
53015
template<> simdjson_inline simdjson_result<array> document_reference::get() & noexcept { return get_array(); }
53016
template<> simdjson_inline simdjson_result<object> document_reference::get() & noexcept { return get_object(); }
53017
template<> simdjson_inline simdjson_result<raw_json_string> document_reference::get() & noexcept { return get_raw_json_string(); }
53018
template<> simdjson_inline simdjson_result<std::string_view> document_reference::get() & noexcept { return get_string(false); }
53019
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
53020
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
53021
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
53022
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
53023
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
53024
#if SIMDJSON_EXCEPTIONS
53025
template <class T>
53026
simdjson_inline document_reference::operator T() noexcept(false) { return get<T>(); }
53027
simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
53028
simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
53029
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
53030
simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
53031
simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
53032
simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
53033
simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
53034
simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
53035
simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
53036
#endif
53037
simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
53038
simdjson_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
53039
simdjson_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
53040
simdjson_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
53041
simdjson_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
53042
simdjson_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
53043
simdjson_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
53044
simdjson_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
53045
simdjson_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
53046
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
53047
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
53048
simdjson_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
53049
simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
53050
simdjson_inline simdjson_result<bool> document_reference::is_string() noexcept { return doc->is_string(); }
53051
simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
53052
simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
53053
simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
53054
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
53055
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
53056
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
53057
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
53058
simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
53059
simdjson_inline simdjson_result<value> document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); }
53060
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
53061
simdjson_inline document_reference::operator document&() const noexcept { return *doc; }
53062
53063
} // namespace ondemand
53064
} // namespace haswell
53065
} // namespace simdjson
53066
53067
53068
53069
namespace simdjson {
53070
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::simdjson_result(haswell::ondemand::document_reference value, error_code error)
53071
  noexcept : implementation_simdjson_result_base<haswell::ondemand::document_reference>(std::forward<haswell::ondemand::document_reference>(value), error) {}
53072
53073
53074
simdjson_inline simdjson_result<size_t> simdjson_result<haswell::ondemand::document_reference>::count_elements() & noexcept {
53075
  if (error()) { return error(); }
53076
  return first.count_elements();
53077
}
53078
simdjson_inline simdjson_result<size_t> simdjson_result<haswell::ondemand::document_reference>::count_fields() & noexcept {
53079
  if (error()) { return error(); }
53080
  return first.count_fields();
53081
}
53082
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::at(size_t index) & noexcept {
53083
  if (error()) { return error(); }
53084
  return first.at(index);
53085
}
53086
simdjson_inline error_code simdjson_result<haswell::ondemand::document_reference>::rewind() noexcept {
53087
  if (error()) { return error(); }
53088
  first.rewind();
53089
  return SUCCESS;
53090
}
53091
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::document_reference>::begin() & noexcept {
53092
  if (error()) { return error(); }
53093
  return first.begin();
53094
}
53095
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::document_reference>::end() & noexcept {
53096
  return {};
53097
}
53098
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
53099
  if (error()) { return error(); }
53100
  return first.find_field_unordered(key);
53101
}
53102
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
53103
  if (error()) { return error(); }
53104
  return first.find_field_unordered(key);
53105
}
53106
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
53107
  if (error()) { return error(); }
53108
  return first[key];
53109
}
53110
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::operator[](const char *key) & noexcept {
53111
  if (error()) { return error(); }
53112
  return first[key];
53113
}
53114
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
53115
  if (error()) { return error(); }
53116
  return first.find_field(key);
53117
}
53118
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::find_field(const char *key) & noexcept {
53119
  if (error()) { return error(); }
53120
  return first.find_field(key);
53121
}
53122
simdjson_inline simdjson_result<haswell::ondemand::array> simdjson_result<haswell::ondemand::document_reference>::get_array() & noexcept {
53123
  if (error()) { return error(); }
53124
  return first.get_array();
53125
}
53126
simdjson_inline simdjson_result<haswell::ondemand::object> simdjson_result<haswell::ondemand::document_reference>::get_object() & noexcept {
53127
  if (error()) { return error(); }
53128
  return first.get_object();
53129
}
53130
simdjson_inline simdjson_result<uint64_t> simdjson_result<haswell::ondemand::document_reference>::get_uint64() noexcept {
53131
  if (error()) { return error(); }
53132
  return first.get_uint64();
53133
}
53134
simdjson_inline simdjson_result<uint64_t> simdjson_result<haswell::ondemand::document_reference>::get_uint64_in_string() noexcept {
53135
  if (error()) { return error(); }
53136
  return first.get_uint64_in_string();
53137
}
53138
simdjson_inline simdjson_result<int64_t> simdjson_result<haswell::ondemand::document_reference>::get_int64() noexcept {
53139
  if (error()) { return error(); }
53140
  return first.get_int64();
53141
}
53142
simdjson_inline simdjson_result<int64_t> simdjson_result<haswell::ondemand::document_reference>::get_int64_in_string() noexcept {
53143
  if (error()) { return error(); }
53144
  return first.get_int64_in_string();
53145
}
53146
simdjson_inline simdjson_result<double> simdjson_result<haswell::ondemand::document_reference>::get_double() noexcept {
53147
  if (error()) { return error(); }
53148
  return first.get_double();
53149
}
53150
simdjson_inline simdjson_result<double> simdjson_result<haswell::ondemand::document_reference>::get_double_in_string() noexcept {
53151
  if (error()) { return error(); }
53152
  return first.get_double_in_string();
53153
}
53154
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::document_reference>::get_string(bool allow_replacement) noexcept {
53155
  if (error()) { return error(); }
53156
  return first.get_string(allow_replacement);
53157
}
53158
template <typename string_type>
53159
simdjson_inline error_code simdjson_result<haswell::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
53160
  if (error()) { return error(); }
53161
  return first.get_string(receiver, allow_replacement);
53162
}
53163
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::document_reference>::get_wobbly_string() noexcept {
53164
  if (error()) { return error(); }
53165
  return first.get_wobbly_string();
53166
}
53167
simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> simdjson_result<haswell::ondemand::document_reference>::get_raw_json_string() noexcept {
53168
  if (error()) { return error(); }
53169
  return first.get_raw_json_string();
53170
}
53171
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document_reference>::get_bool() noexcept {
53172
  if (error()) { return error(); }
53173
  return first.get_bool();
53174
}
53175
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::get_value() noexcept {
53176
  if (error()) { return error(); }
53177
  return first.get_value();
53178
}
53179
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document_reference>::is_null() noexcept {
53180
  if (error()) { return error(); }
53181
  return first.is_null();
53182
}
53183
simdjson_inline simdjson_result<haswell::ondemand::json_type> simdjson_result<haswell::ondemand::document_reference>::type() noexcept {
53184
  if (error()) { return error(); }
53185
  return first.type();
53186
}
53187
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document_reference>::is_scalar() noexcept {
53188
  if (error()) { return error(); }
53189
  return first.is_scalar();
53190
}
53191
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document_reference>::is_string() noexcept {
53192
  if (error()) { return error(); }
53193
  return first.is_string();
53194
}
53195
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document_reference>::is_negative() noexcept {
53196
  if (error()) { return error(); }
53197
  return first.is_negative();
53198
}
53199
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::document_reference>::is_integer() noexcept {
53200
  if (error()) { return error(); }
53201
  return first.is_integer();
53202
}
53203
simdjson_inline simdjson_result<haswell::number_type> simdjson_result<haswell::ondemand::document_reference>::get_number_type() noexcept {
53204
  if (error()) { return error(); }
53205
  return first.get_number_type();
53206
}
53207
simdjson_inline simdjson_result<haswell::ondemand::number> simdjson_result<haswell::ondemand::document_reference>::get_number() noexcept {
53208
  if (error()) { return error(); }
53209
  return first.get_number();
53210
}
53211
#if SIMDJSON_EXCEPTIONS
53212
template <class T, typename std::enable_if<std::is_same<T, haswell::ondemand::document_reference>::value == false>::type>
53213
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator T() noexcept(false) {
53214
  if (error()) { throw simdjson_error(error()); }
53215
  return first;
53216
}
53217
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator haswell::ondemand::array() & noexcept(false) {
53218
  if (error()) { throw simdjson_error(error()); }
53219
  return first;
53220
}
53221
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator haswell::ondemand::object() & noexcept(false) {
53222
  if (error()) { throw simdjson_error(error()); }
53223
  return first;
53224
}
53225
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator uint64_t() noexcept(false) {
53226
  if (error()) { throw simdjson_error(error()); }
53227
  return first;
53228
}
53229
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator int64_t() noexcept(false) {
53230
  if (error()) { throw simdjson_error(error()); }
53231
  return first;
53232
}
53233
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator double() noexcept(false) {
53234
  if (error()) { throw simdjson_error(error()); }
53235
  return first;
53236
}
53237
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator std::string_view() noexcept(false) {
53238
  if (error()) { throw simdjson_error(error()); }
53239
  return first;
53240
}
53241
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator haswell::ondemand::raw_json_string() noexcept(false) {
53242
  if (error()) { throw simdjson_error(error()); }
53243
  return first;
53244
}
53245
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator bool() noexcept(false) {
53246
  if (error()) { throw simdjson_error(error()); }
53247
  return first;
53248
}
53249
simdjson_inline simdjson_result<haswell::ondemand::document_reference>::operator haswell::ondemand::value() noexcept(false) {
53250
  if (error()) { throw simdjson_error(error()); }
53251
  return first;
53252
}
53253
#endif
53254
53255
simdjson_inline simdjson_result<const char *> simdjson_result<haswell::ondemand::document_reference>::current_location() noexcept {
53256
  if (error()) { return error(); }
53257
  return first.current_location();
53258
}
53259
53260
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::document_reference>::raw_json_token() noexcept {
53261
  if (error()) { return error(); }
53262
  return first.raw_json_token();
53263
}
53264
53265
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
53266
  if (error()) { return error(); }
53267
  return first.at_pointer(json_pointer);
53268
}
53269
53270
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::document_reference>::at_path(std::string_view json_path) noexcept {
53271
  if (error()) {
53272
      return error();
53273
  }
53274
  return first.at_path(json_path);
53275
}
53276
53277
} // namespace simdjson
53278
53279
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
53280
/* end file simdjson/generic/ondemand/document-inl.h for haswell */
53281
/* including simdjson/generic/ondemand/document_stream-inl.h for haswell: #include "simdjson/generic/ondemand/document_stream-inl.h" */
53282
/* begin file simdjson/generic/ondemand/document_stream-inl.h for haswell */
53283
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
53284
53285
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
53286
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */
53287
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
53288
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
53289
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
53290
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
53291
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
53292
53293
#include <algorithm>
53294
#include <stdexcept>
53295
53296
namespace simdjson {
53297
namespace haswell {
53298
namespace ondemand {
53299
53300
#ifdef SIMDJSON_THREADS_ENABLED
53301
53302
inline void stage1_worker::finish() {
53303
  // After calling "run" someone would call finish() to wait
53304
  // for the end of the processing.
53305
  // This function will wait until either the thread has done
53306
  // the processing or, else, the destructor has been called.
53307
  std::unique_lock<std::mutex> lock(locking_mutex);
53308
  cond_var.wait(lock, [this]{return has_work == false;});
53309
}
53310
53311
inline stage1_worker::~stage1_worker() {
53312
  // The thread may never outlive the stage1_worker instance
53313
  // and will always be stopped/joined before the stage1_worker
53314
  // instance is gone.
53315
  stop_thread();
53316
}
53317
53318
inline void stage1_worker::start_thread() {
53319
  std::unique_lock<std::mutex> lock(locking_mutex);
53320
  if(thread.joinable()) {
53321
    return; // This should never happen but we never want to create more than one thread.
53322
  }
53323
  thread = std::thread([this]{
53324
      while(true) {
53325
        std::unique_lock<std::mutex> thread_lock(locking_mutex);
53326
        // We wait for either "run" or "stop_thread" to be called.
53327
        cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
53328
        // If, for some reason, the stop_thread() method was called (i.e., the
53329
        // destructor of stage1_worker is called, then we want to immediately destroy
53330
        // the thread (and not do any more processing).
53331
        if(!can_work) {
53332
          break;
53333
        }
53334
        this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
53335
              this->_next_batch_start);
53336
        this->has_work = false;
53337
        // The condition variable call should be moved after thread_lock.unlock() for performance
53338
        // reasons but thread sanitizers may report it as a data race if we do.
53339
        // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
53340
        cond_var.notify_one(); // will notify "finish"
53341
        thread_lock.unlock();
53342
      }
53343
    }
53344
  );
53345
}
53346
53347
53348
inline void stage1_worker::stop_thread() {
53349
  std::unique_lock<std::mutex> lock(locking_mutex);
53350
  // We have to make sure that all locks can be released.
53351
  can_work = false;
53352
  has_work = false;
53353
  cond_var.notify_all();
53354
  lock.unlock();
53355
  if(thread.joinable()) {
53356
    thread.join();
53357
  }
53358
}
53359
53360
inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) {
53361
  std::unique_lock<std::mutex> lock(locking_mutex);
53362
  owner = ds;
53363
  _next_batch_start = next_batch_start;
53364
  stage1_thread_parser = stage1;
53365
  has_work = true;
53366
  // The condition variable call should be moved after thread_lock.unlock() for performance
53367
  // reasons but thread sanitizers may report it as a data race if we do.
53368
  // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
53369
  cond_var.notify_one(); // will notify the thread lock that we have work
53370
  lock.unlock();
53371
}
53372
53373
#endif  // SIMDJSON_THREADS_ENABLED
53374
53375
simdjson_inline document_stream::document_stream(
53376
  ondemand::parser &_parser,
53377
  const uint8_t *_buf,
53378
  size_t _len,
53379
  size_t _batch_size,
53380
  bool _allow_comma_separated
53381
) noexcept
53382
  : parser{&_parser},
53383
    buf{_buf},
53384
    len{_len},
53385
    batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
53386
    allow_comma_separated{_allow_comma_separated},
53387
    error{SUCCESS}
53388
    #ifdef SIMDJSON_THREADS_ENABLED
53389
    , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
53390
    #endif
53391
{
53392
#ifdef SIMDJSON_THREADS_ENABLED
53393
  if(worker.get() == nullptr) {
53394
    error = MEMALLOC;
53395
  }
53396
#endif
53397
}
53398
53399
simdjson_inline document_stream::document_stream() noexcept
53400
  : parser{nullptr},
53401
    buf{nullptr},
53402
    len{0},
53403
    batch_size{0},
53404
    allow_comma_separated{false},
53405
    error{UNINITIALIZED}
53406
    #ifdef SIMDJSON_THREADS_ENABLED
53407
    , use_thread(false)
53408
    #endif
53409
{
53410
}
53411
53412
simdjson_inline document_stream::~document_stream() noexcept
53413
{
53414
  #ifdef SIMDJSON_THREADS_ENABLED
53415
  worker.reset();
53416
  #endif
53417
}
53418
53419
inline size_t document_stream::size_in_bytes() const noexcept {
53420
  return len;
53421
}
53422
53423
inline size_t document_stream::truncated_bytes() const noexcept {
53424
  if(error == CAPACITY) { return len - batch_start; }
53425
  return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
53426
}
53427
53428
simdjson_inline document_stream::iterator::iterator() noexcept
53429
  : stream{nullptr}, finished{true} {
53430
}
53431
53432
simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
53433
  : stream{_stream}, finished{is_end} {
53434
}
53435
53436
simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
53437
  //if(stream->error) { return stream->error; }
53438
  return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
53439
}
53440
53441
simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
53442
  // If there is an error, then we want the iterator
53443
  // to be finished, no matter what. (E.g., we do not
53444
  // keep generating documents with errors, or go beyond
53445
  // a document with errors.)
53446
  //
53447
  // Users do not have to call "operator*()" when they use operator++,
53448
  // so we need to end the stream in the operator++ function.
53449
  //
53450
  // Note that setting finished = true is essential otherwise
53451
  // we would enter an infinite loop.
53452
  if (stream->error) { finished = true; }
53453
  // Note that stream->error() is guarded against error conditions
53454
  // (it will immediately return if stream->error casts to false).
53455
  // In effect, this next function does nothing when (stream->error)
53456
  // is true (hence the risk of an infinite loop).
53457
  stream->next();
53458
  // If that was the last document, we're finished.
53459
  // It is the only type of error we do not want to appear
53460
  // in operator*.
53461
  if (stream->error == EMPTY) { finished = true; }
53462
  // If we had any other kind of error (not EMPTY) then we want
53463
  // to pass it along to the operator* and we cannot mark the result
53464
  // as "finished" just yet.
53465
  return *this;
53466
}
53467
53468
simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
53469
  return finished != other.finished;
53470
}
53471
53472
simdjson_inline document_stream::iterator document_stream::begin() noexcept {
53473
  start();
53474
  // If there are no documents, we're finished.
53475
  return iterator(this, error == EMPTY);
53476
}
53477
53478
simdjson_inline document_stream::iterator document_stream::end() noexcept {
53479
  return iterator(this, true);
53480
}
53481
53482
inline void document_stream::start() noexcept {
53483
  if (error) { return; }
53484
  error = parser->allocate(batch_size);
53485
  if (error) { return; }
53486
  // Always run the first stage 1 parse immediately
53487
  batch_start = 0;
53488
  error = run_stage1(*parser, batch_start);
53489
  while(error == EMPTY) {
53490
    // In exceptional cases, we may start with an empty block
53491
    batch_start = next_batch_start();
53492
    if (batch_start >= len) { return; }
53493
    error = run_stage1(*parser, batch_start);
53494
  }
53495
  if (error) { return; }
53496
  doc_index = batch_start;
53497
  doc = document(json_iterator(&buf[batch_start], parser));
53498
  doc.iter._streaming = true;
53499
53500
  #ifdef SIMDJSON_THREADS_ENABLED
53501
  if (use_thread && next_batch_start() < len) {
53502
    // Kick off the first thread on next batch if needed
53503
    error = stage1_thread_parser.allocate(batch_size);
53504
    if (error) { return; }
53505
    worker->start_thread();
53506
    start_stage1_thread();
53507
    if (error) { return; }
53508
  }
53509
  #endif // SIMDJSON_THREADS_ENABLED
53510
}
53511
53512
inline void document_stream::next() noexcept {
53513
  // We always enter at once once in an error condition.
53514
  if (error) { return; }
53515
  next_document();
53516
  if (error) { return; }
53517
  auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get();
53518
  doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index];
53519
53520
  // Check if at end of structural indexes (i.e. at end of batch)
53521
  if(cur_struct_index >= static_cast<int64_t>(parser->implementation->n_structural_indexes)) {
53522
    error = EMPTY;
53523
    // Load another batch (if available)
53524
    while (error == EMPTY) {
53525
      batch_start = next_batch_start();
53526
      if (batch_start >= len) { break; }
53527
      #ifdef SIMDJSON_THREADS_ENABLED
53528
      if(use_thread) {
53529
        load_from_stage1_thread();
53530
      } else {
53531
        error = run_stage1(*parser, batch_start);
53532
      }
53533
      #else
53534
      error = run_stage1(*parser, batch_start);
53535
      #endif
53536
      /**
53537
       * Whenever we move to another window, we need to update all pointers to make
53538
       * it appear as if the input buffer started at the beginning of the window.
53539
       *
53540
       * Take this input:
53541
       *
53542
       * {"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]  [15,  11,   12, 13]  [154,  110,   112, 1311]
53543
       *
53544
       * Say you process the following window...
53545
       *
53546
       * '{"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]'
53547
       *
53548
       * When you do so, the json_iterator has a pointer at the beginning of the memory region
53549
       * (pointing at the beginning of '{"z"...'.
53550
       *
53551
       * When you move to the window that starts at...
53552
       *
53553
       * '[7,  10,   9]  [15,  11,   12, 13] ...
53554
       *
53555
       * then it is not sufficient to just run stage 1. You also need to re-anchor the
53556
       * json_iterator so that it believes we are starting at '[7,  10,   9]...'.
53557
       *
53558
       * Under the DOM front-end, this gets done automatically because the parser owns
53559
       * the pointer the data, and when you call stage1 and then stage2 on the same
53560
       * parser, then stage2 will run on the pointer acquired by stage1.
53561
       *
53562
       * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that
53563
       * we used. But json_iterator has no callback when stage1 is called on the parser.
53564
       * In fact, I think that the parser is unaware of json_iterator.
53565
       *
53566
       *
53567
       * So we need to re-anchor the json_iterator after each call to stage 1 so that
53568
       * all of the pointers are in sync.
53569
       */
53570
      doc.iter = json_iterator(&buf[batch_start], parser);
53571
      doc.iter._streaming = true;
53572
      /**
53573
       * End of resync.
53574
       */
53575
53576
      if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
53577
      doc_index = batch_start;
53578
    }
53579
  }
53580
}
53581
53582
inline void document_stream::next_document() noexcept {
53583
  // Go to next place where depth=0 (document depth)
53584
  error = doc.iter.skip_child(0);
53585
  if (error) { return; }
53586
  // Always set depth=1 at the start of document
53587
  doc.iter._depth = 1;
53588
  // consume comma if comma separated is allowed
53589
  if (allow_comma_separated) { doc.iter.consume_character(','); }
53590
  // Resets the string buffer at the beginning, thus invalidating the strings.
53591
  doc.iter._string_buf_loc = parser->string_buf.get();
53592
  doc.iter._root = doc.iter.position();
53593
}
53594
53595
inline size_t document_stream::next_batch_start() const noexcept {
53596
  return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
53597
}
53598
53599
inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept {
53600
  // This code only updates the structural index in the parser, it does not update any json_iterator
53601
  // instance.
53602
  size_t remaining = len - _batch_start;
53603
  if (remaining <= batch_size) {
53604
    return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
53605
  } else {
53606
    return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
53607
  }
53608
}
53609
53610
simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
53611
  return stream->doc_index;
53612
}
53613
53614
simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
53615
  auto depth = stream->doc.iter.depth();
53616
  auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get();
53617
53618
  // If at root, process the first token to determine if scalar value
53619
  if (stream->doc.iter.at_root()) {
53620
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
53621
      case '{': case '[':   // Depth=1 already at start of document
53622
        break;
53623
      case '}': case ']':
53624
        depth--;
53625
        break;
53626
      default:    // Scalar value document
53627
        // TODO: Remove any trailing whitespaces
53628
        // This returns a string spanning from start of value to the beginning of the next document (excluded)
53629
        return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[++cur_struct_index] - current_index() - 1);
53630
    }
53631
    cur_struct_index++;
53632
  }
53633
53634
  while (cur_struct_index <= static_cast<int64_t>(stream->parser->implementation->n_structural_indexes)) {
53635
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
53636
      case '{': case '[':
53637
        depth++;
53638
        break;
53639
      case '}': case ']':
53640
        depth--;
53641
        break;
53642
    }
53643
    if (depth == 0) { break; }
53644
    cur_struct_index++;
53645
  }
53646
53647
  return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);;
53648
}
53649
53650
inline error_code document_stream::iterator::error() const noexcept {
53651
  return stream->error;
53652
}
53653
53654
#ifdef SIMDJSON_THREADS_ENABLED
53655
53656
inline void document_stream::load_from_stage1_thread() noexcept {
53657
  worker->finish();
53658
  // Swap to the parser that was loaded up in the thread. Make sure the parser has
53659
  // enough memory to swap to, as well.
53660
  std::swap(stage1_thread_parser,*parser);
53661
  error = stage1_thread_error;
53662
  if (error) { return; }
53663
53664
  // If there's anything left, start the stage 1 thread!
53665
  if (next_batch_start() < len) {
53666
    start_stage1_thread();
53667
  }
53668
}
53669
53670
inline void document_stream::start_stage1_thread() noexcept {
53671
  // we call the thread on a lambda that will update
53672
  // this->stage1_thread_error
53673
  // there is only one thread that may write to this value
53674
  // TODO this is NOT exception-safe.
53675
  this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
53676
  size_t _next_batch_start = this->next_batch_start();
53677
53678
  worker->run(this, & this->stage1_thread_parser, _next_batch_start);
53679
}
53680
53681
#endif // SIMDJSON_THREADS_ENABLED
53682
53683
} // namespace ondemand
53684
} // namespace haswell
53685
} // namespace simdjson
53686
53687
namespace simdjson {
53688
53689
simdjson_inline simdjson_result<haswell::ondemand::document_stream>::simdjson_result(
53690
  error_code error
53691
) noexcept :
53692
    implementation_simdjson_result_base<haswell::ondemand::document_stream>(error)
53693
{
53694
}
53695
simdjson_inline simdjson_result<haswell::ondemand::document_stream>::simdjson_result(
53696
  haswell::ondemand::document_stream &&value
53697
) noexcept :
53698
    implementation_simdjson_result_base<haswell::ondemand::document_stream>(
53699
      std::forward<haswell::ondemand::document_stream>(value)
53700
    )
53701
{
53702
}
53703
53704
}
53705
53706
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
53707
/* end file simdjson/generic/ondemand/document_stream-inl.h for haswell */
53708
/* including simdjson/generic/ondemand/field-inl.h for haswell: #include "simdjson/generic/ondemand/field-inl.h" */
53709
/* begin file simdjson/generic/ondemand/field-inl.h for haswell */
53710
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
53711
53712
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
53713
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */
53714
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
53715
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
53716
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
53717
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
53718
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
53719
53720
namespace simdjson {
53721
namespace haswell {
53722
namespace ondemand {
53723
53724
// clang 6 does not think the default constructor can be noexcept, so we make it explicit
53725
simdjson_inline field::field() noexcept : std::pair<raw_json_string, ondemand::value>() {}
53726
53727
simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept
53728
  : std::pair<raw_json_string, ondemand::value>(key, std::forward<ondemand::value>(value))
53729
{
53730
}
53731
53732
simdjson_inline simdjson_result<field> field::start(value_iterator &parent_iter) noexcept {
53733
  raw_json_string key;
53734
  SIMDJSON_TRY( parent_iter.field_key().get(key) );
53735
  SIMDJSON_TRY( parent_iter.field_value() );
53736
  return field::start(parent_iter, key);
53737
}
53738
53739
simdjson_inline simdjson_result<field> field::start(const value_iterator &parent_iter, raw_json_string key) noexcept {
53740
    return field(key, parent_iter.child());
53741
}
53742
53743
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> field::unescaped_key(bool allow_replacement) noexcept {
53744
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us.
53745
  simdjson_result<std::string_view> answer = first.unescape(second.iter.json_iter(), allow_replacement);
53746
  first.consume();
53747
  return answer;
53748
}
53749
53750
simdjson_inline raw_json_string field::key() const noexcept {
53751
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
53752
  return first;
53753
}
53754
53755
53756
simdjson_inline std::string_view field::key_raw_json_token() const noexcept {
53757
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
53758
  return std::string_view(reinterpret_cast<const char*>(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1);
53759
}
53760
53761
simdjson_inline value &field::value() & noexcept {
53762
  return second;
53763
}
53764
53765
simdjson_inline value field::value() && noexcept {
53766
  return std::forward<field>(*this).second;
53767
}
53768
53769
} // namespace ondemand
53770
} // namespace haswell
53771
} // namespace simdjson
53772
53773
namespace simdjson {
53774
53775
simdjson_inline simdjson_result<haswell::ondemand::field>::simdjson_result(
53776
  haswell::ondemand::field &&value
53777
) noexcept :
53778
    implementation_simdjson_result_base<haswell::ondemand::field>(
53779
      std::forward<haswell::ondemand::field>(value)
53780
    )
53781
{
53782
}
53783
simdjson_inline simdjson_result<haswell::ondemand::field>::simdjson_result(
53784
  error_code error
53785
) noexcept :
53786
    implementation_simdjson_result_base<haswell::ondemand::field>(error)
53787
{
53788
}
53789
53790
simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> simdjson_result<haswell::ondemand::field>::key() noexcept {
53791
  if (error()) { return error(); }
53792
  return first.key();
53793
}
53794
53795
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::field>::key_raw_json_token() noexcept {
53796
  if (error()) { return error(); }
53797
  return first.key_raw_json_token();
53798
}
53799
53800
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::field>::unescaped_key(bool allow_replacement) noexcept {
53801
  if (error()) { return error(); }
53802
  return first.unescaped_key(allow_replacement);
53803
}
53804
53805
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::field>::value() noexcept {
53806
  if (error()) { return error(); }
53807
  return std::move(first.value());
53808
}
53809
53810
} // namespace simdjson
53811
53812
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
53813
/* end file simdjson/generic/ondemand/field-inl.h for haswell */
53814
/* including simdjson/generic/ondemand/json_iterator-inl.h for haswell: #include "simdjson/generic/ondemand/json_iterator-inl.h" */
53815
/* begin file simdjson/generic/ondemand/json_iterator-inl.h for haswell */
53816
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
53817
53818
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
53819
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */
53820
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
53821
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
53822
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
53823
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
53824
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
53825
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */
53826
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */
53827
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */
53828
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
53829
53830
namespace simdjson {
53831
namespace haswell {
53832
namespace ondemand {
53833
53834
simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
53835
  : token(std::forward<token_iterator>(other.token)),
53836
    parser{other.parser},
53837
    _string_buf_loc{other._string_buf_loc},
53838
    error{other.error},
53839
    _depth{other._depth},
53840
    _root{other._root},
53841
    _streaming{other._streaming}
53842
{
53843
  other.parser = nullptr;
53844
}
53845
simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept {
53846
  token = other.token;
53847
  parser = other.parser;
53848
  _string_buf_loc = other._string_buf_loc;
53849
  error = other.error;
53850
  _depth = other._depth;
53851
  _root = other._root;
53852
  _streaming = other._streaming;
53853
  other.parser = nullptr;
53854
  return *this;
53855
}
53856
53857
simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept
53858
  : token(buf, &_parser->implementation->structural_indexes[0]),
53859
    parser{_parser},
53860
    _string_buf_loc{parser->string_buf.get()},
53861
    _depth{1},
53862
    _root{parser->implementation->structural_indexes.get()},
53863
    _streaming{false}
53864
53865
{
53866
  logger::log_headers();
53867
#if SIMDJSON_CHECK_EOF
53868
  assert_more_tokens();
53869
#endif
53870
}
53871
53872
inline void json_iterator::rewind() noexcept {
53873
  token.set_position( root_position() );
53874
  logger::log_headers(); // We start again
53875
  _string_buf_loc = parser->string_buf.get();
53876
  _depth = 1;
53877
}
53878
53879
inline bool json_iterator::balanced() const noexcept {
53880
  token_iterator ti(token);
53881
  int32_t count{0};
53882
  ti.set_position( root_position() );
53883
  while(ti.peek() <= peek_last()) {
53884
    switch (*ti.return_current_and_advance())
53885
    {
53886
    case '[': case '{':
53887
      count++;
53888
      break;
53889
    case ']': case '}':
53890
      count--;
53891
      break;
53892
    default:
53893
      break;
53894
    }
53895
  }
53896
  return count == 0;
53897
}
53898
53899
53900
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
53901
// relating depth and parent_depth, which is a desired effect. The warning does not show up if the
53902
// skip_child() function is not marked inline).
53903
SIMDJSON_PUSH_DISABLE_WARNINGS
53904
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
53905
simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
53906
  if (depth() <= parent_depth) { return SUCCESS; }
53907
  switch (*return_current_and_advance()) {
53908
    // TODO consider whether matching braces is a requirement: if non-matching braces indicates
53909
    // *missing* braces, then future lookups are not in the object/arrays they think they are,
53910
    // violating the rule "validate enough structure that the user can be confident they are
53911
    // looking at the right values."
53912
    // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
53913
53914
    // For the first open array/object in a value, we've already incremented depth, so keep it the same
53915
    // We never stop at colon, but if we did, it wouldn't affect depth
53916
    case '[': case '{': case ':':
53917
      logger::log_start_value(*this, "skip");
53918
      break;
53919
    // If there is a comma, we have just finished a value in an array/object, and need to get back in
53920
    case ',':
53921
      logger::log_value(*this, "skip");
53922
      break;
53923
    // ] or } means we just finished a value and need to jump out of the array/object
53924
    case ']': case '}':
53925
      logger::log_end_value(*this, "skip");
53926
      _depth--;
53927
      if (depth() <= parent_depth) { return SUCCESS; }
53928
#if SIMDJSON_CHECK_EOF
53929
      // If there are no more tokens, the parent is incomplete.
53930
      if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
53931
#endif // SIMDJSON_CHECK_EOF
53932
      break;
53933
    case '"':
53934
      if(*peek() == ':') {
53935
        // We are at a key!!!
53936
        // This might happen if you just started an object and you skip it immediately.
53937
        // Performance note: it would be nice to get rid of this check as it is somewhat
53938
        // expensive.
53939
        // https://github.com/simdjson/simdjson/issues/1742
53940
        logger::log_value(*this, "key");
53941
        return_current_and_advance(); // eat up the ':'
53942
        break; // important!!!
53943
      }
53944
      simdjson_fallthrough;
53945
    // Anything else must be a scalar value
53946
    default:
53947
      // For the first scalar, we will have incremented depth already, so we decrement it here.
53948
      logger::log_value(*this, "skip");
53949
      _depth--;
53950
      if (depth() <= parent_depth) { return SUCCESS; }
53951
      break;
53952
  }
53953
53954
  // Now that we've considered the first value, we only increment/decrement for arrays/objects
53955
  while (position() < end_position()) {
53956
    switch (*return_current_and_advance()) {
53957
      case '[': case '{':
53958
        logger::log_start_value(*this, "skip");
53959
        _depth++;
53960
        break;
53961
      // TODO consider whether matching braces is a requirement: if non-matching braces indicates
53962
      // *missing* braces, then future lookups are not in the object/arrays they think they are,
53963
      // violating the rule "validate enough structure that the user can be confident they are
53964
      // looking at the right values."
53965
      // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
53966
      case ']': case '}':
53967
        logger::log_end_value(*this, "skip");
53968
        _depth--;
53969
        if (depth() <= parent_depth) { return SUCCESS; }
53970
        break;
53971
      default:
53972
        logger::log_value(*this, "skip", "");
53973
        break;
53974
    }
53975
  }
53976
53977
  return report_error(TAPE_ERROR, "not enough close braces");
53978
}
53979
53980
SIMDJSON_POP_DISABLE_WARNINGS
53981
53982
simdjson_inline bool json_iterator::at_root() const noexcept {
53983
  return position() == root_position();
53984
}
53985
53986
simdjson_inline bool json_iterator::is_single_token() const noexcept {
53987
  return parser->implementation->n_structural_indexes == 1;
53988
}
53989
53990
simdjson_inline bool json_iterator::streaming() const noexcept {
53991
  return _streaming;
53992
}
53993
53994
simdjson_inline token_position json_iterator::root_position() const noexcept {
53995
  return _root;
53996
}
53997
53998
simdjson_inline void json_iterator::assert_at_document_depth() const noexcept {
53999
  SIMDJSON_ASSUME( _depth == 1 );
54000
}
54001
54002
simdjson_inline void json_iterator::assert_at_root() const noexcept {
54003
  SIMDJSON_ASSUME( _depth == 1 );
54004
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
54005
  // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument
54006
  // has side effects that will be discarded.
54007
  SIMDJSON_ASSUME( token.position() == _root );
54008
#endif
54009
}
54010
54011
simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
54012
  assert_valid_position(token._position + required_tokens - 1);
54013
}
54014
54015
simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
54016
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
54017
  SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
54018
  SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
54019
#endif
54020
}
54021
54022
simdjson_inline bool json_iterator::at_end() const noexcept {
54023
  return position() == end_position();
54024
}
54025
simdjson_inline token_position json_iterator::end_position() const noexcept {
54026
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
54027
  return &parser->implementation->structural_indexes[n_structural_indexes];
54028
}
54029
54030
inline std::string json_iterator::to_string() const noexcept {
54031
  if( !is_alive() ) { return "dead json_iterator instance"; }
54032
  const char * current_structural = reinterpret_cast<const char *>(token.peek());
54033
  return std::string("json_iterator [ depth : ") + std::to_string(_depth)
54034
          + std::string(", structural : '") + std::string(current_structural,1)
54035
          + std::string("', offset : ") + std::to_string(token.current_offset())
54036
          + std::string("', error : ") + error_message(error)
54037
          + std::string(" ]");
54038
}
54039
54040
inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
54041
  if (!is_alive()) {    // Unrecoverable error
54042
    if (!at_root()) {
54043
      return reinterpret_cast<const char *>(token.peek(-1));
54044
    } else {
54045
      return reinterpret_cast<const char *>(token.peek());
54046
    }
54047
  }
54048
  if (at_end()) {
54049
    return OUT_OF_BOUNDS;
54050
  }
54051
  return reinterpret_cast<const char *>(token.peek());
54052
}
54053
54054
simdjson_inline bool json_iterator::is_alive() const noexcept {
54055
  return parser;
54056
}
54057
54058
simdjson_inline void json_iterator::abandon() noexcept {
54059
  parser = nullptr;
54060
  _depth = 0;
54061
}
54062
54063
simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
54064
#if SIMDJSON_CHECK_EOF
54065
  assert_more_tokens();
54066
#endif // SIMDJSON_CHECK_EOF
54067
  return token.return_current_and_advance();
54068
}
54069
54070
simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
54071
  // deliberately done without safety guard:
54072
  return token.peek();
54073
}
54074
54075
simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
54076
#if SIMDJSON_CHECK_EOF
54077
  assert_more_tokens(delta+1);
54078
#endif // SIMDJSON_CHECK_EOF
54079
  return token.peek(delta);
54080
}
54081
54082
simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
54083
#if SIMDJSON_CHECK_EOF
54084
  assert_more_tokens(delta+1);
54085
#endif // #if SIMDJSON_CHECK_EOF
54086
  return token.peek_length(delta);
54087
}
54088
54089
simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
54090
  // todo: currently we require end-of-string buffering, but the following
54091
  // assert_valid_position should be turned on if/when we lift that condition.
54092
  // assert_valid_position(position);
54093
  // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
54094
  // is ON by default, we have no choice but to disable it for real with a comment.
54095
  return token.peek(position);
54096
}
54097
54098
simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
54099
#if SIMDJSON_CHECK_EOF
54100
  assert_valid_position(position);
54101
#endif // SIMDJSON_CHECK_EOF
54102
  return token.peek_length(position);
54103
}
54104
simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept {
54105
#if SIMDJSON_CHECK_EOF
54106
  assert_valid_position(position);
54107
#endif // SIMDJSON_CHECK_EOF
54108
  return token.peek_root_length(position);
54109
}
54110
54111
simdjson_inline token_position json_iterator::last_position() const noexcept {
54112
  // The following line fails under some compilers...
54113
  // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0);
54114
  // since it has side-effects.
54115
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
54116
  SIMDJSON_ASSUME(n_structural_indexes > 0);
54117
  return &parser->implementation->structural_indexes[n_structural_indexes - 1];
54118
}
54119
simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept {
54120
  return token.peek(last_position());
54121
}
54122
54123
simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
54124
  SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
54125
  SIMDJSON_ASSUME(_depth == parent_depth + 1);
54126
  _depth = parent_depth;
54127
}
54128
54129
simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
54130
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
54131
  SIMDJSON_ASSUME(_depth == child_depth - 1);
54132
  _depth = child_depth;
54133
}
54134
54135
simdjson_inline depth_t json_iterator::depth() const noexcept {
54136
  return _depth;
54137
}
54138
54139
simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
54140
  return _string_buf_loc;
54141
}
54142
54143
simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept {
54144
  SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD);
54145
  logger::log_error(*this, message);
54146
  error = _error;
54147
  return error;
54148
}
54149
54150
simdjson_inline token_position json_iterator::position() const noexcept {
54151
  return token.position();
54152
}
54153
54154
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept {
54155
  return parser->unescape(in, _string_buf_loc, allow_replacement);
54156
}
54157
54158
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in) noexcept {
54159
  return parser->unescape_wobbly(in, _string_buf_loc);
54160
}
54161
54162
simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
54163
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
54164
  SIMDJSON_ASSUME(_depth == child_depth - 1);
54165
#if SIMDJSON_DEVELOPMENT_CHECKS
54166
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
54167
  SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
54168
  SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
54169
#endif
54170
#endif
54171
  token.set_position(position);
54172
  _depth = child_depth;
54173
}
54174
54175
simdjson_inline error_code json_iterator::consume_character(char c) noexcept {
54176
  if (*peek() == c) {
54177
    return_current_and_advance();
54178
    return SUCCESS;
54179
  }
54180
  return TAPE_ERROR;
54181
}
54182
54183
#if SIMDJSON_DEVELOPMENT_CHECKS
54184
54185
simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
54186
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
54187
  return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
54188
}
54189
54190
simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
54191
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
54192
  if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
54193
}
54194
54195
#endif
54196
54197
54198
simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept {
54199
  SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD);
54200
  logger::log_error(*this, message);
54201
  return _error;
54202
}
54203
54204
54205
simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept {
54206
  // This function is not expected to be called in performance-sensitive settings.
54207
  // Let us guard against silly cases:
54208
  if((N < max_len) || (N == 0)) { return false; }
54209
  // Copy to the buffer.
54210
  std::memcpy(tmpbuf, json, max_len);
54211
  if(N > max_len) { // We pad whatever remains with ' '.
54212
    std::memset(tmpbuf + max_len, ' ', N - max_len);
54213
  }
54214
  return true;
54215
}
54216
54217
} // namespace ondemand
54218
} // namespace haswell
54219
} // namespace simdjson
54220
54221
namespace simdjson {
54222
54223
simdjson_inline simdjson_result<haswell::ondemand::json_iterator>::simdjson_result(haswell::ondemand::json_iterator &&value) noexcept
54224
    : implementation_simdjson_result_base<haswell::ondemand::json_iterator>(std::forward<haswell::ondemand::json_iterator>(value)) {}
54225
simdjson_inline simdjson_result<haswell::ondemand::json_iterator>::simdjson_result(error_code error) noexcept
54226
    : implementation_simdjson_result_base<haswell::ondemand::json_iterator>(error) {}
54227
54228
} // namespace simdjson
54229
54230
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
54231
/* end file simdjson/generic/ondemand/json_iterator-inl.h for haswell */
54232
/* including simdjson/generic/ondemand/json_type-inl.h for haswell: #include "simdjson/generic/ondemand/json_type-inl.h" */
54233
/* begin file simdjson/generic/ondemand/json_type-inl.h for haswell */
54234
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
54235
54236
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
54237
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */
54238
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
54239
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
54240
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
54241
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
54242
54243
namespace simdjson {
54244
namespace haswell {
54245
namespace ondemand {
54246
54247
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
54248
    switch (type) {
54249
        case json_type::array: out << "array"; break;
54250
        case json_type::object: out << "object"; break;
54251
        case json_type::number: out << "number"; break;
54252
        case json_type::string: out << "string"; break;
54253
        case json_type::boolean: out << "boolean"; break;
54254
        case json_type::null: out << "null"; break;
54255
        default: SIMDJSON_UNREACHABLE();
54256
    }
54257
    return out;
54258
}
54259
54260
#if SIMDJSON_EXCEPTIONS
54261
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
54262
    return out << type.value();
54263
}
54264
#endif
54265
54266
54267
54268
simdjson_inline number_type number::get_number_type() const noexcept {
54269
  return type;
54270
}
54271
54272
simdjson_inline bool number::is_uint64() const noexcept {
54273
  return get_number_type() == number_type::unsigned_integer;
54274
}
54275
54276
simdjson_inline uint64_t number::get_uint64() const noexcept {
54277
  return payload.unsigned_integer;
54278
}
54279
54280
simdjson_inline number::operator uint64_t() const noexcept {
54281
  return get_uint64();
54282
}
54283
54284
simdjson_inline bool number::is_int64() const noexcept {
54285
  return get_number_type() == number_type::signed_integer;
54286
}
54287
54288
simdjson_inline int64_t number::get_int64() const noexcept {
54289
  return payload.signed_integer;
54290
}
54291
54292
simdjson_inline number::operator int64_t() const noexcept {
54293
  return get_int64();
54294
}
54295
54296
simdjson_inline bool number::is_double() const noexcept {
54297
    return get_number_type() == number_type::floating_point_number;
54298
}
54299
54300
simdjson_inline double number::get_double() const noexcept {
54301
  return payload.floating_point_number;
54302
}
54303
54304
simdjson_inline number::operator double() const noexcept {
54305
  return get_double();
54306
}
54307
54308
simdjson_inline double number::as_double() const noexcept {
54309
  if(is_double()) {
54310
    return payload.floating_point_number;
54311
  }
54312
  if(is_int64()) {
54313
    return double(payload.signed_integer);
54314
  }
54315
  return double(payload.unsigned_integer);
54316
}
54317
54318
simdjson_inline void number::append_s64(int64_t value) noexcept {
54319
  payload.signed_integer = value;
54320
  type = number_type::signed_integer;
54321
}
54322
54323
simdjson_inline void number::append_u64(uint64_t value) noexcept {
54324
  payload.unsigned_integer = value;
54325
  type = number_type::unsigned_integer;
54326
}
54327
54328
simdjson_inline void number::append_double(double value) noexcept {
54329
  payload.floating_point_number = value;
54330
  type = number_type::floating_point_number;
54331
}
54332
54333
simdjson_inline void number::skip_double() noexcept {
54334
  type = number_type::floating_point_number;
54335
}
54336
54337
} // namespace ondemand
54338
} // namespace haswell
54339
} // namespace simdjson
54340
54341
namespace simdjson {
54342
54343
simdjson_inline simdjson_result<haswell::ondemand::json_type>::simdjson_result(haswell::ondemand::json_type &&value) noexcept
54344
    : implementation_simdjson_result_base<haswell::ondemand::json_type>(std::forward<haswell::ondemand::json_type>(value)) {}
54345
simdjson_inline simdjson_result<haswell::ondemand::json_type>::simdjson_result(error_code error) noexcept
54346
    : implementation_simdjson_result_base<haswell::ondemand::json_type>(error) {}
54347
54348
} // namespace simdjson
54349
54350
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
54351
/* end file simdjson/generic/ondemand/json_type-inl.h for haswell */
54352
/* including simdjson/generic/ondemand/logger-inl.h for haswell: #include "simdjson/generic/ondemand/logger-inl.h" */
54353
/* begin file simdjson/generic/ondemand/logger-inl.h for haswell */
54354
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
54355
54356
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
54357
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */
54358
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
54359
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
54360
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
54361
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
54362
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
54363
54364
#include <memory>
54365
#include <cstring>
54366
54367
namespace simdjson {
54368
namespace haswell {
54369
namespace ondemand {
54370
namespace logger {
54371
54372
static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
54373
static constexpr const int LOG_EVENT_LEN = 20;
54374
static constexpr const int LOG_BUFFER_LEN = 30;
54375
static constexpr const int LOG_SMALL_BUFFER_LEN = 10;
54376
static int log_depth = 0; // Not threadsafe. Log only.
54377
54378
// Helper to turn unprintable or newline characters into spaces
54379
static inline char printable_char(char c) {
54380
  if (c >= 0x20) {
54381
    return c;
54382
  } else {
54383
    return ' ';
54384
  }
54385
}
54386
54387
template<typename... Args>
54388
static inline std::string string_format(const std::string& format, const Args&... args)
54389
{
54390
  SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
54391
  int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
54392
  auto size = static_cast<size_t>(size_s);
54393
  if (size <= 0) return std::string();
54394
  std::unique_ptr<char[]> buf(new char[size]);
54395
  std::snprintf(buf.get(), size, format.c_str(), args...);
54396
  SIMDJSON_POP_DISABLE_WARNINGS
54397
  return std::string(buf.get(), buf.get() + size - 1);
54398
}
54399
54400
static inline log_level get_log_level_from_env()
54401
{
54402
  SIMDJSON_PUSH_DISABLE_WARNINGS
54403
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
54404
      char *lvl = getenv("SIMDJSON_LOG_LEVEL");
54405
  SIMDJSON_POP_DISABLE_WARNINGS
54406
  if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; }
54407
  return log_level::info;
54408
}
54409
54410
static inline log_level log_threshold()
54411
{
54412
  static log_level threshold = get_log_level_from_env();
54413
  return threshold;
54414
}
54415
54416
static inline bool should_log(log_level level)
54417
{
54418
  return level >= log_threshold();
54419
}
54420
54421
inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
54422
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
54423
}
54424
54425
inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
54426
  log_line(iter, index, depth, "", type, detail, log_level::info);
54427
}
54428
inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
54429
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
54430
}
54431
54432
inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
54433
  log_line(iter, index, depth, "+", type, detail, log_level::info);
54434
  if (LOG_ENABLED) { log_depth++; }
54435
}
54436
inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
54437
  log_line(iter, "+", type, "", delta, depth_delta, log_level::info);
54438
  if (LOG_ENABLED) { log_depth++; }
54439
}
54440
54441
inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
54442
  if (LOG_ENABLED) { log_depth--; }
54443
  log_line(iter, "-", type, "", delta, depth_delta, log_level::info);
54444
}
54445
54446
inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
54447
  log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error);
54448
}
54449
inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept {
54450
  log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error);
54451
}
54452
54453
inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
54454
  log_event(iter.json_iter(), type, detail, delta, depth_delta);
54455
}
54456
54457
inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
54458
  log_value(iter.json_iter(), type, detail, delta, depth_delta);
54459
}
54460
54461
inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
54462
  log_start_value(iter.json_iter(), type, delta, depth_delta);
54463
}
54464
54465
inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
54466
  log_end_value(iter.json_iter(), type, delta, depth_delta);
54467
}
54468
54469
inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
54470
  log_error(iter.json_iter(), error, detail, delta, depth_delta);
54471
}
54472
54473
inline void log_headers() noexcept {
54474
  if (LOG_ENABLED) {
54475
    if (simdjson_unlikely(should_log(log_level::info))) {
54476
      // Technically a static variable is not thread-safe, but if you are using threads and logging... well...
54477
      static bool displayed_hint{false};
54478
      log_depth = 0;
54479
      printf("\n");
54480
      if (!displayed_hint) {
54481
        // We only print this helpful header once.
54482
        printf("# Logging provides the depth and position of the iterator user-visible steps:\n");
54483
        printf("# +array says 'this is where we were when we discovered the start array'\n");
54484
        printf(
54485
            "# -array says 'this is where we were when we ended the array'\n");
54486
        printf("# skip says 'this is a structural or value I am skipping'\n");
54487
        printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
54488
        printf("#\n");
54489
        printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
54490
        printf("# in addition to the depth being displayed.\n");
54491
        printf("#\n");
54492
        printf("# Every token in the document has a single depth determined by the tokens before it,\n");
54493
        printf("# and is not affected by what the token actually is.\n");
54494
        printf("#\n");
54495
        printf("# Not all structural elements are presented as tokens in the logs.\n");
54496
        printf("#\n");
54497
        printf("# We never give control to the user within an empty array or an empty object.\n");
54498
        printf("#\n");
54499
        printf("# Inside an array, having a depth greater than the array's depth means that\n");
54500
        printf("# we are pointing inside a value.\n");
54501
        printf("# Having a depth equal to the array means that we are pointing right before a value.\n");
54502
        printf("# Having a depth smaller than the array means that we have moved beyond the array.\n");
54503
        displayed_hint = true;
54504
      }
54505
      printf("\n");
54506
      printf("| %-*s ", LOG_EVENT_LEN, "Event");
54507
      printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
54508
      printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next");
54509
      // printf("| %-*s ", 5,                    "Next#");
54510
      printf("| %-*s ", 5, "Depth");
54511
      printf("| Detail ");
54512
      printf("|\n");
54513
54514
      printf("|%.*s", LOG_EVENT_LEN + 2, DASHES);
54515
      printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES);
54516
      printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
54517
      // printf("|%.*s", 5+2, DASHES);
54518
      printf("|%.*s", 5 + 2, DASHES);
54519
      printf("|--------");
54520
      printf("|\n");
54521
      fflush(stdout);
54522
    }
54523
  }
54524
}
54525
54526
template <typename... Args>
54527
inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept {
54528
  log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
54529
}
54530
54531
template <typename... Args>
54532
inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
54533
  if (LOG_ENABLED) {
54534
    if (simdjson_unlikely(should_log(level))) {
54535
      const int indent = depth * 2;
54536
      const auto buf = iter.token.buf;
54537
      auto msg = string_format(title, std::forward<Args>(args)...);
54538
      printf("| %*s%s%-*s ", indent, "", title_prefix,
54539
             LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str());
54540
      {
54541
        // Print the current structural.
54542
        printf("| ");
54543
        // Before we begin, the index might point right before the document.
54544
        // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
54545
        if (index < iter._root) {
54546
          printf("%*s", LOG_BUFFER_LEN, "");
54547
        } else {
54548
          auto current_structural = &buf[*index];
54549
          for (int i = 0; i < LOG_BUFFER_LEN; i++) {
54550
            printf("%c", printable_char(current_structural[i]));
54551
          }
54552
        }
54553
        printf(" ");
54554
      }
54555
      {
54556
        // Print the next structural.
54557
        printf("| ");
54558
        auto next_structural = &buf[*(index + 1)];
54559
        for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
54560
          printf("%c", printable_char(next_structural[i]));
54561
        }
54562
        printf(" ");
54563
      }
54564
      // printf("| %5u ", *(index+1));
54565
      printf("| %5i ", depth);
54566
      printf("| %6.*s ", int(detail.size()), detail.data());
54567
      printf("|\n");
54568
      fflush(stdout);
54569
    }
54570
  }
54571
}
54572
54573
} // namespace logger
54574
} // namespace ondemand
54575
} // namespace haswell
54576
} // namespace simdjson
54577
54578
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
54579
/* end file simdjson/generic/ondemand/logger-inl.h for haswell */
54580
/* including simdjson/generic/ondemand/object-inl.h for haswell: #include "simdjson/generic/ondemand/object-inl.h" */
54581
/* begin file simdjson/generic/ondemand/object-inl.h for haswell */
54582
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
54583
54584
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
54585
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */
54586
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
54587
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
54588
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
54589
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
54590
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
54591
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
54592
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
54593
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
54594
54595
namespace simdjson {
54596
namespace haswell {
54597
namespace ondemand {
54598
54599
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
54600
  bool has_value;
54601
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
54602
  if (!has_value) {
54603
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
54604
    return NO_SUCH_FIELD;
54605
  }
54606
  return value(iter.child());
54607
}
54608
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
54609
  bool has_value;
54610
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
54611
  if (!has_value) {
54612
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
54613
    return NO_SUCH_FIELD;
54614
  }
54615
  return value(iter.child());
54616
}
54617
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
54618
  return find_field_unordered(key);
54619
}
54620
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
54621
  return std::forward<object>(*this).find_field_unordered(key);
54622
}
54623
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
54624
  bool has_value;
54625
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
54626
  if (!has_value) {
54627
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
54628
    return NO_SUCH_FIELD;
54629
  }
54630
  return value(iter.child());
54631
}
54632
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
54633
  bool has_value;
54634
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
54635
  if (!has_value) {
54636
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
54637
    return NO_SUCH_FIELD;
54638
  }
54639
  return value(iter.child());
54640
}
54641
54642
simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
54643
  SIMDJSON_TRY( iter.start_object().error() );
54644
  return object(iter);
54645
}
54646
simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
54647
  SIMDJSON_TRY( iter.start_root_object().error() );
54648
  return object(iter);
54649
}
54650
simdjson_inline error_code object::consume() noexcept {
54651
  if(iter.is_at_key()) {
54652
    /**
54653
     * whenever you are pointing at a key, calling skip_child() is
54654
     * unsafe because you will hit a string and you will assume that
54655
     * it is string value, and this mistake will lead you to make bad
54656
     * depth computation.
54657
     */
54658
    /**
54659
     * We want to 'consume' the key. We could really
54660
     * just do _json_iter->return_current_and_advance(); at this
54661
     * point, but, for clarity, we will use the high-level API to
54662
     * eat the key. We assume that the compiler optimizes away
54663
     * most of the work.
54664
     */
54665
    simdjson_unused raw_json_string actual_key;
54666
    auto error = iter.field_key().get(actual_key);
54667
    if (error) { iter.abandon(); return error; };
54668
    // Let us move to the value while we are at it.
54669
    if ((error = iter.field_value())) { iter.abandon(); return error; }
54670
  }
54671
  auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
54672
  if(error_skip) { iter.abandon(); }
54673
  return error_skip;
54674
}
54675
54676
simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
54677
  const uint8_t * starting_point{iter.peek_start()};
54678
  auto error = consume();
54679
  if(error) { return error; }
54680
  const uint8_t * final_point{iter._json_iter->peek()};
54681
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
54682
}
54683
54684
simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
54685
  SIMDJSON_TRY( iter.started_object().error() );
54686
  return object(iter);
54687
}
54688
54689
simdjson_inline object object::resume(const value_iterator &iter) noexcept {
54690
  return iter;
54691
}
54692
54693
simdjson_inline object::object(const value_iterator &_iter) noexcept
54694
  : iter{_iter}
54695
{
54696
}
54697
54698
simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
54699
#if SIMDJSON_DEVELOPMENT_CHECKS
54700
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
54701
#endif
54702
  return object_iterator(iter);
54703
}
54704
simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
54705
  return object_iterator(iter);
54706
}
54707
54708
inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
54709
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
54710
  json_pointer = json_pointer.substr(1);
54711
  size_t slash = json_pointer.find('/');
54712
  std::string_view key = json_pointer.substr(0, slash);
54713
  // Grab the child with the given key
54714
  simdjson_result<value> child;
54715
54716
  // If there is an escape character in the key, unescape it and then get the child.
54717
  size_t escape = key.find('~');
54718
  if (escape != std::string_view::npos) {
54719
    // Unescape the key
54720
    std::string unescaped(key);
54721
    do {
54722
      switch (unescaped[escape+1]) {
54723
        case '0':
54724
          unescaped.replace(escape, 2, "~");
54725
          break;
54726
        case '1':
54727
          unescaped.replace(escape, 2, "/");
54728
          break;
54729
        default:
54730
          return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
54731
      }
54732
      escape = unescaped.find('~', escape+1);
54733
    } while (escape != std::string::npos);
54734
    child = find_field(unescaped);  // Take note find_field does not unescape keys when matching
54735
  } else {
54736
    child = find_field(key);
54737
  }
54738
  if(child.error()) {
54739
    return child; // we do not continue if there was an error
54740
  }
54741
  // If there is a /, we have to recurse and look up more of the path
54742
  if (slash != std::string_view::npos) {
54743
    child = child.at_pointer(json_pointer.substr(slash));
54744
  }
54745
  return child;
54746
}
54747
54748
inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
54749
  auto json_pointer = json_path_to_pointer_conversion(json_path);
54750
  if (json_pointer == "-1") {
54751
    return INVALID_JSON_POINTER;
54752
  }
54753
  return at_pointer(json_pointer);
54754
}
54755
54756
simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
54757
  size_t count{0};
54758
  // Important: we do not consume any of the values.
54759
  for(simdjson_unused auto v : *this) { count++; }
54760
  // The above loop will always succeed, but we want to report errors.
54761
  if(iter.error()) { return iter.error(); }
54762
  // We need to move back at the start because we expect users to iterate through
54763
  // the object after counting the number of elements.
54764
  iter.reset_object();
54765
  return count;
54766
}
54767
54768
simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
54769
  bool is_not_empty;
54770
  auto error = iter.reset_object().get(is_not_empty);
54771
  if(error) { return error; }
54772
  return !is_not_empty;
54773
}
54774
54775
simdjson_inline simdjson_result<bool> object::reset() & noexcept {
54776
  return iter.reset_object();
54777
}
54778
54779
} // namespace ondemand
54780
} // namespace haswell
54781
} // namespace simdjson
54782
54783
namespace simdjson {
54784
54785
simdjson_inline simdjson_result<haswell::ondemand::object>::simdjson_result(haswell::ondemand::object &&value) noexcept
54786
    : implementation_simdjson_result_base<haswell::ondemand::object>(std::forward<haswell::ondemand::object>(value)) {}
54787
simdjson_inline simdjson_result<haswell::ondemand::object>::simdjson_result(error_code error) noexcept
54788
    : implementation_simdjson_result_base<haswell::ondemand::object>(error) {}
54789
54790
simdjson_inline simdjson_result<haswell::ondemand::object_iterator> simdjson_result<haswell::ondemand::object>::begin() noexcept {
54791
  if (error()) { return error(); }
54792
  return first.begin();
54793
}
54794
simdjson_inline simdjson_result<haswell::ondemand::object_iterator> simdjson_result<haswell::ondemand::object>::end() noexcept {
54795
  if (error()) { return error(); }
54796
  return first.end();
54797
}
54798
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
54799
  if (error()) { return error(); }
54800
  return first.find_field_unordered(key);
54801
}
54802
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
54803
  if (error()) { return error(); }
54804
  return std::forward<haswell::ondemand::object>(first).find_field_unordered(key);
54805
}
54806
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::operator[](std::string_view key) & noexcept {
54807
  if (error()) { return error(); }
54808
  return first[key];
54809
}
54810
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::operator[](std::string_view key) && noexcept {
54811
  if (error()) { return error(); }
54812
  return std::forward<haswell::ondemand::object>(first)[key];
54813
}
54814
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::find_field(std::string_view key) & noexcept {
54815
  if (error()) { return error(); }
54816
  return first.find_field(key);
54817
}
54818
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::find_field(std::string_view key) && noexcept {
54819
  if (error()) { return error(); }
54820
  return std::forward<haswell::ondemand::object>(first).find_field(key);
54821
}
54822
54823
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
54824
  if (error()) { return error(); }
54825
  return first.at_pointer(json_pointer);
54826
}
54827
54828
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::object>::at_path(
54829
    std::string_view json_path) noexcept {
54830
  if (error()) {
54831
    return error();
54832
  }
54833
  return first.at_path(json_path);
54834
}
54835
54836
inline simdjson_result<bool> simdjson_result<haswell::ondemand::object>::reset() noexcept {
54837
  if (error()) { return error(); }
54838
  return first.reset();
54839
}
54840
54841
inline simdjson_result<bool> simdjson_result<haswell::ondemand::object>::is_empty() noexcept {
54842
  if (error()) { return error(); }
54843
  return first.is_empty();
54844
}
54845
54846
simdjson_inline  simdjson_result<size_t> simdjson_result<haswell::ondemand::object>::count_fields() & noexcept {
54847
  if (error()) { return error(); }
54848
  return first.count_fields();
54849
}
54850
54851
simdjson_inline  simdjson_result<std::string_view> simdjson_result<haswell::ondemand::object>::raw_json() noexcept {
54852
  if (error()) { return error(); }
54853
  return first.raw_json();
54854
}
54855
} // namespace simdjson
54856
54857
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
54858
/* end file simdjson/generic/ondemand/object-inl.h for haswell */
54859
/* including simdjson/generic/ondemand/object_iterator-inl.h for haswell: #include "simdjson/generic/ondemand/object_iterator-inl.h" */
54860
/* begin file simdjson/generic/ondemand/object_iterator-inl.h for haswell */
54861
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
54862
54863
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
54864
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */
54865
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
54866
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
54867
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */
54868
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
54869
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
54870
54871
namespace simdjson {
54872
namespace haswell {
54873
namespace ondemand {
54874
54875
//
54876
// object_iterator
54877
//
54878
54879
simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
54880
  : iter{_iter}
54881
{}
54882
54883
simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
54884
  error_code error = iter.error();
54885
  if (error) { iter.abandon(); return error; }
54886
  auto result = field::start(iter);
54887
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
54888
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
54889
  if (result.error()) { iter.abandon(); }
54890
  return result;
54891
}
54892
simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
54893
  return !(*this != other);
54894
}
54895
simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
54896
  return iter.is_open();
54897
}
54898
54899
SIMDJSON_PUSH_DISABLE_WARNINGS
54900
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
54901
simdjson_inline object_iterator &object_iterator::operator++() noexcept {
54902
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
54903
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
54904
  if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
54905
54906
  simdjson_unused error_code error;
54907
  if ((error = iter.skip_child() )) { return *this; }
54908
54909
  simdjson_unused bool has_value;
54910
  if ((error = iter.has_next_field().get(has_value) )) { return *this; };
54911
  return *this;
54912
}
54913
SIMDJSON_POP_DISABLE_WARNINGS
54914
54915
//
54916
// ### Live States
54917
//
54918
// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
54919
// always SUCCESS:
54920
//
54921
// - Start: This is the state when the object is first found and the iterator is just past the {.
54922
//   In this state, at_start == true.
54923
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
54924
//   iterate over, the iterator is at the , or } before the next value. In this state,
54925
//   depth == iter.depth, at_start == false, and error == SUCCESS.
54926
// - Unfinished Business: When we hand an array/object to the user which they do not fully
54927
//   iterate over, we need to finish that iteration by skipping child values until we reach the
54928
//   Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
54929
//
54930
// ## Error States
54931
//
54932
// In error states, we will yield exactly one more value before stopping. iter.depth == depth
54933
// and at_start is always false. We decrement after yielding the error, moving to the Finished
54934
// state.
54935
//
54936
// - Chained Error: When the object iterator is part of an error chain--for example, in
54937
//   `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
54938
//   object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
54939
//   iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
54940
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
54941
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
54942
//   error == TAPE_ERROR, iter.depth == depth, and at_start == false.
54943
//
54944
// Errors that occur while reading a field to give to the user (such as when the key is not a
54945
// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
54946
// moving to the Finished state without transitioning through an Error state at all.
54947
//
54948
// ## Terminal State
54949
//
54950
// The terminal state has iter.depth < depth. at_start is always false.
54951
//
54952
// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
54953
//   In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
54954
//
54955
54956
} // namespace ondemand
54957
} // namespace haswell
54958
} // namespace simdjson
54959
54960
namespace simdjson {
54961
54962
simdjson_inline simdjson_result<haswell::ondemand::object_iterator>::simdjson_result(
54963
  haswell::ondemand::object_iterator &&value
54964
) noexcept
54965
  : implementation_simdjson_result_base<haswell::ondemand::object_iterator>(std::forward<haswell::ondemand::object_iterator>(value))
54966
{
54967
  first.iter.assert_is_valid();
54968
}
54969
simdjson_inline simdjson_result<haswell::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
54970
  : implementation_simdjson_result_base<haswell::ondemand::object_iterator>({}, error)
54971
{
54972
}
54973
54974
simdjson_inline simdjson_result<haswell::ondemand::field> simdjson_result<haswell::ondemand::object_iterator>::operator*() noexcept {
54975
  if (error()) { return error(); }
54976
  return *first;
54977
}
54978
// If we're iterating and there is an error, return the error once.
54979
simdjson_inline bool simdjson_result<haswell::ondemand::object_iterator>::operator==(const simdjson_result<haswell::ondemand::object_iterator> &other) const noexcept {
54980
  if (!first.iter.is_valid()) { return !error(); }
54981
  return first == other.first;
54982
}
54983
// If we're iterating and there is an error, return the error once.
54984
simdjson_inline bool simdjson_result<haswell::ondemand::object_iterator>::operator!=(const simdjson_result<haswell::ondemand::object_iterator> &other) const noexcept {
54985
  if (!first.iter.is_valid()) { return error(); }
54986
  return first != other.first;
54987
}
54988
// Checks for ']' and ','
54989
simdjson_inline simdjson_result<haswell::ondemand::object_iterator> &simdjson_result<haswell::ondemand::object_iterator>::operator++() noexcept {
54990
  // Clear the error if there is one, so we don't yield it twice
54991
  if (error()) { second = SUCCESS; return *this; }
54992
  ++first;
54993
  return *this;
54994
}
54995
54996
} // namespace simdjson
54997
54998
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
54999
/* end file simdjson/generic/ondemand/object_iterator-inl.h for haswell */
55000
/* including simdjson/generic/ondemand/parser-inl.h for haswell: #include "simdjson/generic/ondemand/parser-inl.h" */
55001
/* begin file simdjson/generic/ondemand/parser-inl.h for haswell */
55002
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
55003
55004
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
55005
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */
55006
/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */
55007
/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */
55008
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
55009
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
55010
/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */
55011
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
55012
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
55013
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
55014
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
55015
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
55016
55017
namespace simdjson {
55018
namespace haswell {
55019
namespace ondemand {
55020
55021
simdjson_inline parser::parser(size_t max_capacity) noexcept
55022
  : _max_capacity{max_capacity} {
55023
}
55024
55025
simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept {
55026
  if (new_capacity > max_capacity()) { return CAPACITY; }
55027
  if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; }
55028
55029
  // string_capacity copied from document::allocate
55030
  _capacity = 0;
55031
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64);
55032
  string_buf.reset(new (std::nothrow) uint8_t[string_capacity]);
55033
#if SIMDJSON_DEVELOPMENT_CHECKS
55034
  start_positions.reset(new (std::nothrow) token_position[new_max_depth]);
55035
#endif
55036
  if (implementation) {
55037
    SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
55038
    SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
55039
  } else {
55040
    SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
55041
  }
55042
  _capacity = new_capacity;
55043
  _max_depth = new_max_depth;
55044
  return SUCCESS;
55045
}
55046
55047
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(padded_string_view json) & noexcept {
55048
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
55049
55050
  json.remove_utf8_bom();
55051
55052
  // Allocate if needed
55053
  if (capacity() < json.length() || !string_buf) {
55054
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
55055
  }
55056
55057
  // Run stage 1.
55058
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
55059
  return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this });
55060
}
55061
55062
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const char *json, size_t len, size_t allocated) & noexcept {
55063
  return iterate(padded_string_view(json, len, allocated));
55064
}
55065
55066
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept {
55067
  return iterate(padded_string_view(json, len, allocated));
55068
}
55069
55070
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string_view json, size_t allocated) & noexcept {
55071
  return iterate(padded_string_view(json, allocated));
55072
}
55073
55074
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
55075
  if(json.capacity() - json.size() < SIMDJSON_PADDING) {
55076
    json.reserve(json.size() + SIMDJSON_PADDING);
55077
  }
55078
  return iterate(padded_string_view(json));
55079
}
55080
55081
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
55082
  return iterate(padded_string_view(json));
55083
}
55084
55085
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string_view> &result) & noexcept {
55086
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
55087
  SIMDJSON_TRY( result.error() );
55088
  padded_string_view json = result.value_unsafe();
55089
  return iterate(json);
55090
}
55091
55092
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
55093
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
55094
  SIMDJSON_TRY( result.error() );
55095
  const padded_string &json = result.value_unsafe();
55096
  return iterate(json);
55097
}
55098
55099
simdjson_warn_unused simdjson_inline simdjson_result<json_iterator> parser::iterate_raw(padded_string_view json) & noexcept {
55100
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
55101
55102
  json.remove_utf8_bom();
55103
55104
  // Allocate if needed
55105
  if (capacity() < json.length()) {
55106
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
55107
  }
55108
55109
  // Run stage 1.
55110
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
55111
  return json_iterator(reinterpret_cast<const uint8_t *>(json.data()), this);
55112
}
55113
55114
inline simdjson_result<document_stream> parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
55115
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
55116
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
55117
    buf += 3;
55118
    len -= 3;
55119
  }
55120
  if(allow_comma_separated && batch_size < len) { batch_size = len; }
55121
  return document_stream(*this, buf, len, batch_size, allow_comma_separated);
55122
}
55123
inline simdjson_result<document_stream> parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
55124
  return iterate_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size, allow_comma_separated);
55125
}
55126
inline simdjson_result<document_stream> parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept {
55127
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
55128
}
55129
inline simdjson_result<document_stream> parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept {
55130
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
55131
}
55132
55133
simdjson_inline size_t parser::capacity() const noexcept {
55134
  return _capacity;
55135
}
55136
simdjson_inline size_t parser::max_capacity() const noexcept {
55137
  return _max_capacity;
55138
}
55139
simdjson_inline size_t parser::max_depth() const noexcept {
55140
  return _max_depth;
55141
}
55142
55143
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
55144
  if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
55145
    _max_capacity = max_capacity;
55146
  } else {
55147
    _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
55148
  }
55149
}
55150
55151
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept {
55152
  uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement);
55153
  if (!end) { return STRING_ERROR; }
55154
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
55155
  dst = end;
55156
  return result;
55157
}
55158
55159
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept {
55160
  uint8_t *end = implementation->parse_wobbly_string(in.buf, dst);
55161
  if (!end) { return STRING_ERROR; }
55162
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
55163
  dst = end;
55164
  return result;
55165
}
55166
55167
} // namespace ondemand
55168
} // namespace haswell
55169
} // namespace simdjson
55170
55171
namespace simdjson {
55172
55173
simdjson_inline simdjson_result<haswell::ondemand::parser>::simdjson_result(haswell::ondemand::parser &&value) noexcept
55174
    : implementation_simdjson_result_base<haswell::ondemand::parser>(std::forward<haswell::ondemand::parser>(value)) {}
55175
simdjson_inline simdjson_result<haswell::ondemand::parser>::simdjson_result(error_code error) noexcept
55176
    : implementation_simdjson_result_base<haswell::ondemand::parser>(error) {}
55177
55178
} // namespace simdjson
55179
55180
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
55181
/* end file simdjson/generic/ondemand/parser-inl.h for haswell */
55182
/* including simdjson/generic/ondemand/raw_json_string-inl.h for haswell: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
55183
/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for haswell */
55184
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
55185
55186
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
55187
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */
55188
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
55189
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
55190
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
55191
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
55192
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
55193
55194
namespace simdjson {
55195
55196
namespace haswell {
55197
namespace ondemand {
55198
55199
simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
55200
55201
simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
55202
55203
55204
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
55205
  size_t pos{0};
55206
  // if the content has no escape character, just scan through it quickly!
55207
  for(;pos < target.size() && target[pos] != '\\';pos++) {}
55208
  // slow path may begin.
55209
  bool escaping{false};
55210
  for(;pos < target.size();pos++) {
55211
    if((target[pos] == '"') && !escaping) {
55212
      return false;
55213
    } else if(target[pos] == '\\') {
55214
      escaping = !escaping;
55215
    } else {
55216
      escaping = false;
55217
    }
55218
  }
55219
  return true;
55220
}
55221
55222
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
55223
  size_t pos{0};
55224
  // if the content has no escape character, just scan through it quickly!
55225
  for(;target[pos] && target[pos] != '\\';pos++) {}
55226
  // slow path may begin.
55227
  bool escaping{false};
55228
  for(;target[pos];pos++) {
55229
    if((target[pos] == '"') && !escaping) {
55230
      return false;
55231
    } else if(target[pos] == '\\') {
55232
      escaping = !escaping;
55233
    } else {
55234
      escaping = false;
55235
    }
55236
  }
55237
  return true;
55238
}
55239
55240
55241
simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
55242
  // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
55243
  return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
55244
}
55245
55246
simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
55247
  // Assumptions: does not contain unescaped quote characters, and
55248
  // the raw content is quote terminated within a valid JSON string.
55249
  if(target.size() <= SIMDJSON_PADDING) {
55250
    return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
55251
  }
55252
  const char * r{raw()};
55253
  size_t pos{0};
55254
  for(;pos < target.size();pos++) {
55255
    if(r[pos] != target[pos]) { return false; }
55256
  }
55257
  if(r[pos] != '"') { return false; }
55258
  return true;
55259
}
55260
55261
simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
55262
  const char * r{raw()};
55263
  size_t pos{0};
55264
  bool escaping{false};
55265
  for(;pos < target.size();pos++) {
55266
    if(r[pos] != target[pos]) { return false; }
55267
    // if target is a compile-time constant and it is free from
55268
    // quotes, then the next part could get optimized away through
55269
    // inlining.
55270
    if((target[pos] == '"') && !escaping) {
55271
      // We have reached the end of the raw_json_string but
55272
      // the target is not done.
55273
      return false;
55274
    } else if(target[pos] == '\\') {
55275
      escaping = !escaping;
55276
    } else {
55277
      escaping = false;
55278
    }
55279
  }
55280
  if(r[pos] != '"') { return false; }
55281
  return true;
55282
}
55283
55284
55285
simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
55286
  // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
55287
  // the raw content is quote terminated within a valid JSON string.
55288
  const char * r{raw()};
55289
  size_t pos{0};
55290
  for(;target[pos];pos++) {
55291
    if(r[pos] != target[pos]) { return false; }
55292
  }
55293
  if(r[pos] != '"') { return false; }
55294
  return true;
55295
}
55296
55297
simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
55298
  // Assumptions: does not contain unescaped quote characters, and
55299
  // the raw content is quote terminated within a valid JSON string.
55300
  const char * r{raw()};
55301
  size_t pos{0};
55302
  bool escaping{false};
55303
  for(;target[pos];pos++) {
55304
    if(r[pos] != target[pos]) { return false; }
55305
    // if target is a compile-time constant and it is free from
55306
    // quotes, then the next part could get optimized away through
55307
    // inlining.
55308
    if((target[pos] == '"') && !escaping) {
55309
      // We have reached the end of the raw_json_string but
55310
      // the target is not done.
55311
      return false;
55312
    } else if(target[pos] == '\\') {
55313
      escaping = !escaping;
55314
    } else {
55315
      escaping = false;
55316
    }
55317
  }
55318
  if(r[pos] != '"') { return false; }
55319
  return true;
55320
}
55321
55322
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
55323
  return a.unsafe_is_equal(c);
55324
}
55325
55326
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
55327
  return a == c;
55328
}
55329
55330
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
55331
  return !(a == c);
55332
}
55333
55334
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
55335
  return !(a == c);
55336
}
55337
55338
55339
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
55340
  return iter.unescape(*this, allow_replacement);
55341
}
55342
55343
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
55344
  return iter.unescape_wobbly(*this);
55345
}
55346
55347
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
55348
  bool in_escape = false;
55349
  const char *s = str.raw();
55350
  while (true) {
55351
    switch (*s) {
55352
      case '\\': in_escape = !in_escape; break;
55353
      case '"': if (in_escape) { in_escape = false; } else { return out; } break;
55354
      default: if (in_escape) { in_escape = false; }
55355
    }
55356
    out << *s;
55357
    s++;
55358
  }
55359
}
55360
55361
} // namespace ondemand
55362
} // namespace haswell
55363
} // namespace simdjson
55364
55365
namespace simdjson {
55366
55367
simdjson_inline simdjson_result<haswell::ondemand::raw_json_string>::simdjson_result(haswell::ondemand::raw_json_string &&value) noexcept
55368
    : implementation_simdjson_result_base<haswell::ondemand::raw_json_string>(std::forward<haswell::ondemand::raw_json_string>(value)) {}
55369
simdjson_inline simdjson_result<haswell::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
55370
    : implementation_simdjson_result_base<haswell::ondemand::raw_json_string>(error) {}
55371
55372
simdjson_inline simdjson_result<const char *> simdjson_result<haswell::ondemand::raw_json_string>::raw() const noexcept {
55373
  if (error()) { return error(); }
55374
  return first.raw();
55375
}
55376
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<haswell::ondemand::raw_json_string>::unescape(haswell::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
55377
  if (error()) { return error(); }
55378
  return first.unescape(iter, allow_replacement);
55379
}
55380
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<haswell::ondemand::raw_json_string>::unescape_wobbly(haswell::ondemand::json_iterator &iter) const noexcept {
55381
  if (error()) { return error(); }
55382
  return first.unescape_wobbly(iter);
55383
}
55384
} // namespace simdjson
55385
55386
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
55387
/* end file simdjson/generic/ondemand/raw_json_string-inl.h for haswell */
55388
/* including simdjson/generic/ondemand/serialization-inl.h for haswell: #include "simdjson/generic/ondemand/serialization-inl.h" */
55389
/* begin file simdjson/generic/ondemand/serialization-inl.h for haswell */
55390
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
55391
55392
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
55393
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */
55394
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
55395
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
55396
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
55397
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
55398
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
55399
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */
55400
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
55401
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
55402
55403
namespace simdjson {
55404
55405
inline std::string_view trim(const std::string_view str) noexcept {
55406
  // We can almost surely do better by rolling our own find_first_not_of function.
55407
  size_t first = str.find_first_not_of(" \t\n\r");
55408
  // If we have the empty string (just white space), then no trimming is possible, and
55409
  // we return the empty string_view.
55410
  if (std::string_view::npos == first) { return std::string_view(); }
55411
  size_t last = str.find_last_not_of(" \t\n\r");
55412
  return str.substr(first, (last - first + 1));
55413
}
55414
55415
55416
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::document& x) noexcept {
55417
  std::string_view v;
55418
  auto error = x.raw_json().get(v);
55419
  if(error) {return error; }
55420
  return trim(v);
55421
}
55422
55423
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::document_reference& x) noexcept {
55424
  std::string_view v;
55425
  auto error = x.raw_json().get(v);
55426
  if(error) {return error; }
55427
  return trim(v);
55428
}
55429
55430
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::value& x) noexcept {
55431
  /**
55432
   * If we somehow receive a value that has already been consumed,
55433
   * then the following code could be in trouble. E.g., we create
55434
   * an array as needed, but if an array was already created, then
55435
   * it could be bad.
55436
   */
55437
  using namespace haswell::ondemand;
55438
  haswell::ondemand::json_type t;
55439
  auto error = x.type().get(t);
55440
  if(error != SUCCESS) { return error; }
55441
  switch (t)
55442
  {
55443
    case json_type::array:
55444
    {
55445
      haswell::ondemand::array array;
55446
      error = x.get_array().get(array);
55447
      if(error) { return error; }
55448
      return to_json_string(array);
55449
    }
55450
    case json_type::object:
55451
    {
55452
      haswell::ondemand::object object;
55453
      error = x.get_object().get(object);
55454
      if(error) { return error; }
55455
      return to_json_string(object);
55456
    }
55457
    default:
55458
      return trim(x.raw_json_token());
55459
  }
55460
}
55461
55462
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::object& x) noexcept {
55463
  std::string_view v;
55464
  auto error = x.raw_json().get(v);
55465
  if(error) {return error; }
55466
  return trim(v);
55467
}
55468
55469
inline simdjson_result<std::string_view> to_json_string(haswell::ondemand::array& x) noexcept {
55470
  std::string_view v;
55471
  auto error = x.raw_json().get(v);
55472
  if(error) {return error; }
55473
  return trim(v);
55474
}
55475
55476
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::document> x) {
55477
  if (x.error()) { return x.error(); }
55478
  return to_json_string(x.value_unsafe());
55479
}
55480
55481
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::document_reference> x) {
55482
  if (x.error()) { return x.error(); }
55483
  return to_json_string(x.value_unsafe());
55484
}
55485
55486
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::value> x) {
55487
  if (x.error()) { return x.error(); }
55488
  return to_json_string(x.value_unsafe());
55489
}
55490
55491
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::object> x) {
55492
  if (x.error()) { return x.error(); }
55493
  return to_json_string(x.value_unsafe());
55494
}
55495
55496
inline simdjson_result<std::string_view> to_json_string(simdjson_result<haswell::ondemand::array> x) {
55497
  if (x.error()) { return x.error(); }
55498
  return to_json_string(x.value_unsafe());
55499
}
55500
} // namespace simdjson
55501
55502
namespace simdjson { namespace haswell { namespace ondemand {
55503
55504
#if SIMDJSON_EXCEPTIONS
55505
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::value x) {
55506
  std::string_view v;
55507
  auto error = simdjson::to_json_string(x).get(v);
55508
  if(error == simdjson::SUCCESS) {
55509
    return (out << v);
55510
  } else {
55511
    throw simdjson::simdjson_error(error);
55512
  }
55513
}
55514
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::value> x) {
55515
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
55516
  return (out << x.value());
55517
}
55518
#else
55519
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::value x) {
55520
  std::string_view v;
55521
  auto error = simdjson::to_json_string(x).get(v);
55522
  if(error == simdjson::SUCCESS) {
55523
    return (out << v);
55524
  } else {
55525
    return (out << error);
55526
  }
55527
}
55528
#endif
55529
55530
#if SIMDJSON_EXCEPTIONS
55531
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::array value) {
55532
  std::string_view v;
55533
  auto error = simdjson::to_json_string(value).get(v);
55534
  if(error == simdjson::SUCCESS) {
55535
    return (out << v);
55536
  } else {
55537
    throw simdjson::simdjson_error(error);
55538
  }
55539
}
55540
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::array> x) {
55541
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
55542
  return (out << x.value());
55543
}
55544
#else
55545
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::array value) {
55546
  std::string_view v;
55547
  auto error = simdjson::to_json_string(value).get(v);
55548
  if(error == simdjson::SUCCESS) {
55549
    return (out << v);
55550
  } else {
55551
    return (out << error);
55552
  }
55553
}
55554
#endif
55555
55556
#if SIMDJSON_EXCEPTIONS
55557
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::document& value)  {
55558
  std::string_view v;
55559
  auto error = simdjson::to_json_string(value).get(v);
55560
  if(error == simdjson::SUCCESS) {
55561
    return (out << v);
55562
  } else {
55563
    throw simdjson::simdjson_error(error);
55564
  }
55565
}
55566
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::document_reference& value)  {
55567
  std::string_view v;
55568
  auto error = simdjson::to_json_string(value).get(v);
55569
  if(error == simdjson::SUCCESS) {
55570
    return (out << v);
55571
  } else {
55572
    throw simdjson::simdjson_error(error);
55573
  }
55574
}
55575
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::document>&& x) {
55576
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
55577
  return (out << x.value());
55578
}
55579
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::haswell::ondemand::document_reference>&& x) {
55580
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
55581
  return (out << x.value());
55582
}
55583
#else
55584
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::document& value)  {
55585
  std::string_view v;
55586
  auto error = simdjson::to_json_string(value).get(v);
55587
  if(error == simdjson::SUCCESS) {
55588
    return (out << v);
55589
  } else {
55590
    return (out << error);
55591
  }
55592
}
55593
#endif
55594
55595
#if SIMDJSON_EXCEPTIONS
55596
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::object value) {
55597
  std::string_view v;
55598
  auto error = simdjson::to_json_string(value).get(v);
55599
  if(error == simdjson::SUCCESS) {
55600
    return (out << v);
55601
  } else {
55602
    throw simdjson::simdjson_error(error);
55603
  }
55604
}
55605
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::haswell::ondemand::object> x) {
55606
  if (x.error()) { throw  simdjson::simdjson_error(x.error()); }
55607
  return (out << x.value());
55608
}
55609
#else
55610
inline std::ostream& operator<<(std::ostream& out, simdjson::haswell::ondemand::object value) {
55611
  std::string_view v;
55612
  auto error = simdjson::to_json_string(value).get(v);
55613
  if(error == simdjson::SUCCESS) {
55614
    return (out << v);
55615
  } else {
55616
    return (out << error);
55617
  }
55618
}
55619
#endif
55620
}}} // namespace simdjson::haswell::ondemand
55621
55622
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
55623
/* end file simdjson/generic/ondemand/serialization-inl.h for haswell */
55624
/* including simdjson/generic/ondemand/token_iterator-inl.h for haswell: #include "simdjson/generic/ondemand/token_iterator-inl.h" */
55625
/* begin file simdjson/generic/ondemand/token_iterator-inl.h for haswell */
55626
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
55627
55628
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
55629
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */
55630
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
55631
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
55632
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
55633
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
55634
55635
namespace simdjson {
55636
namespace haswell {
55637
namespace ondemand {
55638
55639
simdjson_inline token_iterator::token_iterator(
55640
  const uint8_t *_buf,
55641
  token_position position
55642
) noexcept : buf{_buf}, _position{position}
55643
{
55644
}
55645
55646
simdjson_inline uint32_t token_iterator::current_offset() const noexcept {
55647
  return *(_position);
55648
}
55649
55650
55651
simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept {
55652
  return &buf[*(_position++)];
55653
}
55654
55655
simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept {
55656
  return &buf[*position];
55657
}
55658
simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept {
55659
  return *position;
55660
}
55661
simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept {
55662
  return *(position+1) - *position;
55663
}
55664
55665
simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept {
55666
  return *(position+2) - *(position) > *(position+1) - *(position) ?
55667
      *(position+1) - *(position)
55668
      : *(position+2) - *(position);
55669
}
55670
simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept {
55671
  return &buf[*(_position+delta)];
55672
}
55673
simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept {
55674
  return *(_position+delta);
55675
}
55676
simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept {
55677
  return *(_position+delta+1) - *(_position+delta);
55678
}
55679
55680
simdjson_inline token_position token_iterator::position() const noexcept {
55681
  return _position;
55682
}
55683
simdjson_inline void token_iterator::set_position(token_position target_position) noexcept {
55684
  _position = target_position;
55685
}
55686
55687
simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept {
55688
  return _position == other._position;
55689
}
55690
simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept {
55691
  return _position != other._position;
55692
}
55693
simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept {
55694
  return _position > other._position;
55695
}
55696
simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept {
55697
  return _position >= other._position;
55698
}
55699
simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept {
55700
  return _position < other._position;
55701
}
55702
simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept {
55703
  return _position <= other._position;
55704
}
55705
55706
} // namespace ondemand
55707
} // namespace haswell
55708
} // namespace simdjson
55709
55710
namespace simdjson {
55711
55712
simdjson_inline simdjson_result<haswell::ondemand::token_iterator>::simdjson_result(haswell::ondemand::token_iterator &&value) noexcept
55713
    : implementation_simdjson_result_base<haswell::ondemand::token_iterator>(std::forward<haswell::ondemand::token_iterator>(value)) {}
55714
simdjson_inline simdjson_result<haswell::ondemand::token_iterator>::simdjson_result(error_code error) noexcept
55715
    : implementation_simdjson_result_base<haswell::ondemand::token_iterator>(error) {}
55716
55717
} // namespace simdjson
55718
55719
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
55720
/* end file simdjson/generic/ondemand/token_iterator-inl.h for haswell */
55721
/* including simdjson/generic/ondemand/value-inl.h for haswell: #include "simdjson/generic/ondemand/value-inl.h" */
55722
/* begin file simdjson/generic/ondemand/value-inl.h for haswell */
55723
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
55724
55725
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
55726
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */
55727
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
55728
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
55729
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
55730
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
55731
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
55732
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
55733
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
55734
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
55735
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
55736
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
55737
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
55738
55739
namespace simdjson {
55740
namespace haswell {
55741
namespace ondemand {
55742
55743
simdjson_inline value::value(const value_iterator &_iter) noexcept
55744
  : iter{_iter}
55745
{
55746
}
55747
simdjson_inline value value::start(const value_iterator &iter) noexcept {
55748
  return iter;
55749
}
55750
simdjson_inline value value::resume(const value_iterator &iter) noexcept {
55751
  return iter;
55752
}
55753
55754
simdjson_inline simdjson_result<array> value::get_array() noexcept {
55755
  return array::start(iter);
55756
}
55757
simdjson_inline simdjson_result<object> value::get_object() noexcept {
55758
  return object::start(iter);
55759
}
55760
simdjson_inline simdjson_result<object> value::start_or_resume_object() noexcept {
55761
  if (iter.at_start()) {
55762
    return get_object();
55763
  } else {
55764
    return object::resume(iter);
55765
  }
55766
}
55767
55768
simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
55769
  return iter.get_raw_json_string();
55770
}
55771
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
55772
  return iter.get_string(allow_replacement);
55773
}
55774
template <typename string_type>
55775
simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
55776
  return iter.get_string(receiver, allow_replacement);
55777
}
55778
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
55779
  return iter.get_wobbly_string();
55780
}
55781
simdjson_inline simdjson_result<double> value::get_double() noexcept {
55782
  return iter.get_double();
55783
}
55784
simdjson_inline simdjson_result<double> value::get_double_in_string() noexcept {
55785
  return iter.get_double_in_string();
55786
}
55787
simdjson_inline simdjson_result<uint64_t> value::get_uint64() noexcept {
55788
  return iter.get_uint64();
55789
}
55790
simdjson_inline simdjson_result<uint64_t> value::get_uint64_in_string() noexcept {
55791
  return iter.get_uint64_in_string();
55792
}
55793
simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
55794
  return iter.get_int64();
55795
}
55796
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
55797
  return iter.get_int64_in_string();
55798
}
55799
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
55800
  return iter.get_bool();
55801
}
55802
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
55803
  return iter.is_null();
55804
}
55805
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
55806
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
55807
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
55808
template<> simdjson_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(false); }
55809
template<> simdjson_inline simdjson_result<number> value::get() noexcept { return get_number(); }
55810
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
55811
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
55812
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
55813
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
55814
55815
template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
55816
  return get<T>().get(out);
55817
}
55818
55819
#if SIMDJSON_EXCEPTIONS
55820
template <class T>
55821
simdjson_inline value::operator T() noexcept(false) {
55822
  return get<T>();
55823
}
55824
simdjson_inline value::operator array() noexcept(false) {
55825
  return get_array();
55826
}
55827
simdjson_inline value::operator object() noexcept(false) {
55828
  return get_object();
55829
}
55830
simdjson_inline value::operator uint64_t() noexcept(false) {
55831
  return get_uint64();
55832
}
55833
simdjson_inline value::operator int64_t() noexcept(false) {
55834
  return get_int64();
55835
}
55836
simdjson_inline value::operator double() noexcept(false) {
55837
  return get_double();
55838
}
55839
simdjson_inline value::operator std::string_view() noexcept(false) {
55840
  return get_string(false);
55841
}
55842
simdjson_inline value::operator raw_json_string() noexcept(false) {
55843
  return get_raw_json_string();
55844
}
55845
simdjson_inline value::operator bool() noexcept(false) {
55846
  return get_bool();
55847
}
55848
#endif
55849
55850
simdjson_inline simdjson_result<array_iterator> value::begin() & noexcept {
55851
  return get_array().begin();
55852
}
55853
simdjson_inline simdjson_result<array_iterator> value::end() & noexcept {
55854
  return {};
55855
}
55856
simdjson_inline simdjson_result<size_t> value::count_elements() & noexcept {
55857
  simdjson_result<size_t> answer;
55858
  auto a = get_array();
55859
  answer = a.count_elements();
55860
  // count_elements leaves you pointing inside the array, at the first element.
55861
  // We need to move back so that the user can create a new array (which requires that
55862
  // we point at '[').
55863
  iter.move_at_start();
55864
  return answer;
55865
}
55866
simdjson_inline simdjson_result<size_t> value::count_fields() & noexcept {
55867
  simdjson_result<size_t> answer;
55868
  auto a = get_object();
55869
  answer = a.count_fields();
55870
  iter.move_at_start();
55871
  return answer;
55872
}
55873
simdjson_inline simdjson_result<value> value::at(size_t index) noexcept {
55874
  auto a = get_array();
55875
  return a.at(index);
55876
}
55877
55878
simdjson_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
55879
  return start_or_resume_object().find_field(key);
55880
}
55881
simdjson_inline simdjson_result<value> value::find_field(const char *key) noexcept {
55882
  return start_or_resume_object().find_field(key);
55883
}
55884
55885
simdjson_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
55886
  return start_or_resume_object().find_field_unordered(key);
55887
}
55888
simdjson_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
55889
  return start_or_resume_object().find_field_unordered(key);
55890
}
55891
55892
simdjson_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
55893
  return start_or_resume_object()[key];
55894
}
55895
simdjson_inline simdjson_result<value> value::operator[](const char *key) noexcept {
55896
  return start_or_resume_object()[key];
55897
}
55898
55899
simdjson_inline simdjson_result<json_type> value::type() noexcept {
55900
  return iter.type();
55901
}
55902
55903
simdjson_inline simdjson_result<bool> value::is_scalar() noexcept {
55904
  json_type this_type;
55905
  auto error = type().get(this_type);
55906
  if(error) { return error; }
55907
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
55908
}
55909
55910
simdjson_inline simdjson_result<bool> value::is_string() noexcept {
55911
  json_type this_type;
55912
  auto error = type().get(this_type);
55913
  if(error) { return error; }
55914
  return (this_type == json_type::string);
55915
}
55916
55917
55918
simdjson_inline bool value::is_negative() noexcept {
55919
  return iter.is_negative();
55920
}
55921
55922
simdjson_inline simdjson_result<bool> value::is_integer() noexcept {
55923
  return iter.is_integer();
55924
}
55925
simdjson_warn_unused simdjson_inline simdjson_result<number_type> value::get_number_type() noexcept {
55926
  return iter.get_number_type();
55927
}
55928
simdjson_warn_unused simdjson_inline simdjson_result<number> value::get_number() noexcept {
55929
  return iter.get_number();
55930
}
55931
55932
simdjson_inline std::string_view value::raw_json_token() noexcept {
55933
  return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
55934
}
55935
55936
simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
55937
  json_type t;
55938
  SIMDJSON_TRY(type().get(t));
55939
  switch (t)
55940
  {
55941
    case json_type::array: {
55942
      ondemand::array array;
55943
      SIMDJSON_TRY(get_array().get(array));
55944
      return array.raw_json();
55945
    }
55946
    case json_type::object: {
55947
      ondemand::object object;
55948
      SIMDJSON_TRY(get_object().get(object));
55949
      return object.raw_json();
55950
    }
55951
    default:
55952
      return raw_json_token();
55953
  }
55954
}
55955
55956
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
55957
  return iter.json_iter().current_location();
55958
}
55959
55960
simdjson_inline int32_t value::current_depth() const noexcept{
55961
  return iter.json_iter().depth();
55962
}
55963
55964
simdjson_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
55965
  json_type t;
55966
  SIMDJSON_TRY(type().get(t));
55967
  switch (t)
55968
  {
55969
    case json_type::array:
55970
      return (*this).get_array().at_pointer(json_pointer);
55971
    case json_type::object:
55972
      return (*this).get_object().at_pointer(json_pointer);
55973
    default:
55974
      return INVALID_JSON_POINTER;
55975
  }
55976
}
55977
55978
simdjson_inline simdjson_result<value> value::at_path(std::string_view json_path) noexcept {
55979
  json_type t;
55980
  SIMDJSON_TRY(type().get(t));
55981
  switch (t) {
55982
  case json_type::array:
55983
      return (*this).get_array().at_path(json_path);
55984
  case json_type::object:
55985
      return (*this).get_object().at_path(json_path);
55986
  default:
55987
      return INVALID_JSON_POINTER;
55988
  }
55989
}
55990
55991
} // namespace ondemand
55992
} // namespace haswell
55993
} // namespace simdjson
55994
55995
namespace simdjson {
55996
55997
simdjson_inline simdjson_result<haswell::ondemand::value>::simdjson_result(
55998
  haswell::ondemand::value &&value
55999
) noexcept :
56000
    implementation_simdjson_result_base<haswell::ondemand::value>(
56001
      std::forward<haswell::ondemand::value>(value)
56002
    )
56003
{
56004
}
56005
simdjson_inline simdjson_result<haswell::ondemand::value>::simdjson_result(
56006
  error_code error
56007
) noexcept :
56008
    implementation_simdjson_result_base<haswell::ondemand::value>(error)
56009
{
56010
}
56011
simdjson_inline simdjson_result<size_t> simdjson_result<haswell::ondemand::value>::count_elements() & noexcept {
56012
  if (error()) { return error(); }
56013
  return first.count_elements();
56014
}
56015
simdjson_inline simdjson_result<size_t> simdjson_result<haswell::ondemand::value>::count_fields() & noexcept {
56016
  if (error()) { return error(); }
56017
  return first.count_fields();
56018
}
56019
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::at(size_t index) noexcept {
56020
  if (error()) { return error(); }
56021
  return first.at(index);
56022
}
56023
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::value>::begin() & noexcept {
56024
  if (error()) { return error(); }
56025
  return first.begin();
56026
}
56027
simdjson_inline simdjson_result<haswell::ondemand::array_iterator> simdjson_result<haswell::ondemand::value>::end() & noexcept {
56028
  if (error()) { return error(); }
56029
  return {};
56030
}
56031
56032
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::find_field(std::string_view key) noexcept {
56033
  if (error()) { return error(); }
56034
  return first.find_field(key);
56035
}
56036
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::find_field(const char *key) noexcept {
56037
  if (error()) { return error(); }
56038
  return first.find_field(key);
56039
}
56040
56041
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
56042
  if (error()) { return error(); }
56043
  return first.find_field_unordered(key);
56044
}
56045
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::find_field_unordered(const char *key) noexcept {
56046
  if (error()) { return error(); }
56047
  return first.find_field_unordered(key);
56048
}
56049
56050
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::operator[](std::string_view key) noexcept {
56051
  if (error()) { return error(); }
56052
  return first[key];
56053
}
56054
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::operator[](const char *key) noexcept {
56055
  if (error()) { return error(); }
56056
  return first[key];
56057
}
56058
56059
simdjson_inline simdjson_result<haswell::ondemand::array> simdjson_result<haswell::ondemand::value>::get_array() noexcept {
56060
  if (error()) { return error(); }
56061
  return first.get_array();
56062
}
56063
simdjson_inline simdjson_result<haswell::ondemand::object> simdjson_result<haswell::ondemand::value>::get_object() noexcept {
56064
  if (error()) { return error(); }
56065
  return first.get_object();
56066
}
56067
simdjson_inline simdjson_result<uint64_t> simdjson_result<haswell::ondemand::value>::get_uint64() noexcept {
56068
  if (error()) { return error(); }
56069
  return first.get_uint64();
56070
}
56071
simdjson_inline simdjson_result<uint64_t> simdjson_result<haswell::ondemand::value>::get_uint64_in_string() noexcept {
56072
  if (error()) { return error(); }
56073
  return first.get_uint64_in_string();
56074
}
56075
simdjson_inline simdjson_result<int64_t> simdjson_result<haswell::ondemand::value>::get_int64() noexcept {
56076
  if (error()) { return error(); }
56077
  return first.get_int64();
56078
}
56079
simdjson_inline simdjson_result<int64_t> simdjson_result<haswell::ondemand::value>::get_int64_in_string() noexcept {
56080
  if (error()) { return error(); }
56081
  return first.get_int64_in_string();
56082
}
56083
simdjson_inline simdjson_result<double> simdjson_result<haswell::ondemand::value>::get_double() noexcept {
56084
  if (error()) { return error(); }
56085
  return first.get_double();
56086
}
56087
simdjson_inline simdjson_result<double> simdjson_result<haswell::ondemand::value>::get_double_in_string() noexcept {
56088
  if (error()) { return error(); }
56089
  return first.get_double_in_string();
56090
}
56091
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::value>::get_string(bool allow_replacement) noexcept {
56092
  if (error()) { return error(); }
56093
  return first.get_string(allow_replacement);
56094
}
56095
template <typename string_type>
56096
simdjson_inline error_code simdjson_result<haswell::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
56097
  if (error()) { return error(); }
56098
  return first.get_string(receiver, allow_replacement);
56099
}
56100
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::value>::get_wobbly_string() noexcept {
56101
  if (error()) { return error(); }
56102
  return first.get_wobbly_string();
56103
}
56104
simdjson_inline simdjson_result<haswell::ondemand::raw_json_string> simdjson_result<haswell::ondemand::value>::get_raw_json_string() noexcept {
56105
  if (error()) { return error(); }
56106
  return first.get_raw_json_string();
56107
}
56108
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::value>::get_bool() noexcept {
56109
  if (error()) { return error(); }
56110
  return first.get_bool();
56111
}
56112
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::value>::is_null() noexcept {
56113
  if (error()) { return error(); }
56114
  return first.is_null();
56115
}
56116
56117
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<haswell::ondemand::value>::get() noexcept {
56118
  if (error()) { return error(); }
56119
  return first.get<T>();
56120
}
56121
template<typename T> simdjson_inline error_code simdjson_result<haswell::ondemand::value>::get(T &out) noexcept {
56122
  if (error()) { return error(); }
56123
  return first.get<T>(out);
56124
}
56125
56126
template<> simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::get<haswell::ondemand::value>() noexcept  {
56127
  if (error()) { return error(); }
56128
  return std::move(first);
56129
}
56130
template<> simdjson_inline error_code simdjson_result<haswell::ondemand::value>::get<haswell::ondemand::value>(haswell::ondemand::value &out) noexcept {
56131
  if (error()) { return error(); }
56132
  out = first;
56133
  return SUCCESS;
56134
}
56135
56136
simdjson_inline simdjson_result<haswell::ondemand::json_type> simdjson_result<haswell::ondemand::value>::type() noexcept {
56137
  if (error()) { return error(); }
56138
  return first.type();
56139
}
56140
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::value>::is_scalar() noexcept {
56141
  if (error()) { return error(); }
56142
  return first.is_scalar();
56143
}
56144
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::value>::is_string() noexcept {
56145
  if (error()) { return error(); }
56146
  return first.is_string();
56147
}
56148
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::value>::is_negative() noexcept {
56149
  if (error()) { return error(); }
56150
  return first.is_negative();
56151
}
56152
simdjson_inline simdjson_result<bool> simdjson_result<haswell::ondemand::value>::is_integer() noexcept {
56153
  if (error()) { return error(); }
56154
  return first.is_integer();
56155
}
56156
simdjson_inline simdjson_result<haswell::number_type> simdjson_result<haswell::ondemand::value>::get_number_type() noexcept {
56157
  if (error()) { return error(); }
56158
  return first.get_number_type();
56159
}
56160
simdjson_inline simdjson_result<haswell::ondemand::number> simdjson_result<haswell::ondemand::value>::get_number() noexcept {
56161
  if (error()) { return error(); }
56162
  return first.get_number();
56163
}
56164
#if SIMDJSON_EXCEPTIONS
56165
template <class T>
56166
simdjson_inline simdjson_result<haswell::ondemand::value>::operator T() noexcept(false) {
56167
  if (error()) { throw simdjson_error(error()); }
56168
  return static_cast<T>(first);
56169
}
56170
simdjson_inline simdjson_result<haswell::ondemand::value>::operator haswell::ondemand::array() noexcept(false) {
56171
  if (error()) { throw simdjson_error(error()); }
56172
  return first;
56173
}
56174
simdjson_inline simdjson_result<haswell::ondemand::value>::operator haswell::ondemand::object() noexcept(false) {
56175
  if (error()) { throw simdjson_error(error()); }
56176
  return first;
56177
}
56178
simdjson_inline simdjson_result<haswell::ondemand::value>::operator uint64_t() noexcept(false) {
56179
  if (error()) { throw simdjson_error(error()); }
56180
  return first;
56181
}
56182
simdjson_inline simdjson_result<haswell::ondemand::value>::operator int64_t() noexcept(false) {
56183
  if (error()) { throw simdjson_error(error()); }
56184
  return first;
56185
}
56186
simdjson_inline simdjson_result<haswell::ondemand::value>::operator double() noexcept(false) {
56187
  if (error()) { throw simdjson_error(error()); }
56188
  return first;
56189
}
56190
simdjson_inline simdjson_result<haswell::ondemand::value>::operator std::string_view() noexcept(false) {
56191
  if (error()) { throw simdjson_error(error()); }
56192
  return first;
56193
}
56194
simdjson_inline simdjson_result<haswell::ondemand::value>::operator haswell::ondemand::raw_json_string() noexcept(false) {
56195
  if (error()) { throw simdjson_error(error()); }
56196
  return first;
56197
}
56198
simdjson_inline simdjson_result<haswell::ondemand::value>::operator bool() noexcept(false) {
56199
  if (error()) { throw simdjson_error(error()); }
56200
  return first;
56201
}
56202
#endif
56203
56204
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::value>::raw_json_token() noexcept {
56205
  if (error()) { return error(); }
56206
  return first.raw_json_token();
56207
}
56208
56209
simdjson_inline simdjson_result<std::string_view> simdjson_result<haswell::ondemand::value>::raw_json() noexcept {
56210
  if (error()) { return error(); }
56211
  return first.raw_json();
56212
}
56213
56214
simdjson_inline simdjson_result<const char *> simdjson_result<haswell::ondemand::value>::current_location() noexcept {
56215
  if (error()) { return error(); }
56216
  return first.current_location();
56217
}
56218
56219
simdjson_inline simdjson_result<int32_t> simdjson_result<haswell::ondemand::value>::current_depth() const noexcept {
56220
  if (error()) { return error(); }
56221
  return first.current_depth();
56222
}
56223
56224
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::at_pointer(
56225
    std::string_view json_pointer) noexcept {
56226
  if (error()) {
56227
      return error();
56228
  }
56229
  return first.at_pointer(json_pointer);
56230
}
56231
56232
simdjson_inline simdjson_result<haswell::ondemand::value> simdjson_result<haswell::ondemand::value>::at_path(
56233
      std::string_view json_path) noexcept {
56234
  if (error()) {
56235
    return error();
56236
  }
56237
  return first.at_path(json_path);
56238
}
56239
56240
} // namespace simdjson
56241
56242
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
56243
/* end file simdjson/generic/ondemand/value-inl.h for haswell */
56244
/* including simdjson/generic/ondemand/value_iterator-inl.h for haswell: #include "simdjson/generic/ondemand/value_iterator-inl.h" */
56245
/* begin file simdjson/generic/ondemand/value_iterator-inl.h for haswell */
56246
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
56247
56248
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
56249
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */
56250
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
56251
/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */
56252
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
56253
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
56254
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */
56255
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
56256
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
56257
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
56258
56259
namespace simdjson {
56260
namespace haswell {
56261
namespace ondemand {
56262
56263
simdjson_inline value_iterator::value_iterator(
56264
  json_iterator *json_iter,
56265
  depth_t depth,
56266
  token_position start_position
56267
) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
56268
{
56269
}
56270
56271
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
56272
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
56273
  return started_object();
56274
}
56275
56276
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
56277
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
56278
  return started_root_object();
56279
}
56280
56281
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
56282
  assert_at_container_start();
56283
#if SIMDJSON_DEVELOPMENT_CHECKS
56284
  _json_iter->set_start_position(_depth, start_position());
56285
#endif
56286
  if (*_json_iter->peek() == '}') {
56287
    logger::log_value(*_json_iter, "empty object");
56288
    _json_iter->return_current_and_advance();
56289
    end_container();
56290
    return false;
56291
  }
56292
  return true;
56293
}
56294
56295
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
56296
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
56297
  // current document. It only works in the normal mode where we have indexed a single document.
56298
  // Note that adding a check for 'streaming' is not expensive since we only have at most
56299
  // one root element.
56300
  if ( ! _json_iter->streaming() ) {
56301
    // The following lines do not fully protect against garbage content within the
56302
    // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
56303
    // call `at_end()` on the document instance at the end of the processing to
56304
    // ensure that the processing has finished at the end.
56305
    //
56306
    if (*_json_iter->peek_last() != '}') {
56307
      _json_iter->abandon();
56308
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
56309
    }
56310
    // If the last character is } *and* the first gibberish character is also '}'
56311
    // then on-demand could accidentally go over. So we need additional checks.
56312
    // https://github.com/simdjson/simdjson/issues/1834
56313
    // Checking that the document is balanced requires a full scan which is potentially
56314
    // expensive, but it only happens in edge cases where the first padding character is
56315
    // a closing bracket.
56316
    if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
56317
      _json_iter->abandon();
56318
      // The exact error would require more work. It will typically be an unclosed object.
56319
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
56320
    }
56321
  }
56322
  return SUCCESS;
56323
}
56324
56325
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
56326
  auto error = check_root_object();
56327
  if(error) { return error; }
56328
  return started_object();
56329
}
56330
56331
simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
56332
#if SIMDJSON_CHECK_EOF
56333
    if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
56334
    // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
56335
#endif // SIMDJSON_CHECK_EOF
56336
    _json_iter->ascend_to(depth()-1);
56337
    return SUCCESS;
56338
}
56339
56340
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
56341
  assert_at_next();
56342
56343
  // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
56344
  // obligated to verify there are more tokens if they are not the top level.
56345
  switch (*_json_iter->return_current_and_advance()) {
56346
    case '}':
56347
      logger::log_end_value(*_json_iter, "object");
56348
      SIMDJSON_TRY( end_container() );
56349
      return false;
56350
    case ',':
56351
      return true;
56352
    default:
56353
      return report_error(TAPE_ERROR, "Missing comma between object fields");
56354
  }
56355
}
56356
56357
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
56358
  error_code error;
56359
  bool has_value;
56360
  //
56361
  // Initially, the object can be in one of a few different places:
56362
  //
56363
  // 1. The start of the object, at the first field:
56364
  //
56365
  //    ```
56366
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56367
  //      ^ (depth 2, index 1)
56368
  //    ```
56369
  if (at_first_field()) {
56370
    has_value = true;
56371
56372
  //
56373
  // 2. When a previous search did not yield a value or the object is empty:
56374
  //
56375
  //    ```
56376
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56377
  //                                     ^ (depth 0)
56378
  //    { }
56379
  //        ^ (depth 0, index 2)
56380
  //    ```
56381
  //
56382
  } else if (!is_open()) {
56383
#if SIMDJSON_DEVELOPMENT_CHECKS
56384
    // If we're past the end of the object, we're being iterated out of order.
56385
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
56386
    // this object iterator will blithely scan that object for fields.
56387
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
56388
#endif
56389
    return false;
56390
56391
  // 3. When a previous search found a field or an iterator yielded a value:
56392
  //
56393
  //    ```
56394
  //    // When a field was not fully consumed (or not even touched at all)
56395
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56396
  //           ^ (depth 2)
56397
  //    // When a field was fully consumed
56398
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56399
  //                   ^ (depth 1)
56400
  //    // When the last field was fully consumed
56401
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56402
  //                                   ^ (depth 1)
56403
  //    ```
56404
  //
56405
  } else {
56406
    if ((error = skip_child() )) { abandon(); return error; }
56407
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
56408
#if SIMDJSON_DEVELOPMENT_CHECKS
56409
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
56410
#endif
56411
  }
56412
  while (has_value) {
56413
    // Get the key and colon, stopping at the value.
56414
    raw_json_string actual_key;
56415
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
56416
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
56417
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
56418
    // The depth is left unchanged by field_key().
56419
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
56420
    // field_value() will advance and check that we find a ':' separating the
56421
    // key and the value. It will also increment the depth by one.
56422
    if ((error = field_value() )) { abandon(); return error; }
56423
    // If it matches, stop and return
56424
    // We could do it this way if we wanted to allow arbitrary
56425
    // key content (including escaped quotes).
56426
    //if (actual_key.unsafe_is_equal(max_key_length, key)) {
56427
    // Instead we do the following which may trigger buffer overruns if the
56428
    // user provides an adversarial key (containing a well placed unescaped quote
56429
    // character and being longer than the number of bytes remaining in the JSON
56430
    // input).
56431
    if (actual_key.unsafe_is_equal(key)) {
56432
      logger::log_event(*this, "match", key, -2);
56433
      // If we return here, then we return while pointing at the ':' that we just checked.
56434
      return true;
56435
    }
56436
56437
    // No match: skip the value and see if , or } is next
56438
    logger::log_event(*this, "no match", key, -2);
56439
    // The call to skip_child is meant to skip over the value corresponding to the key.
56440
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
56441
    SIMDJSON_TRY( skip_child() ); // Skip the value entirely
56442
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
56443
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
56444
    // then we are in error and we abort.
56445
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
56446
  }
56447
56448
  // If the loop ended, we're out of fields to look at.
56449
  return false;
56450
}
56451
56452
SIMDJSON_PUSH_DISABLE_WARNINGS
56453
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
56454
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
56455
  /**
56456
   * When find_field_unordered_raw is called, we can either be pointing at the
56457
   * first key, pointing outside (at the closing brace) or if a key was matched
56458
   * we can be either pointing right afterthe ':' right before the value (that we need skip),
56459
   * or we may have consumed the value and we might be at a comma or at the
56460
   * final brace (ready for a call to has_next_field()).
56461
   */
56462
  error_code error;
56463
  bool has_value;
56464
56465
  // First, we scan from that point to the end.
56466
  // If we don't find a match, we may loop back around, and scan from the beginning to that point.
56467
  token_position search_start = _json_iter->position();
56468
56469
  // We want to know whether we need to go back to the beginning.
56470
  bool at_first = at_first_field();
56471
  ///////////////
56472
  // Initially, the object can be in one of a few different places:
56473
  //
56474
  // 1. At the first key:
56475
  //
56476
  //    ```
56477
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56478
  //      ^ (depth 2, index 1)
56479
  //    ```
56480
  //
56481
  if (at_first) {
56482
    has_value = true;
56483
56484
  // 2. When a previous search did not yield a value or the object is empty:
56485
  //
56486
  //    ```
56487
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56488
  //                                     ^ (depth 0)
56489
  //    { }
56490
  //        ^ (depth 0, index 2)
56491
  //    ```
56492
  //
56493
  } else if (!is_open()) {
56494
56495
#if SIMDJSON_DEVELOPMENT_CHECKS
56496
    // If we're past the end of the object, we're being iterated out of order.
56497
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
56498
    // this object iterator will blithely scan that object for fields.
56499
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
56500
#endif
56501
    SIMDJSON_TRY(reset_object().get(has_value));
56502
    at_first = true;
56503
  // 3. When a previous search found a field or an iterator yielded a value:
56504
  //
56505
  //    ```
56506
  //    // When a field was not fully consumed (or not even touched at all)
56507
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56508
  //           ^ (depth 2)
56509
  //    // When a field was fully consumed
56510
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56511
  //                   ^ (depth 1)
56512
  //    // When the last field was fully consumed
56513
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56514
  //                                   ^ (depth 1)
56515
  //    ```
56516
  //
56517
  } else {
56518
    // If someone queried a key but they not did access the value, then we are left pointing
56519
    // at the ':' and we need to move forward through the value... If the value was
56520
    // processed then skip_child() does not move the iterator (but may adjust the depth).
56521
    if ((error = skip_child() )) { abandon(); return error; }
56522
    search_start = _json_iter->position();
56523
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
56524
#if SIMDJSON_DEVELOPMENT_CHECKS
56525
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
56526
#endif
56527
  }
56528
56529
  // After initial processing, we will be in one of two states:
56530
  //
56531
  // ```
56532
  // // At the beginning of a field
56533
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56534
  //   ^ (depth 1)
56535
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56536
  //                  ^ (depth 1)
56537
  // // At the end of the object
56538
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
56539
  //                                  ^ (depth 0)
56540
  // ```
56541
  //
56542
  // Next, we find a match starting from the current position.
56543
  while (has_value) {
56544
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
56545
56546
    // Get the key and colon, stopping at the value.
56547
    raw_json_string actual_key;
56548
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
56549
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
56550
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
56551
    // The depth is left unchanged by field_key().
56552
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
56553
    // field_value() will advance and check that we find a ':' separating the
56554
    // key and the value. It will also increment the depth by one.
56555
    if ((error = field_value() )) { abandon(); return error; }
56556
56557
    // If it matches, stop and return
56558
    // We could do it this way if we wanted to allow arbitrary
56559
    // key content (including escaped quotes).
56560
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
56561
    // Instead we do the following which may trigger buffer overruns if the
56562
    // user provides an adversarial key (containing a well placed unescaped quote
56563
    // character and being longer than the number of bytes remaining in the JSON
56564
    // input).
56565
    if (actual_key.unsafe_is_equal(key)) {
56566
      logger::log_event(*this, "match", key, -2);
56567
      // If we return here, then we return while pointing at the ':' that we just checked.
56568
      return true;
56569
    }
56570
56571
    // No match: skip the value and see if , or } is next
56572
    logger::log_event(*this, "no match", key, -2);
56573
    // The call to skip_child is meant to skip over the value corresponding to the key.
56574
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
56575
    SIMDJSON_TRY( skip_child() );
56576
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
56577
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
56578
    // then we are in error and we abort.
56579
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
56580
  }
56581
  // Performance note: it maybe wasteful to rewind to the beginning when there might be
56582
  // no other query following. Indeed, it would require reskipping the whole object.
56583
  // Instead, you can just stay where you are. If there is a new query, there is always time
56584
  // to rewind.
56585
  if(at_first) { return false; }
56586
56587
  // If we reach the end without finding a match, search the rest of the fields starting at the
56588
  // beginning of the object.
56589
  // (We have already run through the object before, so we've already validated its structure. We
56590
  // don't check errors in this bit.)
56591
  SIMDJSON_TRY(reset_object().get(has_value));
56592
  while (true) {
56593
    SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
56594
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
56595
56596
    // Get the key and colon, stopping at the value.
56597
    raw_json_string actual_key;
56598
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
56599
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
56600
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
56601
    // The depth is left unchanged by field_key().
56602
    error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
56603
    // field_value() will advance and check that we find a ':' separating the
56604
    // key and the value.  It will also increment the depth by one.
56605
    error = field_value(); SIMDJSON_ASSUME(!error);
56606
56607
    // If it matches, stop and return
56608
    // We could do it this way if we wanted to allow arbitrary
56609
    // key content (including escaped quotes).
56610
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
56611
    // Instead we do the following which may trigger buffer overruns if the
56612
    // user provides an adversarial key (containing a well placed unescaped quote
56613
    // character and being longer than the number of bytes remaining in the JSON
56614
    // input).
56615
    if (actual_key.unsafe_is_equal(key)) {
56616
      logger::log_event(*this, "match", key, -2);
56617
      // If we return here, then we return while pointing at the ':' that we just checked.
56618
      return true;
56619
    }
56620
56621
    // No match: skip the value and see if , or } is next
56622
    logger::log_event(*this, "no match", key, -2);
56623
    // The call to skip_child is meant to skip over the value corresponding to the key.
56624
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
56625
    SIMDJSON_TRY( skip_child() );
56626
    // If we reached the end of the key-value pair we started from, then we know
56627
    // that the key is not there so we return false. We are either right before
56628
    // the next comma or the final brace.
56629
    if(_json_iter->position() == search_start) { return false; }
56630
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
56631
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
56632
    // then we are in error and we abort.
56633
    error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
56634
    // If we make the mistake of exiting here, then we could be left pointing at a key
56635
    // in the middle of an object. That's not an allowable state.
56636
  }
56637
  // If the loop ended, we're out of fields to look at. The program should
56638
  // never reach this point.
56639
  return false;
56640
}
56641
SIMDJSON_POP_DISABLE_WARNINGS
56642
56643
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
56644
  assert_at_next();
56645
56646
  const uint8_t *key = _json_iter->return_current_and_advance();
56647
  if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
56648
  return raw_json_string(key);
56649
}
56650
56651
simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
56652
  assert_at_next();
56653
56654
  if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
56655
  _json_iter->descend_to(depth()+1);
56656
  return SUCCESS;
56657
}
56658
56659
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
56660
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
56661
  return started_array();
56662
}
56663
56664
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
56665
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
56666
  return started_root_array();
56667
}
56668
56669
inline std::string value_iterator::to_string() const noexcept {
56670
  auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
56671
  if(_json_iter != nullptr) { answer +=  _json_iter->to_string(); }
56672
  answer += std::string(" ]");
56673
  return answer;
56674
}
56675
56676
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
56677
  assert_at_container_start();
56678
  if (*_json_iter->peek() == ']') {
56679
    logger::log_value(*_json_iter, "empty array");
56680
    _json_iter->return_current_and_advance();
56681
    SIMDJSON_TRY( end_container() );
56682
    return false;
56683
  }
56684
  _json_iter->descend_to(depth()+1);
56685
#if SIMDJSON_DEVELOPMENT_CHECKS
56686
  _json_iter->set_start_position(_depth, start_position());
56687
#endif
56688
  return true;
56689
}
56690
56691
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
56692
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
56693
  // current document. It only works in the normal mode where we have indexed a single document.
56694
  // Note that adding a check for 'streaming' is not expensive since we only have at most
56695
  // one root element.
56696
  if ( ! _json_iter->streaming() ) {
56697
    // The following lines do not fully protect against garbage content within the
56698
    // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
56699
    // also call `at_end()` on the document instance at the end of the processing to
56700
    // ensure that the processing has finished at the end.
56701
    //
56702
    if (*_json_iter->peek_last() != ']') {
56703
      _json_iter->abandon();
56704
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
56705
    }
56706
    // If the last character is ] *and* the first gibberish character is also ']'
56707
    // then on-demand could accidentally go over. So we need additional checks.
56708
    // https://github.com/simdjson/simdjson/issues/1834
56709
    // Checking that the document is balanced requires a full scan which is potentially
56710
    // expensive, but it only happens in edge cases where the first padding character is
56711
    // a closing bracket.
56712
    if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
56713
      _json_iter->abandon();
56714
      // The exact error would require more work. It will typically be an unclosed array.
56715
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
56716
    }
56717
  }
56718
  return SUCCESS;
56719
}
56720
56721
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
56722
  auto error = check_root_array();
56723
  if (error) { return error; }
56724
  return started_array();
56725
}
56726
56727
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
56728
  assert_at_next();
56729
56730
  logger::log_event(*this, "has_next_element");
56731
  switch (*_json_iter->return_current_and_advance()) {
56732
    case ']':
56733
      logger::log_end_value(*_json_iter, "array");
56734
      SIMDJSON_TRY( end_container() );
56735
      return false;
56736
    case ',':
56737
      _json_iter->descend_to(depth()+1);
56738
      return true;
56739
    default:
56740
      return report_error(TAPE_ERROR, "Missing comma between array elements");
56741
  }
56742
}
56743
56744
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
56745
  auto not_true = atomparsing::str4ncmp(json, "true");
56746
  auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
56747
  bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
56748
  if (error) { return incorrect_type_error("Not a boolean"); }
56749
  return simdjson_result<bool>(!not_true);
56750
}
56751
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
56752
  bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
56753
  // if we start with 'n', we must be a null
56754
  if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
56755
  return is_null_string;
56756
}
56757
56758
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
56759
  return get_raw_json_string().unescape(json_iter(), allow_replacement);
56760
}
56761
template <typename string_type>
56762
simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
56763
  std::string_view content;
56764
  auto err = get_string(allow_replacement).get(content);
56765
  if (err) { return err; }
56766
  receiver = content;
56767
  return SUCCESS;
56768
}
56769
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
56770
  return get_raw_json_string().unescape_wobbly(json_iter());
56771
}
56772
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
56773
  auto json = peek_scalar("string");
56774
  if (*json != '"') { return incorrect_type_error("Not a string"); }
56775
  advance_scalar("string");
56776
  return raw_json_string(json+1);
56777
}
56778
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
56779
  auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
56780
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
56781
  return result;
56782
}
56783
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
56784
  auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
56785
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
56786
  return result;
56787
}
56788
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
56789
  auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
56790
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
56791
  return result;
56792
}
56793
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
56794
  auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
56795
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
56796
  return result;
56797
}
56798
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
56799
  auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
56800
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
56801
  return result;
56802
}
56803
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
56804
  auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
56805
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
56806
  return result;
56807
}
56808
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
56809
  auto result = parse_bool(peek_non_root_scalar("bool"));
56810
  if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
56811
  return result;
56812
}
56813
simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
56814
  bool is_null_value;
56815
  SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
56816
  if(is_null_value) { advance_non_root_scalar("null"); }
56817
  return is_null_value;
56818
}
56819
simdjson_inline bool value_iterator::is_negative() noexcept {
56820
  return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
56821
}
56822
simdjson_inline bool value_iterator::is_root_negative() noexcept {
56823
  return numberparsing::is_negative(peek_root_scalar("numbersign"));
56824
}
56825
simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
56826
  return numberparsing::is_integer(peek_non_root_scalar("integer"));
56827
}
56828
simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
56829
  return numberparsing::get_number_type(peek_non_root_scalar("integer"));
56830
}
56831
simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
56832
  number num;
56833
  error_code error =  numberparsing::parse_number(peek_non_root_scalar("number"), num);
56834
  if(error) { return error; }
56835
  return num;
56836
}
56837
56838
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
56839
  auto max_len = peek_root_length();
56840
  auto json = peek_root_scalar("is_root_integer");
56841
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
56842
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
56843
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
56844
    return false; // if there are more than 20 characters, it cannot be represented as an integer.
56845
  }
56846
  auto answer = numberparsing::is_integer(tmpbuf);
56847
  // If the parsing was a success, we must still check that it is
56848
  // a single scalar. Note that we parse first because of cases like '[]' where
56849
  // getting TRAILING_CONTENT is wrong.
56850
  if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
56851
  return answer;
56852
}
56853
56854
simdjson_inline simdjson_result<haswell::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
56855
  auto max_len = peek_root_length();
56856
  auto json = peek_root_scalar("number");
56857
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
56858
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
56859
  // number: -0.<fraction>e-308.
56860
  uint8_t tmpbuf[1074+8+1+1];
56861
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
56862
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
56863
    if(numberparsing::check_if_integer(json, max_len)) {
56864
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56865
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
56866
      return number_type::big_integer;
56867
    }
56868
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
56869
    return NUMBER_ERROR;
56870
  }
56871
  auto answer = numberparsing::get_number_type(tmpbuf);
56872
  if (check_trailing && (answer.error() == SUCCESS)  && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56873
  return answer;
56874
}
56875
simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
56876
  auto max_len = peek_root_length();
56877
  auto json = peek_root_scalar("number");
56878
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
56879
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
56880
  // number: -0.<fraction>e-308.
56881
  // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
56882
  uint8_t tmpbuf[1074+8+1+1];
56883
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
56884
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
56885
    if(numberparsing::check_if_integer(json, max_len)) {
56886
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56887
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
56888
      return BIGINT_ERROR;
56889
    }
56890
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
56891
    return NUMBER_ERROR;
56892
  }
56893
  number num;
56894
  error_code error =  numberparsing::parse_number(tmpbuf, num);
56895
  if(error) { return error; }
56896
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56897
  advance_root_scalar("number");
56898
  return num;
56899
}
56900
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
56901
  return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
56902
}
56903
template <typename string_type>
56904
simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
56905
  std::string_view content;
56906
  auto err = get_root_string(check_trailing, allow_replacement).get(content);
56907
  if (err) { return err; }
56908
  receiver = content;
56909
  return SUCCESS;
56910
}
56911
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
56912
  return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
56913
}
56914
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
56915
  auto json = peek_scalar("string");
56916
  if (*json != '"') { return incorrect_type_error("Not a string"); }
56917
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56918
  advance_scalar("string");
56919
  return raw_json_string(json+1);
56920
}
56921
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
56922
  auto max_len = peek_root_length();
56923
  auto json = peek_root_scalar("uint64");
56924
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
56925
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
56926
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
56927
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
56928
    return NUMBER_ERROR;
56929
  }
56930
  auto result = numberparsing::parse_unsigned(tmpbuf);
56931
  if(result.error() == SUCCESS) {
56932
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56933
    advance_root_scalar("uint64");
56934
  }
56935
  return result;
56936
}
56937
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
56938
  auto max_len = peek_root_length();
56939
  auto json = peek_root_scalar("uint64");
56940
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
56941
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
56942
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
56943
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
56944
    return NUMBER_ERROR;
56945
  }
56946
  auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
56947
  if(result.error() == SUCCESS) {
56948
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56949
    advance_root_scalar("uint64");
56950
  }
56951
  return result;
56952
}
56953
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
56954
  auto max_len = peek_root_length();
56955
  auto json = peek_root_scalar("int64");
56956
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
56957
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
56958
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
56959
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
56960
    return NUMBER_ERROR;
56961
  }
56962
56963
  auto result = numberparsing::parse_integer(tmpbuf);
56964
  if(result.error() == SUCCESS) {
56965
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56966
    advance_root_scalar("int64");
56967
  }
56968
  return result;
56969
}
56970
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
56971
  auto max_len = peek_root_length();
56972
  auto json = peek_root_scalar("int64");
56973
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
56974
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
56975
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
56976
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
56977
    return NUMBER_ERROR;
56978
  }
56979
56980
  auto result = numberparsing::parse_integer_in_string(tmpbuf);
56981
  if(result.error() == SUCCESS) {
56982
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
56983
    advance_root_scalar("int64");
56984
  }
56985
  return result;
56986
}
56987
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
56988
  auto max_len = peek_root_length();
56989
  auto json = peek_root_scalar("double");
56990
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
56991
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
56992
  // number: -0.<fraction>e-308.
56993
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
56994
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
56995
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
56996
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
56997
    return NUMBER_ERROR;
56998
  }
56999
  auto result = numberparsing::parse_double(tmpbuf);
57000
  if(result.error() == SUCCESS) {
57001
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
57002
    advance_root_scalar("double");
57003
  }
57004
  return result;
57005
}
57006
57007
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
57008
  auto max_len = peek_root_length();
57009
  auto json = peek_root_scalar("double");
57010
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
57011
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
57012
  // number: -0.<fraction>e-308.
57013
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
57014
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
57015
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
57016
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
57017
    return NUMBER_ERROR;
57018
  }
57019
  auto result = numberparsing::parse_double_in_string(tmpbuf);
57020
  if(result.error() == SUCCESS) {
57021
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
57022
    advance_root_scalar("double");
57023
  }
57024
  return result;
57025
}
57026
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
57027
  auto max_len = peek_root_length();
57028
  auto json = peek_root_scalar("bool");
57029
  uint8_t tmpbuf[5+1+1]; // +1 for null termination
57030
  tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
57031
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
57032
  auto result = parse_bool(tmpbuf);
57033
  if(result.error() == SUCCESS) {
57034
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
57035
    advance_root_scalar("bool");
57036
  }
57037
  return result;
57038
}
57039
simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
57040
  auto max_len = peek_root_length();
57041
  auto json = peek_root_scalar("null");
57042
  bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
57043
         (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
57044
  if(result) { // we have something that looks like a null.
57045
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
57046
    advance_root_scalar("null");
57047
  }
57048
  return result;
57049
}
57050
57051
simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
57052
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
57053
  SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
57054
57055
  return _json_iter->skip_child(depth());
57056
}
57057
57058
simdjson_inline value_iterator value_iterator::child() const noexcept {
57059
  assert_at_child();
57060
  return { _json_iter, depth()+1, _json_iter->token.position() };
57061
}
57062
57063
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
57064
// relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
57065
// marked non-inline.
57066
SIMDJSON_PUSH_DISABLE_WARNINGS
57067
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
57068
simdjson_inline bool value_iterator::is_open() const noexcept {
57069
  return _json_iter->depth() >= depth();
57070
}
57071
SIMDJSON_POP_DISABLE_WARNINGS
57072
57073
simdjson_inline bool value_iterator::at_end() const noexcept {
57074
  return _json_iter->at_end();
57075
}
57076
57077
simdjson_inline bool value_iterator::at_start() const noexcept {
57078
  return _json_iter->token.position() == start_position();
57079
}
57080
57081
simdjson_inline bool value_iterator::at_first_field() const noexcept {
57082
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
57083
  return _json_iter->token.position() == start_position() + 1;
57084
}
57085
57086
simdjson_inline void value_iterator::abandon() noexcept {
57087
  _json_iter->abandon();
57088
}
57089
57090
simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
57091
  return _depth;
57092
}
57093
simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
57094
  return _json_iter->error;
57095
}
57096
simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
57097
  return _json_iter->string_buf_loc();
57098
}
57099
simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
57100
  return *_json_iter;
57101
}
57102
simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
57103
  return *_json_iter;
57104
}
57105
57106
simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
57107
  return _json_iter->peek(start_position());
57108
}
57109
simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
57110
  return _json_iter->peek_length(start_position());
57111
}
57112
simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
57113
  return _json_iter->peek_root_length(start_position());
57114
}
57115
57116
simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
57117
  logger::log_value(*_json_iter, start_position(), depth(), type);
57118
  // If we're not at the position anymore, we don't want to advance the cursor.
57119
  if (!is_at_start()) { return peek_start(); }
57120
57121
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
57122
  assert_at_start();
57123
  return _json_iter->peek();
57124
}
57125
57126
simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
57127
  logger::log_value(*_json_iter, start_position(), depth(), type);
57128
  // If we're not at the position anymore, we don't want to advance the cursor.
57129
  if (!is_at_start()) { return; }
57130
57131
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
57132
  assert_at_start();
57133
  _json_iter->return_current_and_advance();
57134
  _json_iter->ascend_to(depth()-1);
57135
}
57136
57137
simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
57138
  logger::log_start_value(*_json_iter, start_position(), depth(), type);
57139
  // If we're not at the position anymore, we don't want to advance the cursor.
57140
  const uint8_t *json;
57141
  if (!is_at_start()) {
57142
#if SIMDJSON_DEVELOPMENT_CHECKS
57143
    if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
57144
#endif
57145
    json = peek_start();
57146
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
57147
  } else {
57148
    assert_at_start();
57149
    /**
57150
     * We should be prudent. Let us peek. If it is not the right type, we
57151
     * return an error. Only once we have determined that we have the right
57152
     * type are we allowed to advance!
57153
     */
57154
    json = _json_iter->peek();
57155
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
57156
    _json_iter->return_current_and_advance();
57157
  }
57158
57159
57160
  return SUCCESS;
57161
}
57162
57163
57164
simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
57165
  logger::log_value(*_json_iter, start_position(), depth(), type);
57166
  if (!is_at_start()) { return peek_start(); }
57167
57168
  assert_at_root();
57169
  return _json_iter->peek();
57170
}
57171
simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
57172
  logger::log_value(*_json_iter, start_position(), depth(), type);
57173
  if (!is_at_start()) { return peek_start(); }
57174
57175
  assert_at_non_root_start();
57176
  return _json_iter->peek();
57177
}
57178
57179
simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
57180
  logger::log_value(*_json_iter, start_position(), depth(), type);
57181
  if (!is_at_start()) { return; }
57182
57183
  assert_at_root();
57184
  _json_iter->return_current_and_advance();
57185
  _json_iter->ascend_to(depth()-1);
57186
}
57187
simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
57188
  logger::log_value(*_json_iter, start_position(), depth(), type);
57189
  if (!is_at_start()) { return; }
57190
57191
  assert_at_non_root_start();
57192
  _json_iter->return_current_and_advance();
57193
  _json_iter->ascend_to(depth()-1);
57194
}
57195
57196
simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
57197
  logger::log_error(*_json_iter, start_position(), depth(), message);
57198
  return INCORRECT_TYPE;
57199
}
57200
57201
simdjson_inline bool value_iterator::is_at_start() const noexcept {
57202
  return position() == start_position();
57203
}
57204
57205
simdjson_inline bool value_iterator::is_at_key() const noexcept {
57206
  // Keys are at the same depth as the object.
57207
  // Note here that we could be safer and check that we are within an object,
57208
  // but we do not.
57209
  return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
57210
}
57211
57212
simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
57213
  // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
57214
  auto delta = position() - start_position();
57215
  return delta == 1 || delta == 2;
57216
}
57217
57218
inline void value_iterator::assert_at_start() const noexcept {
57219
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
57220
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
57221
  SIMDJSON_ASSUME( _depth > 0 );
57222
}
57223
57224
inline void value_iterator::assert_at_container_start() const noexcept {
57225
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
57226
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
57227
  SIMDJSON_ASSUME( _depth > 0 );
57228
}
57229
57230
inline void value_iterator::assert_at_next() const noexcept {
57231
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
57232
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
57233
  SIMDJSON_ASSUME( _depth > 0 );
57234
}
57235
57236
simdjson_inline void value_iterator::move_at_start() noexcept {
57237
  _json_iter->_depth = _depth;
57238
  _json_iter->token.set_position(_start_position);
57239
}
57240
57241
simdjson_inline void value_iterator::move_at_container_start() noexcept {
57242
  _json_iter->_depth = _depth;
57243
  _json_iter->token.set_position(_start_position + 1);
57244
}
57245
57246
simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
57247
  if(error()) { return error(); }
57248
  move_at_container_start();
57249
  return started_array();
57250
}
57251
57252
simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
57253
  if(error()) { return error(); }
57254
  move_at_container_start();
57255
  return started_object();
57256
}
57257
57258
inline void value_iterator::assert_at_child() const noexcept {
57259
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
57260
  SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
57261
  SIMDJSON_ASSUME( _depth > 0 );
57262
}
57263
57264
inline void value_iterator::assert_at_root() const noexcept {
57265
  assert_at_start();
57266
  SIMDJSON_ASSUME( _depth == 1 );
57267
}
57268
57269
inline void value_iterator::assert_at_non_root_start() const noexcept {
57270
  assert_at_start();
57271
  SIMDJSON_ASSUME( _depth > 1 );
57272
}
57273
57274
inline void value_iterator::assert_is_valid() const noexcept {
57275
  SIMDJSON_ASSUME( _json_iter != nullptr );
57276
}
57277
57278
simdjson_inline bool value_iterator::is_valid() const noexcept {
57279
  return _json_iter != nullptr;
57280
}
57281
57282
simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
57283
  switch (*peek_start()) {
57284
    case '{':
57285
      return json_type::object;
57286
    case '[':
57287
      return json_type::array;
57288
    case '"':
57289
      return json_type::string;
57290
    case 'n':
57291
      return json_type::null;
57292
    case 't': case 'f':
57293
      return json_type::boolean;
57294
    case '-':
57295
    case '0': case '1': case '2': case '3': case '4':
57296
    case '5': case '6': case '7': case '8': case '9':
57297
      return json_type::number;
57298
    default:
57299
      return TAPE_ERROR;
57300
  }
57301
}
57302
57303
simdjson_inline token_position value_iterator::start_position() const noexcept {
57304
  return _start_position;
57305
}
57306
57307
simdjson_inline token_position value_iterator::position() const noexcept {
57308
  return _json_iter->position();
57309
}
57310
57311
simdjson_inline token_position value_iterator::end_position() const noexcept {
57312
  return _json_iter->end_position();
57313
}
57314
57315
simdjson_inline token_position value_iterator::last_position() const noexcept {
57316
  return _json_iter->last_position();
57317
}
57318
57319
simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
57320
  return _json_iter->report_error(error, message);
57321
}
57322
57323
} // namespace ondemand
57324
} // namespace haswell
57325
} // namespace simdjson
57326
57327
namespace simdjson {
57328
57329
simdjson_inline simdjson_result<haswell::ondemand::value_iterator>::simdjson_result(haswell::ondemand::value_iterator &&value) noexcept
57330
    : implementation_simdjson_result_base<haswell::ondemand::value_iterator>(std::forward<haswell::ondemand::value_iterator>(value)) {}
57331
simdjson_inline simdjson_result<haswell::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
57332
    : implementation_simdjson_result_base<haswell::ondemand::value_iterator>(error) {}
57333
57334
} // namespace simdjson
57335
57336
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
57337
/* end file simdjson/generic/ondemand/value_iterator-inl.h for haswell */
57338
/* end file simdjson/generic/ondemand/amalgamated.h for haswell */
57339
/* including simdjson/haswell/end.h: #include "simdjson/haswell/end.h" */
57340
/* begin file simdjson/haswell/end.h */
57341
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57342
/* amalgamation skipped (editor-only): #include "simdjson/haswell/base.h" */
57343
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57344
57345
#if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL
57346
SIMDJSON_UNTARGET_REGION
57347
#endif
57348
57349
/* undefining SIMDJSON_IMPLEMENTATION from "haswell" */
57350
#undef SIMDJSON_IMPLEMENTATION
57351
/* end file simdjson/haswell/end.h */
57352
57353
#endif // SIMDJSON_HASWELL_ONDEMAND_H
57354
/* end file simdjson/haswell/ondemand.h */
57355
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
57356
/* including simdjson/icelake/ondemand.h: #include "simdjson/icelake/ondemand.h" */
57357
/* begin file simdjson/icelake/ondemand.h */
57358
#ifndef SIMDJSON_ICELAKE_ONDEMAND_H
57359
#define SIMDJSON_ICELAKE_ONDEMAND_H
57360
57361
/* including simdjson/icelake/begin.h: #include "simdjson/icelake/begin.h" */
57362
/* begin file simdjson/icelake/begin.h */
57363
/* defining SIMDJSON_IMPLEMENTATION to "icelake" */
57364
#define SIMDJSON_IMPLEMENTATION icelake
57365
/* including simdjson/icelake/base.h: #include "simdjson/icelake/base.h" */
57366
/* begin file simdjson/icelake/base.h */
57367
#ifndef SIMDJSON_ICELAKE_BASE_H
57368
#define SIMDJSON_ICELAKE_BASE_H
57369
57370
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57371
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
57372
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57373
57374
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_ICELAKE
57375
namespace simdjson {
57376
/**
57377
 * Implementation for Icelake (Intel AVX512).
57378
 */
57379
namespace icelake {
57380
57381
class implementation;
57382
57383
} // namespace icelake
57384
} // namespace simdjson
57385
57386
#endif // SIMDJSON_ICELAKE_BASE_H
57387
/* end file simdjson/icelake/base.h */
57388
/* including simdjson/icelake/intrinsics.h: #include "simdjson/icelake/intrinsics.h" */
57389
/* begin file simdjson/icelake/intrinsics.h */
57390
#ifndef SIMDJSON_ICELAKE_INTRINSICS_H
57391
#define SIMDJSON_ICELAKE_INTRINSICS_H
57392
57393
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57394
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
57395
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57396
57397
#if SIMDJSON_VISUAL_STUDIO
57398
// under clang within visual studio, this will include <x86intrin.h>
57399
#include <intrin.h>  // visual studio or clang
57400
#else
57401
#include <x86intrin.h> // elsewhere
57402
#endif // SIMDJSON_VISUAL_STUDIO
57403
57404
#if SIMDJSON_CLANG_VISUAL_STUDIO
57405
/**
57406
 * You are not supposed, normally, to include these
57407
 * headers directly. Instead you should either include intrin.h
57408
 * or x86intrin.h. However, when compiling with clang
57409
 * under Windows (i.e., when _MSC_VER is set), these headers
57410
 * only get included *if* the corresponding features are detected
57411
 * from macros:
57412
 * e.g., if __AVX2__ is set... in turn,  we normally set these
57413
 * macros by compiling against the corresponding architecture
57414
 * (e.g., arch:AVX2, -mavx2, etc.) which compiles the whole
57415
 * software with these advanced instructions. In simdjson, we
57416
 * want to compile the whole program for a generic target,
57417
 * and only target our specific kernels. As a workaround,
57418
 * we directly include the needed headers. These headers would
57419
 * normally guard against such usage, but we carefully included
57420
 * <x86intrin.h>  (or <intrin.h>) before, so the headers
57421
 * are fooled.
57422
 */
57423
#include <bmiintrin.h>   // for _blsr_u64
57424
#include <lzcntintrin.h> // for  __lzcnt64
57425
#include <immintrin.h>   // for most things (AVX2, AVX512, _popcnt64)
57426
#include <smmintrin.h>
57427
#include <tmmintrin.h>
57428
#include <avxintrin.h>
57429
#include <avx2intrin.h>
57430
#include <wmmintrin.h>   // for  _mm_clmulepi64_si128
57431
// Important: we need the AVX-512 headers:
57432
#include <avx512fintrin.h>
57433
#include <avx512dqintrin.h>
57434
#include <avx512cdintrin.h>
57435
#include <avx512bwintrin.h>
57436
#include <avx512vlintrin.h>
57437
#include <avx512vbmiintrin.h>
57438
#include <avx512vbmi2intrin.h>
57439
// unfortunately, we may not get _blsr_u64, but, thankfully, clang
57440
// has it as a macro.
57441
#ifndef _blsr_u64
57442
// we roll our own
57443
#define _blsr_u64(n) ((n - 1) & n)
57444
#endif //  _blsr_u64
57445
#endif // SIMDJSON_CLANG_VISUAL_STUDIO
57446
57447
static_assert(sizeof(__m512i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for icelake");
57448
57449
#endif // SIMDJSON_ICELAKE_INTRINSICS_H
57450
/* end file simdjson/icelake/intrinsics.h */
57451
57452
#if !SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
57453
SIMDJSON_TARGET_REGION("avx512f,avx512dq,avx512cd,avx512bw,avx512vbmi,avx512vbmi2,avx512vl,avx2,bmi,pclmul,lzcnt,popcnt")
57454
#endif
57455
57456
/* including simdjson/icelake/bitmanipulation.h: #include "simdjson/icelake/bitmanipulation.h" */
57457
/* begin file simdjson/icelake/bitmanipulation.h */
57458
#ifndef SIMDJSON_ICELAKE_BITMANIPULATION_H
57459
#define SIMDJSON_ICELAKE_BITMANIPULATION_H
57460
57461
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57462
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
57463
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
57464
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57465
57466
namespace simdjson {
57467
namespace icelake {
57468
namespace {
57469
57470
// We sometimes call trailing_zero on inputs that are zero,
57471
// but the algorithms do not end up using the returned value.
57472
// Sadly, sanitizers are not smart enough to figure it out.
57473
SIMDJSON_NO_SANITIZE_UNDEFINED
57474
// This function can be used safely even if not all bytes have been
57475
// initialized.
57476
// See issue https://github.com/simdjson/simdjson/issues/1965
57477
SIMDJSON_NO_SANITIZE_MEMORY
57478
simdjson_inline int trailing_zeroes(uint64_t input_num) {
57479
#if SIMDJSON_REGULAR_VISUAL_STUDIO
57480
  return (int)_tzcnt_u64(input_num);
57481
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
57482
  ////////
57483
  // You might expect the next line to be equivalent to
57484
  // return (int)_tzcnt_u64(input_num);
57485
  // but the generated code differs and might be less efficient?
57486
  ////////
57487
  return __builtin_ctzll(input_num);
57488
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
57489
}
57490
57491
/* result might be undefined when input_num is zero */
57492
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
57493
  return _blsr_u64(input_num);
57494
}
57495
57496
/* result might be undefined when input_num is zero */
57497
simdjson_inline int leading_zeroes(uint64_t input_num) {
57498
  return int(_lzcnt_u64(input_num));
57499
}
57500
57501
#if SIMDJSON_REGULAR_VISUAL_STUDIO
57502
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
57503
  // note: we do not support legacy 32-bit Windows
57504
  return __popcnt64(input_num);// Visual Studio wants two underscores
57505
}
57506
#else
57507
simdjson_inline long long int count_ones(uint64_t input_num) {
57508
  return _popcnt64(input_num);
57509
}
57510
#endif
57511
57512
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
57513
                                uint64_t *result) {
57514
#if SIMDJSON_REGULAR_VISUAL_STUDIO
57515
  return _addcarry_u64(0, value1, value2,
57516
                       reinterpret_cast<unsigned __int64 *>(result));
57517
#else
57518
  return __builtin_uaddll_overflow(value1, value2,
57519
                                   reinterpret_cast<unsigned long long *>(result));
57520
#endif
57521
}
57522
57523
} // unnamed namespace
57524
} // namespace icelake
57525
} // namespace simdjson
57526
57527
#endif // SIMDJSON_ICELAKE_BITMANIPULATION_H
57528
/* end file simdjson/icelake/bitmanipulation.h */
57529
/* including simdjson/icelake/bitmask.h: #include "simdjson/icelake/bitmask.h" */
57530
/* begin file simdjson/icelake/bitmask.h */
57531
#ifndef SIMDJSON_ICELAKE_BITMASK_H
57532
#define SIMDJSON_ICELAKE_BITMASK_H
57533
57534
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57535
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
57536
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
57537
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57538
57539
namespace simdjson {
57540
namespace icelake {
57541
namespace {
57542
57543
//
57544
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
57545
//
57546
// For example, prefix_xor(00100100) == 00011100
57547
//
57548
simdjson_inline uint64_t prefix_xor(const uint64_t bitmask) {
57549
  // There should be no such thing with a processor supporting avx2
57550
  // but not clmul.
57551
  __m128i all_ones = _mm_set1_epi8('\xFF');
57552
  __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, bitmask), all_ones, 0);
57553
  return _mm_cvtsi128_si64(result);
57554
}
57555
57556
} // unnamed namespace
57557
} // namespace icelake
57558
} // namespace simdjson
57559
57560
#endif // SIMDJSON_ICELAKE_BITMASK_H
57561
/* end file simdjson/icelake/bitmask.h */
57562
/* including simdjson/icelake/simd.h: #include "simdjson/icelake/simd.h" */
57563
/* begin file simdjson/icelake/simd.h */
57564
#ifndef SIMDJSON_ICELAKE_SIMD_H
57565
#define SIMDJSON_ICELAKE_SIMD_H
57566
57567
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57568
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
57569
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
57570
/* amalgamation skipped (editor-only): #include "simdjson/icelake/bitmanipulation.h" */
57571
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
57572
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57573
57574
#if defined(__GNUC__) && !defined(__clang__)
57575
#if __GNUC__ == 8
57576
#define SIMDJSON_GCC8 1
57577
#endif //  __GNUC__ == 8
57578
#endif // defined(__GNUC__) && !defined(__clang__)
57579
57580
#if SIMDJSON_GCC8
57581
/**
57582
 * GCC 8 fails to provide _mm512_set_epi8. We roll our own.
57583
 */
57584
inline __m512i _mm512_set_epi8(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, uint8_t a7, uint8_t a8, uint8_t a9, uint8_t a10, uint8_t a11, uint8_t a12, uint8_t a13, uint8_t a14, uint8_t a15, uint8_t a16, uint8_t a17, uint8_t a18, uint8_t a19, uint8_t a20, uint8_t a21, uint8_t a22, uint8_t a23, uint8_t a24, uint8_t a25, uint8_t a26, uint8_t a27, uint8_t a28, uint8_t a29, uint8_t a30, uint8_t a31, uint8_t a32, uint8_t a33, uint8_t a34, uint8_t a35, uint8_t a36, uint8_t a37, uint8_t a38, uint8_t a39, uint8_t a40, uint8_t a41, uint8_t a42, uint8_t a43, uint8_t a44, uint8_t a45, uint8_t a46, uint8_t a47, uint8_t a48, uint8_t a49, uint8_t a50, uint8_t a51, uint8_t a52, uint8_t a53, uint8_t a54, uint8_t a55, uint8_t a56, uint8_t a57, uint8_t a58, uint8_t a59, uint8_t a60, uint8_t a61, uint8_t a62, uint8_t a63) {
57585
  return _mm512_set_epi64(uint64_t(a7) + (uint64_t(a6) << 8) + (uint64_t(a5) << 16) + (uint64_t(a4) << 24) + (uint64_t(a3) << 32) + (uint64_t(a2) << 40) + (uint64_t(a1) << 48) + (uint64_t(a0) << 56),
57586
                          uint64_t(a15) + (uint64_t(a14) << 8) + (uint64_t(a13) << 16) + (uint64_t(a12) << 24) + (uint64_t(a11) << 32) + (uint64_t(a10) << 40) + (uint64_t(a9) << 48) + (uint64_t(a8) << 56),
57587
                          uint64_t(a23) + (uint64_t(a22) << 8) + (uint64_t(a21) << 16) + (uint64_t(a20) << 24) + (uint64_t(a19) << 32) + (uint64_t(a18) << 40) + (uint64_t(a17) << 48) + (uint64_t(a16) << 56),
57588
                          uint64_t(a31) + (uint64_t(a30) << 8) + (uint64_t(a29) << 16) + (uint64_t(a28) << 24) + (uint64_t(a27) << 32) + (uint64_t(a26) << 40) + (uint64_t(a25) << 48) + (uint64_t(a24) << 56),
57589
                          uint64_t(a39) + (uint64_t(a38) << 8) + (uint64_t(a37) << 16) + (uint64_t(a36) << 24) + (uint64_t(a35) << 32) + (uint64_t(a34) << 40) + (uint64_t(a33) << 48) + (uint64_t(a32) << 56),
57590
                          uint64_t(a47) + (uint64_t(a46) << 8) + (uint64_t(a45) << 16) + (uint64_t(a44) << 24) + (uint64_t(a43) << 32) + (uint64_t(a42) << 40) + (uint64_t(a41) << 48) + (uint64_t(a40) << 56),
57591
                          uint64_t(a55) + (uint64_t(a54) << 8) + (uint64_t(a53) << 16) + (uint64_t(a52) << 24) + (uint64_t(a51) << 32) + (uint64_t(a50) << 40) + (uint64_t(a49) << 48) + (uint64_t(a48) << 56),
57592
                          uint64_t(a63) + (uint64_t(a62) << 8) + (uint64_t(a61) << 16) + (uint64_t(a60) << 24) + (uint64_t(a59) << 32) + (uint64_t(a58) << 40) + (uint64_t(a57) << 48) + (uint64_t(a56) << 56));
57593
}
57594
#endif // SIMDJSON_GCC8
57595
57596
57597
57598
namespace simdjson {
57599
namespace icelake {
57600
namespace {
57601
namespace simd {
57602
57603
  // Forward-declared so they can be used by splat and friends.
57604
  template<typename Child>
57605
  struct base {
57606
    __m512i value;
57607
57608
    // Zero constructor
57609
    simdjson_inline base() : value{__m512i()} {}
57610
57611
    // Conversion from SIMD register
57612
    simdjson_inline base(const __m512i _value) : value(_value) {}
57613
57614
    // Conversion to SIMD register
57615
    simdjson_inline operator const __m512i&() const { return this->value; }
57616
    simdjson_inline operator __m512i&() { return this->value; }
57617
57618
    // Bit operations
57619
    simdjson_inline Child operator|(const Child other) const { return _mm512_or_si512(*this, other); }
57620
    simdjson_inline Child operator&(const Child other) const { return _mm512_and_si512(*this, other); }
57621
    simdjson_inline Child operator^(const Child other) const { return _mm512_xor_si512(*this, other); }
57622
    simdjson_inline Child bit_andnot(const Child other) const { return _mm512_andnot_si512(other, *this); }
57623
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
57624
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
57625
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
57626
  };
57627
57628
  // Forward-declared so they can be used by splat and friends.
57629
  template<typename T>
57630
  struct simd8;
57631
57632
  template<typename T, typename Mask=simd8<bool>>
57633
  struct base8: base<simd8<T>> {
57634
    typedef uint32_t bitmask_t;
57635
    typedef uint64_t bitmask2_t;
57636
57637
    simdjson_inline base8() : base<simd8<T>>() {}
57638
    simdjson_inline base8(const __m512i _value) : base<simd8<T>>(_value) {}
57639
57640
    friend simdjson_really_inline uint64_t operator==(const simd8<T> lhs, const simd8<T> rhs) {
57641
      return _mm512_cmpeq_epi8_mask(lhs, rhs);
57642
    }
57643
57644
    static const int SIZE = sizeof(base<T>::value);
57645
57646
    template<int N=1>
57647
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
57648
     // workaround for compilers unable to figure out that 16 - N is a constant (GCC 8)
57649
      constexpr int shift = 16 - N;
57650
      return _mm512_alignr_epi8(*this, _mm512_permutex2var_epi64(prev_chunk, _mm512_set_epi64(13, 12, 11, 10, 9, 8, 7, 6), *this), shift);
57651
    }
57652
  };
57653
57654
  // SIMD byte mask type (returned by things like eq and gt)
57655
  template<>
57656
  struct simd8<bool>: base8<bool> {
57657
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm512_set1_epi8(uint8_t(-(!!_value))); }
57658
57659
    simdjson_inline simd8<bool>() : base8() {}
57660
    simdjson_inline simd8<bool>(const __m512i _value) : base8<bool>(_value) {}
57661
    // Splat constructor
57662
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
57663
    simdjson_inline bool any() const { return !!_mm512_test_epi8_mask (*this, *this); }
57664
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
57665
  };
57666
57667
  template<typename T>
57668
  struct base8_numeric: base8<T> {
57669
    static simdjson_inline simd8<T> splat(T _value) { return _mm512_set1_epi8(_value); }
57670
    static simdjson_inline simd8<T> zero() { return _mm512_setzero_si512(); }
57671
    static simdjson_inline simd8<T> load(const T values[64]) {
57672
      return _mm512_loadu_si512(reinterpret_cast<const __m512i *>(values));
57673
    }
57674
    // Repeat 16 values as many times as necessary (usually for lookup tables)
57675
    static simdjson_inline simd8<T> repeat_16(
57676
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
57677
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
57678
    ) {
57679
      return simd8<T>(
57680
        v0, v1, v2, v3, v4, v5, v6, v7,
57681
        v8, v9, v10,v11,v12,v13,v14,v15,
57682
        v0, v1, v2, v3, v4, v5, v6, v7,
57683
        v8, v9, v10,v11,v12,v13,v14,v15,
57684
        v0, v1, v2, v3, v4, v5, v6, v7,
57685
        v8, v9, v10,v11,v12,v13,v14,v15,
57686
        v0, v1, v2, v3, v4, v5, v6, v7,
57687
        v8, v9, v10,v11,v12,v13,v14,v15
57688
      );
57689
    }
57690
57691
    simdjson_inline base8_numeric() : base8<T>() {}
57692
    simdjson_inline base8_numeric(const __m512i _value) : base8<T>(_value) {}
57693
57694
    // Store to array
57695
    simdjson_inline void store(T dst[64]) const { return _mm512_storeu_si512(reinterpret_cast<__m512i *>(dst), *this); }
57696
57697
    // Addition/subtraction are the same for signed and unsigned
57698
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm512_add_epi8(*this, other); }
57699
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm512_sub_epi8(*this, other); }
57700
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
57701
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
57702
57703
    // Override to distinguish from bool version
57704
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
57705
57706
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
57707
    template<typename L>
57708
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
57709
      return _mm512_shuffle_epi8(lookup_table, *this);
57710
    }
57711
57712
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
57713
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
57714
    // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes
57715
    // get written.
57716
    // Design consideration: it seems like a function with the
57717
    // signature simd8<L> compress(uint32_t mask) would be
57718
    // sensible, but the AVX ISA makes this kind of approach difficult.
57719
    template<typename L>
57720
    simdjson_inline void compress(uint64_t mask, L * output) const {
57721
      _mm512_mask_compressstoreu_epi8 (output,~mask,*this);
57722
    }
57723
57724
    template<typename L>
57725
    simdjson_inline simd8<L> lookup_16(
57726
        L replace0,  L replace1,  L replace2,  L replace3,
57727
        L replace4,  L replace5,  L replace6,  L replace7,
57728
        L replace8,  L replace9,  L replace10, L replace11,
57729
        L replace12, L replace13, L replace14, L replace15) const {
57730
      return lookup_16(simd8<L>::repeat_16(
57731
        replace0,  replace1,  replace2,  replace3,
57732
        replace4,  replace5,  replace6,  replace7,
57733
        replace8,  replace9,  replace10, replace11,
57734
        replace12, replace13, replace14, replace15
57735
      ));
57736
    }
57737
  };
57738
57739
  // Signed bytes
57740
  template<>
57741
  struct simd8<int8_t> : base8_numeric<int8_t> {
57742
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
57743
    simdjson_inline simd8(const __m512i _value) : base8_numeric<int8_t>(_value) {}
57744
    // Splat constructor
57745
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
57746
    // Array constructor
57747
    simdjson_inline simd8(const int8_t values[64]) : simd8(load(values)) {}
57748
    // Member-by-member initialization
57749
    simdjson_inline simd8(
57750
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
57751
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15,
57752
      int8_t v16, int8_t v17, int8_t v18, int8_t v19, int8_t v20, int8_t v21, int8_t v22, int8_t v23,
57753
      int8_t v24, int8_t v25, int8_t v26, int8_t v27, int8_t v28, int8_t v29, int8_t v30, int8_t v31,
57754
      int8_t v32, int8_t v33, int8_t v34, int8_t v35, int8_t v36, int8_t v37, int8_t v38, int8_t v39,
57755
      int8_t v40, int8_t v41, int8_t v42, int8_t v43, int8_t v44, int8_t v45, int8_t v46, int8_t v47,
57756
      int8_t v48, int8_t v49, int8_t v50, int8_t v51, int8_t v52, int8_t v53, int8_t v54, int8_t v55,
57757
      int8_t v56, int8_t v57, int8_t v58, int8_t v59, int8_t v60, int8_t v61, int8_t v62, int8_t v63
57758
    ) : simd8(_mm512_set_epi8(
57759
      v63, v62, v61, v60, v59, v58, v57, v56,
57760
      v55, v54, v53, v52, v51, v50, v49, v48,
57761
      v47, v46, v45, v44, v43, v42, v41, v40,
57762
      v39, v38, v37, v36, v35, v34, v33, v32,
57763
      v31, v30, v29, v28, v27, v26, v25, v24,
57764
      v23, v22, v21, v20, v19, v18, v17, v16,
57765
      v15, v14, v13, v12, v11, v10,  v9,  v8,
57766
       v7,  v6,  v5,  v4,  v3,  v2,  v1,  v0
57767
    )) {}
57768
57769
    // Repeat 16 values as many times as necessary (usually for lookup tables)
57770
    simdjson_inline static simd8<int8_t> repeat_16(
57771
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
57772
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
57773
    ) {
57774
      return simd8<int8_t>(
57775
        v0, v1, v2, v3, v4, v5, v6, v7,
57776
        v8, v9, v10,v11,v12,v13,v14,v15,
57777
        v0, v1, v2, v3, v4, v5, v6, v7,
57778
        v8, v9, v10,v11,v12,v13,v14,v15,
57779
        v0, v1, v2, v3, v4, v5, v6, v7,
57780
        v8, v9, v10,v11,v12,v13,v14,v15,
57781
        v0, v1, v2, v3, v4, v5, v6, v7,
57782
        v8, v9, v10,v11,v12,v13,v14,v15
57783
      );
57784
    }
57785
57786
    // Order-sensitive comparisons
57787
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm512_max_epi8(*this, other); }
57788
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm512_min_epi8(*this, other); }
57789
57790
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm512_maskz_abs_epi8(_mm512_cmpgt_epi8_mask(*this, other),_mm512_set1_epi8(uint8_t(0x80))); }
57791
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm512_maskz_abs_epi8(_mm512_cmpgt_epi8_mask(other, *this),_mm512_set1_epi8(uint8_t(0x80))); }
57792
  };
57793
57794
  // Unsigned bytes
57795
  template<>
57796
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
57797
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
57798
    simdjson_inline simd8(const __m512i _value) : base8_numeric<uint8_t>(_value) {}
57799
    // Splat constructor
57800
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
57801
    // Array constructor
57802
    simdjson_inline simd8(const uint8_t values[64]) : simd8(load(values)) {}
57803
    // Member-by-member initialization
57804
    simdjson_inline simd8(
57805
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
57806
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15,
57807
      uint8_t v16, uint8_t v17, uint8_t v18, uint8_t v19, uint8_t v20, uint8_t v21, uint8_t v22, uint8_t v23,
57808
      uint8_t v24, uint8_t v25, uint8_t v26, uint8_t v27, uint8_t v28, uint8_t v29, uint8_t v30, uint8_t v31,
57809
      uint8_t v32, uint8_t v33, uint8_t v34, uint8_t v35, uint8_t v36, uint8_t v37, uint8_t v38, uint8_t v39,
57810
      uint8_t v40, uint8_t v41, uint8_t v42, uint8_t v43, uint8_t v44, uint8_t v45, uint8_t v46, uint8_t v47,
57811
      uint8_t v48, uint8_t v49, uint8_t v50, uint8_t v51, uint8_t v52, uint8_t v53, uint8_t v54, uint8_t v55,
57812
      uint8_t v56, uint8_t v57, uint8_t v58, uint8_t v59, uint8_t v60, uint8_t v61, uint8_t v62, uint8_t v63
57813
    ) : simd8(_mm512_set_epi8(
57814
      v63, v62, v61, v60, v59, v58, v57, v56,
57815
      v55, v54, v53, v52, v51, v50, v49, v48,
57816
      v47, v46, v45, v44, v43, v42, v41, v40,
57817
      v39, v38, v37, v36, v35, v34, v33, v32,
57818
      v31, v30, v29, v28, v27, v26, v25, v24,
57819
      v23, v22, v21, v20, v19, v18, v17, v16,
57820
      v15, v14, v13, v12, v11, v10,  v9,  v8,
57821
       v7,  v6,  v5,  v4,  v3,  v2,  v1,  v0
57822
    )) {}
57823
57824
    // Repeat 16 values as many times as necessary (usually for lookup tables)
57825
    simdjson_inline static simd8<uint8_t> repeat_16(
57826
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
57827
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
57828
    ) {
57829
      return simd8<uint8_t>(
57830
        v0, v1, v2, v3, v4, v5, v6, v7,
57831
        v8, v9, v10,v11,v12,v13,v14,v15,
57832
        v0, v1, v2, v3, v4, v5, v6, v7,
57833
        v8, v9, v10,v11,v12,v13,v14,v15,
57834
        v0, v1, v2, v3, v4, v5, v6, v7,
57835
        v8, v9, v10,v11,v12,v13,v14,v15,
57836
        v0, v1, v2, v3, v4, v5, v6, v7,
57837
        v8, v9, v10,v11,v12,v13,v14,v15
57838
      );
57839
    }
57840
57841
    // Saturated math
57842
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm512_adds_epu8(*this, other); }
57843
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm512_subs_epu8(*this, other); }
57844
57845
    // Order-specific operations
57846
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm512_max_epu8(*this, other); }
57847
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm512_min_epu8(other, *this); }
57848
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
57849
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
57850
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
57851
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
57852
    simdjson_inline uint64_t operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
57853
    simdjson_inline uint64_t operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
57854
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
57855
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->lt_bits(other).any_bits_set(); }
57856
57857
    // Bit-specific operations
57858
    simdjson_inline simd8<bool> bits_not_set() const { return _mm512_mask_blend_epi8(*this == uint8_t(0), _mm512_set1_epi8(0), _mm512_set1_epi8(-1)); }
57859
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
57860
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
57861
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
57862
57863
    simdjson_inline bool is_ascii() const { return _mm512_movepi8_mask(*this) == 0; }
57864
    simdjson_inline bool bits_not_set_anywhere() const {
57865
      return !_mm512_test_epi8_mask(*this, *this);
57866
    }
57867
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
57868
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return !_mm512_test_epi8_mask(*this, bits); }
57869
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
57870
    template<int N>
57871
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm512_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
57872
    template<int N>
57873
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm512_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
57874
    // Get one of the bits and make a bitmask out of it.
57875
    // e.g. value.get_bit<7>() gets the high bit
57876
    template<int N>
57877
    simdjson_inline uint64_t get_bit() const { return _mm512_movepi8_mask(_mm512_slli_epi16(*this, 7-N)); }
57878
  };
57879
57880
  template<typename T>
57881
  struct simd8x64 {
57882
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
57883
    static_assert(NUM_CHUNKS == 1, "Icelake kernel should use one register per 64-byte block.");
57884
    const simd8<T> chunks[NUM_CHUNKS];
57885
57886
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
57887
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
57888
    simd8x64() = delete; // no default constructor allowed
57889
57890
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1) : chunks{chunk0, chunk1} {}
57891
    simdjson_inline simd8x64(const simd8<T> chunk0) : chunks{chunk0} {}
57892
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr)} {}
57893
57894
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
57895
      this->chunks[0].compress(mask, output);
57896
      return 64 - count_ones(mask);
57897
    }
57898
57899
    simdjson_inline void store(T ptr[64]) const {
57900
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
57901
    }
57902
57903
    simdjson_inline simd8<T> reduce_or() const {
57904
      return this->chunks[0];
57905
    }
57906
57907
    simdjson_inline simd8x64<T> bit_or(const T m) const {
57908
      const simd8<T> mask = simd8<T>::splat(m);
57909
      return simd8x64<T>(
57910
        this->chunks[0] | mask
57911
      );
57912
    }
57913
57914
    simdjson_inline uint64_t eq(const T m) const {
57915
      const simd8<T> mask = simd8<T>::splat(m);
57916
      return this->chunks[0] == mask;
57917
    }
57918
57919
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
57920
      return this->chunks[0] == other.chunks[0];
57921
    }
57922
57923
    simdjson_inline uint64_t lteq(const T m) const {
57924
      const simd8<T> mask = simd8<T>::splat(m);
57925
      return this->chunks[0] <= mask;
57926
    }
57927
  }; // struct simd8x64<T>
57928
57929
} // namespace simd
57930
57931
} // unnamed namespace
57932
} // namespace icelake
57933
} // namespace simdjson
57934
57935
#endif // SIMDJSON_ICELAKE_SIMD_H
57936
/* end file simdjson/icelake/simd.h */
57937
/* including simdjson/icelake/stringparsing_defs.h: #include "simdjson/icelake/stringparsing_defs.h" */
57938
/* begin file simdjson/icelake/stringparsing_defs.h */
57939
#ifndef SIMDJSON_ICELAKE_STRINGPARSING_DEFS_H
57940
#define SIMDJSON_ICELAKE_STRINGPARSING_DEFS_H
57941
57942
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57943
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
57944
/* amalgamation skipped (editor-only): #include "simdjson/icelake/simd.h" */
57945
/* amalgamation skipped (editor-only): #include "simdjson/icelake/bitmanipulation.h" */
57946
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57947
57948
namespace simdjson {
57949
namespace icelake {
57950
namespace {
57951
57952
using namespace simd;
57953
57954
// Holds backslashes and quotes locations.
57955
struct backslash_and_quote {
57956
public:
57957
  static constexpr uint32_t BYTES_PROCESSED = 64;
57958
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
57959
57960
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
57961
  simdjson_inline bool has_backslash() { return ((quote_bits - 1) & bs_bits) != 0; }
57962
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
57963
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
57964
57965
  uint64_t bs_bits;
57966
  uint64_t quote_bits;
57967
}; // struct backslash_and_quote
57968
57969
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
57970
  // this can read up to 15 bytes beyond the buffer size, but we require
57971
  // SIMDJSON_PADDING of padding
57972
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
57973
  simd8<uint8_t> v(src);
57974
  // store to dest unconditionally - we can overwrite the bits we don't like later
57975
  v.store(dst);
57976
  return {
57977
      static_cast<uint64_t>(v == '\\'), // bs_bits
57978
      static_cast<uint64_t>(v == '"'), // quote_bits
57979
  };
57980
}
57981
57982
} // unnamed namespace
57983
} // namespace icelake
57984
} // namespace simdjson
57985
57986
#endif // SIMDJSON_ICELAKE_STRINGPARSING_DEFS_H
57987
/* end file simdjson/icelake/stringparsing_defs.h */
57988
/* including simdjson/icelake/numberparsing_defs.h: #include "simdjson/icelake/numberparsing_defs.h" */
57989
/* begin file simdjson/icelake/numberparsing_defs.h */
57990
#ifndef SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H
57991
#define SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H
57992
57993
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
57994
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
57995
/* amalgamation skipped (editor-only): #include "simdjson/icelake/intrinsics.h" */
57996
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
57997
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
57998
57999
namespace simdjson {
58000
namespace icelake {
58001
namespace numberparsing {
58002
58003
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
58004
  // this actually computes *16* values so we are being wasteful.
58005
  const __m128i ascii0 = _mm_set1_epi8('0');
58006
  const __m128i mul_1_10 =
58007
      _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1);
58008
  const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1);
58009
  const __m128i mul_1_10000 =
58010
      _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1);
58011
  const __m128i input = _mm_sub_epi8(
58012
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0);
58013
  const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10);
58014
  const __m128i t2 = _mm_madd_epi16(t1, mul_1_100);
58015
  const __m128i t3 = _mm_packus_epi32(t2, t2);
58016
  const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000);
58017
  return _mm_cvtsi128_si32(
58018
      t4); // only captures the sum of the first 8 digits, drop the rest
58019
}
58020
58021
/** @private */
58022
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
58023
  internal::value128 answer;
58024
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
58025
#ifdef _M_ARM64
58026
  // ARM64 has native support for 64-bit multiplications, no need to emultate
58027
  answer.high = __umulh(value1, value2);
58028
  answer.low = value1 * value2;
58029
#else
58030
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
58031
#endif // _M_ARM64
58032
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
58033
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
58034
  answer.low = uint64_t(r);
58035
  answer.high = uint64_t(r >> 64);
58036
#endif
58037
  return answer;
58038
}
58039
58040
} // namespace numberparsing
58041
} // namespace icelake
58042
} // namespace simdjson
58043
58044
#define SIMDJSON_SWAR_NUMBER_PARSING 1
58045
58046
#endif // SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H
58047
/* end file simdjson/icelake/numberparsing_defs.h */
58048
/* end file simdjson/icelake/begin.h */
58049
/* including simdjson/generic/ondemand/amalgamated.h for icelake: #include "simdjson/generic/ondemand/amalgamated.h" */
58050
/* begin file simdjson/generic/ondemand/amalgamated.h for icelake */
58051
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
58052
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
58053
#endif
58054
58055
// Stuff other things depend on
58056
/* including simdjson/generic/ondemand/base.h for icelake: #include "simdjson/generic/ondemand/base.h" */
58057
/* begin file simdjson/generic/ondemand/base.h for icelake */
58058
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
58059
58060
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
58061
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_BASE_H */
58062
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
58063
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
58064
58065
namespace simdjson {
58066
namespace icelake {
58067
/**
58068
 * A fast, simple, DOM-like interface that parses JSON as you use it.
58069
 *
58070
 * Designed for maximum speed and a lower memory profile.
58071
 */
58072
namespace ondemand {
58073
58074
/** Represents the depth of a JSON value (number of nested arrays/objects). */
58075
using depth_t = int32_t;
58076
58077
/** @copydoc simdjson::icelake::number_type */
58078
using number_type = simdjson::icelake::number_type;
58079
58080
/** @private Position in the JSON buffer indexes */
58081
using token_position = const uint32_t *;
58082
58083
class array;
58084
class array_iterator;
58085
class document;
58086
class document_reference;
58087
class document_stream;
58088
class field;
58089
class json_iterator;
58090
enum class json_type;
58091
struct number;
58092
class object;
58093
class object_iterator;
58094
class parser;
58095
class raw_json_string;
58096
class token_iterator;
58097
class value;
58098
class value_iterator;
58099
58100
} // namespace ondemand
58101
} // namespace icelake
58102
} // namespace simdjson
58103
58104
#endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H
58105
/* end file simdjson/generic/ondemand/base.h for icelake */
58106
/* including simdjson/generic/ondemand/value_iterator.h for icelake: #include "simdjson/generic/ondemand/value_iterator.h" */
58107
/* begin file simdjson/generic/ondemand/value_iterator.h for icelake */
58108
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
58109
58110
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
58111
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H */
58112
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
58113
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
58114
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
58115
58116
namespace simdjson {
58117
namespace icelake {
58118
namespace ondemand {
58119
58120
/**
58121
 * Iterates through a single JSON value at a particular depth.
58122
 *
58123
 * Does not keep track of the type of value: provides methods for objects, arrays and scalars and expects
58124
 * the caller to call the right ones.
58125
 *
58126
 * @private This is not intended for external use.
58127
 */
58128
class value_iterator {
58129
protected:
58130
  /** The underlying JSON iterator */
58131
  json_iterator *_json_iter{};
58132
  /** The depth of this value */
58133
  depth_t _depth{};
58134
  /**
58135
   * The starting token index for this value
58136
   */
58137
  token_position _start_position{};
58138
58139
public:
58140
  simdjson_inline value_iterator() noexcept = default;
58141
58142
  /**
58143
   * Denote that we're starting a document.
58144
   */
58145
  simdjson_inline void start_document() noexcept;
58146
58147
  /**
58148
   * Skips a non-iterated or partially-iterated JSON value, whether it is a scalar, array or object.
58149
   *
58150
   * Optimized for scalars.
58151
   */
58152
  simdjson_warn_unused simdjson_inline error_code skip_child() noexcept;
58153
58154
  /**
58155
   * Tell whether the iterator is at the EOF mark
58156
   */
58157
  simdjson_inline bool at_end() const noexcept;
58158
58159
  /**
58160
   * Tell whether the iterator is at the start of the value
58161
   */
58162
  simdjson_inline bool at_start() const noexcept;
58163
58164
  /**
58165
   * Tell whether the value is open--if the value has not been used, or the array/object is still open.
58166
   */
58167
  simdjson_inline bool is_open() const noexcept;
58168
58169
  /**
58170
   * Tell whether the value is at an object's first field (just after the {).
58171
   */
58172
  simdjson_inline bool at_first_field() const noexcept;
58173
58174
  /**
58175
   * Abandon all iteration.
58176
   */
58177
  simdjson_inline void abandon() noexcept;
58178
58179
  /**
58180
   * Get the child value as a value_iterator.
58181
   */
58182
  simdjson_inline value_iterator child_value() const noexcept;
58183
58184
  /**
58185
   * Get the depth of this value.
58186
   */
58187
  simdjson_inline int32_t depth() const noexcept;
58188
58189
  /**
58190
   * Get the JSON type of this value.
58191
   *
58192
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
58193
   */
58194
  simdjson_inline simdjson_result<json_type> type() const noexcept;
58195
58196
  /**
58197
   * @addtogroup object Object iteration
58198
   *
58199
   * Methods to iterate and find object fields. These methods generally *assume* the value is
58200
   * actually an object; the caller is responsible for keeping track of that fact.
58201
   *
58202
   * @{
58203
   */
58204
58205
  /**
58206
   * Start an object iteration.
58207
   *
58208
   * @returns Whether the object had any fields (returns false for empty).
58209
   * @error INCORRECT_TYPE if there is no opening {
58210
   */
58211
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_object() noexcept;
58212
  /**
58213
   * Start an object iteration from the root.
58214
   *
58215
   * @returns Whether the object had any fields (returns false for empty).
58216
   * @error INCORRECT_TYPE if there is no opening {
58217
   * @error TAPE_ERROR if there is no matching } at end of document
58218
   */
58219
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_object() noexcept;
58220
  /**
58221
   * Checks whether an object could be started from the root. May be called by start_root_object.
58222
   *
58223
   * @returns SUCCESS if it is possible to safely start an object from the root (document level).
58224
   * @error INCORRECT_TYPE if there is no opening {
58225
   * @error TAPE_ERROR if there is no matching } at end of document
58226
   */
58227
  simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept;
58228
  /**
58229
   * Start an object iteration after the user has already checked and moved past the {.
58230
   *
58231
   * Does not move the iterator unless the object is empty ({}).
58232
   *
58233
   * @returns Whether the object had any fields (returns false for empty).
58234
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
58235
   *        array or object is incomplete).
58236
   */
58237
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_object() noexcept;
58238
  /**
58239
   * Start an object iteration from the root, after the user has already checked and moved past the {.
58240
   *
58241
   * Does not move the iterator unless the object is empty ({}).
58242
   *
58243
   * @returns Whether the object had any fields (returns false for empty).
58244
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
58245
   *        array or object is incomplete).
58246
   */
58247
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_object() noexcept;
58248
58249
  /**
58250
   * Moves to the next field in an object.
58251
   *
58252
   * Looks for , and }. If } is found, the object is finished and the iterator advances past it.
58253
   * Otherwise, it advances to the next value.
58254
   *
58255
   * @return whether there is another field in the object.
58256
   * @error TAPE_ERROR If there is a comma missing between fields.
58257
   * @error TAPE_ERROR If there is a comma, but not enough tokens remaining to have a key, :, and value.
58258
   */
58259
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_field() noexcept;
58260
58261
  /**
58262
   * Get the current field's key.
58263
   */
58264
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> field_key() noexcept;
58265
58266
  /**
58267
   * Pass the : in the field and move to its value.
58268
   */
58269
  simdjson_warn_unused simdjson_inline error_code field_value() noexcept;
58270
58271
  /**
58272
   * Find the next field with the given key.
58273
   *
58274
   * Assumes you have called next_field() or otherwise matched the previous value.
58275
   *
58276
   * This means the iterator must be sitting at the next key:
58277
   *
58278
   * ```
58279
   * { "a": 1, "b": 2 }
58280
   *           ^
58281
   * ```
58282
   *
58283
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
58284
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
58285
   * fail to match some keys with escapes (\u, \n, etc.).
58286
   */
58287
  simdjson_warn_unused simdjson_inline error_code find_field(const std::string_view key) noexcept;
58288
58289
  /**
58290
   * Find the next field with the given key, *without* unescaping. This assumes object order: it
58291
   * will not find the field if it was already passed when looking for some *other* field.
58292
   *
58293
   * Assumes you have called next_field() or otherwise matched the previous value.
58294
   *
58295
   * This means the iterator must be sitting at the next key:
58296
   *
58297
   * ```
58298
   * { "a": 1, "b": 2 }
58299
   *           ^
58300
   * ```
58301
   *
58302
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
58303
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
58304
   * fail to match some keys with escapes (\u, \n, etc.).
58305
   */
58306
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
58307
58308
  /**
58309
   * Find the field with the given key without regard to order, and *without* unescaping.
58310
   *
58311
   * This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
58312
   *
58313
   * Assumes you have called next_field() or otherwise matched the previous value.
58314
   *
58315
   * This means the iterator must be sitting at the next key:
58316
   *
58317
   * ```
58318
   * { "a": 1, "b": 2 }
58319
   *           ^
58320
   * ```
58321
   *
58322
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
58323
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
58324
   * fail to match some keys with escapes (\u, \n, etc.).
58325
   */
58326
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
58327
58328
  /** @} */
58329
58330
  /**
58331
   * @addtogroup array Array iteration
58332
   * Methods to iterate over array elements. These methods generally *assume* the value is actually
58333
   * an object; the caller is responsible for keeping track of that fact.
58334
   * @{
58335
   */
58336
58337
  /**
58338
   * Check for an opening [ and start an array iteration.
58339
   *
58340
   * @returns Whether the array had any elements (returns false for empty).
58341
   * @error INCORRECT_TYPE If there is no [.
58342
   */
58343
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_array() noexcept;
58344
  /**
58345
   * Check for an opening [ and start an array iteration while at the root.
58346
   *
58347
   * @returns Whether the array had any elements (returns false for empty).
58348
   * @error INCORRECT_TYPE If there is no [.
58349
   * @error TAPE_ERROR if there is no matching ] at end of document
58350
   */
58351
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_array() noexcept;
58352
  /**
58353
   * Checks whether an array could be started from the root. May be called by start_root_array.
58354
   *
58355
   * @returns SUCCESS if it is possible to safely start an array from the root (document level).
58356
   * @error INCORRECT_TYPE If there is no [.
58357
   * @error TAPE_ERROR if there is no matching ] at end of document
58358
   */
58359
  simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept;
58360
  /**
58361
   * Start an array iteration, after the user has already checked and moved past the [.
58362
   *
58363
   * Does not move the iterator unless the array is empty ([]).
58364
   *
58365
   * @returns Whether the array had any elements (returns false for empty).
58366
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
58367
   *        array or object is incomplete).
58368
   */
58369
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_array() noexcept;
58370
  /**
58371
   * Start an array iteration from the root, after the user has already checked and moved past the [.
58372
   *
58373
   * Does not move the iterator unless the array is empty ([]).
58374
   *
58375
   * @returns Whether the array had any elements (returns false for empty).
58376
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
58377
   *        array or object is incomplete).
58378
   */
58379
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_array() noexcept;
58380
58381
  /**
58382
   * Moves to the next element in an array.
58383
   *
58384
   * Looks for , and ]. If ] is found, the array is finished and the iterator advances past it.
58385
   * Otherwise, it advances to the next value.
58386
   *
58387
   * @return Whether there is another element in the array.
58388
   * @error TAPE_ERROR If there is a comma missing between elements.
58389
   */
58390
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_element() noexcept;
58391
58392
  /**
58393
   * Get a child value iterator.
58394
   */
58395
  simdjson_warn_unused simdjson_inline value_iterator child() const noexcept;
58396
58397
  /** @} */
58398
58399
  /**
58400
   * @defgroup scalar Scalar values
58401
   * @addtogroup scalar
58402
   * @{
58403
   */
58404
58405
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
58406
  template <typename string_type>
58407
  simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
58408
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
58409
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
58410
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
58411
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
58412
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
58413
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
58414
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
58415
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
58416
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
58417
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
58418
  simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
58419
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
58420
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
58421
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
58422
58423
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
58424
  template <typename string_type>
58425
  simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
58426
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
58427
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
58428
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
58429
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
58430
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
58431
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
58432
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
58433
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
58434
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
58435
  simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
58436
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
58437
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
58438
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
58439
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
58440
58441
  simdjson_inline error_code error() const noexcept;
58442
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
58443
  simdjson_inline const json_iterator &json_iter() const noexcept;
58444
  simdjson_inline json_iterator &json_iter() noexcept;
58445
58446
  simdjson_inline void assert_is_valid() const noexcept;
58447
  simdjson_inline bool is_valid() const noexcept;
58448
58449
  /** @} */
58450
protected:
58451
  /**
58452
   * Restarts an array iteration.
58453
   * @returns Whether the array has any elements (returns false for empty).
58454
   */
58455
  simdjson_inline simdjson_result<bool> reset_array() noexcept;
58456
  /**
58457
   * Restarts an object iteration.
58458
   * @returns Whether the object has any fields (returns false for empty).
58459
   */
58460
  simdjson_inline simdjson_result<bool> reset_object() noexcept;
58461
  /**
58462
   * move_at_start(): moves us so that we are pointing at the beginning of
58463
   * the container. It updates the index so that at_start() is true and it
58464
   * syncs the depth. The user can then create a new container instance.
58465
   *
58466
   * Usage: used with value::count_elements().
58467
   **/
58468
  simdjson_inline void move_at_start() noexcept;
58469
58470
  /**
58471
   * move_at_container_start(): moves us so that we are pointing at the beginning of
58472
   * the container so that assert_at_container_start() passes.
58473
   *
58474
   * Usage: used with reset_array() and reset_object().
58475
   **/
58476
   simdjson_inline void move_at_container_start() noexcept;
58477
  /* Useful for debugging and logging purposes. */
58478
  inline std::string to_string() const noexcept;
58479
  simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
58480
58481
  simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
58482
  simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
58483
  simdjson_inline const uint8_t *peek_start() const noexcept;
58484
  simdjson_inline uint32_t peek_start_length() const noexcept;
58485
  simdjson_inline uint32_t peek_root_length() const noexcept;
58486
58487
  /**
58488
   * The general idea of the advance_... methods and the peek_* methods
58489
   * is that you first peek and check that you have desired type. If you do,
58490
   * and only if you do, then you advance.
58491
   *
58492
   * We used to unconditionally advance. But this made reasoning about our
58493
   * current state difficult.
58494
   * Suppose you always advance. Look at the 'value' matching the key
58495
   * "shadowable" in the following example...
58496
   *
58497
   * ({"globals":{"a":{"shadowable":[}}}})
58498
   *
58499
   * If the user thinks it is a Boolean and asks for it, then we check the '[',
58500
   * decide it is not a Boolean, but still move into the next character ('}'). Now
58501
   * we are left pointing at '}' right after a '['. And we have not yet reported
58502
   * an error, only that we do not have a Boolean.
58503
   *
58504
   * If, instead, you just stand your ground until it is content that you know, then
58505
   * you will only even move beyond the '[' if the user tells you that you have an
58506
   * array. So you will be at the '}' character inside the array and, hopefully, you
58507
   * will then catch the error because an array cannot start with '}', but the code
58508
   * processing Boolean values does not know this.
58509
   *
58510
   * So the contract is: first call 'peek_...' and then call 'advance_...' only
58511
   * if you have determined that it is a type you can handle.
58512
   *
58513
   * Unfortunately, it makes the code more verbose, longer and maybe more error prone.
58514
   */
58515
58516
  simdjson_inline void advance_scalar(const char *type) noexcept;
58517
  simdjson_inline void advance_root_scalar(const char *type) noexcept;
58518
  simdjson_inline void advance_non_root_scalar(const char *type) noexcept;
58519
58520
  simdjson_inline const uint8_t *peek_scalar(const char *type) noexcept;
58521
  simdjson_inline const uint8_t *peek_root_scalar(const char *type) noexcept;
58522
  simdjson_inline const uint8_t *peek_non_root_scalar(const char *type) noexcept;
58523
58524
58525
  simdjson_inline error_code start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept;
58526
  simdjson_inline error_code end_container() noexcept;
58527
58528
  /**
58529
   * Advance to a place expecting a value (increasing depth).
58530
   *
58531
   * @return The current token (the one left behind).
58532
   * @error TAPE_ERROR If the document ended early.
58533
   */
58534
  simdjson_inline simdjson_result<const uint8_t *> advance_to_value() noexcept;
58535
58536
  simdjson_inline error_code incorrect_type_error(const char *message) const noexcept;
58537
  simdjson_inline error_code error_unless_more_tokens(uint32_t tokens=1) const noexcept;
58538
58539
  simdjson_inline bool is_at_start() const noexcept;
58540
  /**
58541
   * is_at_iterator_start() returns true on an array or object after it has just been
58542
   * created, whether the instance is empty or not.
58543
   *
58544
   * Usage: used by array::begin() in debug mode (SIMDJSON_DEVELOPMENT_CHECKS)
58545
   */
58546
  simdjson_inline bool is_at_iterator_start() const noexcept;
58547
58548
  /**
58549
   * Assuming that we are within an object, this returns true if we
58550
   * are pointing at a key.
58551
   *
58552
   * Usage: the skip_child() method should never be used while we are pointing
58553
   * at a key inside an object.
58554
   */
58555
  simdjson_inline bool is_at_key() const noexcept;
58556
58557
  inline void assert_at_start() const noexcept;
58558
  inline void assert_at_container_start() const noexcept;
58559
  inline void assert_at_root() const noexcept;
58560
  inline void assert_at_child() const noexcept;
58561
  inline void assert_at_next() const noexcept;
58562
  inline void assert_at_non_root_start() const noexcept;
58563
58564
  /** Get the starting position of this value */
58565
  simdjson_inline token_position start_position() const noexcept;
58566
58567
  /** @copydoc error_code json_iterator::position() const noexcept; */
58568
  simdjson_inline token_position position() const noexcept;
58569
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
58570
  simdjson_inline token_position last_position() const noexcept;
58571
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
58572
  simdjson_inline token_position end_position() const noexcept;
58573
  /** @copydoc error_code json_iterator::report_error(error_code error, const char *message) noexcept; */
58574
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
58575
58576
  friend class document;
58577
  friend class object;
58578
  friend class array;
58579
  friend class value;
58580
  friend class field;
58581
}; // value_iterator
58582
58583
} // namespace ondemand
58584
} // namespace icelake
58585
} // namespace simdjson
58586
58587
namespace simdjson {
58588
58589
template<>
58590
struct simdjson_result<icelake::ondemand::value_iterator> : public icelake::implementation_simdjson_result_base<icelake::ondemand::value_iterator> {
58591
public:
58592
  simdjson_inline simdjson_result(icelake::ondemand::value_iterator &&value) noexcept; ///< @private
58593
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
58594
  simdjson_inline simdjson_result() noexcept = default;
58595
};
58596
58597
} // namespace simdjson
58598
58599
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
58600
/* end file simdjson/generic/ondemand/value_iterator.h for icelake */
58601
/* including simdjson/generic/ondemand/value.h for icelake: #include "simdjson/generic/ondemand/value.h" */
58602
/* begin file simdjson/generic/ondemand/value.h for icelake */
58603
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H
58604
58605
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
58606
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_H */
58607
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
58608
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
58609
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
58610
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
58611
58612
namespace simdjson {
58613
namespace icelake {
58614
namespace ondemand {
58615
58616
/**
58617
 * An ephemeral JSON value returned during iteration. It is only valid for as long as you do
58618
 * not access more data in the JSON document.
58619
 */
58620
class value {
58621
public:
58622
  /**
58623
   * Create a new invalid value.
58624
   *
58625
   * Exists so you can declare a variable and later assign to it before use.
58626
   */
58627
  simdjson_inline value() noexcept = default;
58628
58629
  /**
58630
   * Get this value as the given type.
58631
   *
58632
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
58633
   *
58634
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
58635
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
58636
   *
58637
   * @returns A value of the given type, parsed from the JSON.
58638
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
58639
   */
58640
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
58641
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
58642
    // immediately fail.
58643
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
58644
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
58645
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
58646
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
58647
      " You may also add support for custom types, see our documentation.");
58648
  }
58649
58650
  /**
58651
   * Get this value as the given type.
58652
   *
58653
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
58654
   *
58655
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
58656
   * @returns INCORRECT_TYPE If the JSON value is not an object.
58657
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
58658
   */
58659
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
58660
58661
  /**
58662
   * Cast this JSON value to an array.
58663
   *
58664
   * @returns An object that can be used to iterate the array.
58665
   * @returns INCORRECT_TYPE If the JSON value is not an array.
58666
   */
58667
  simdjson_inline simdjson_result<array> get_array() noexcept;
58668
58669
  /**
58670
   * Cast this JSON value to an object.
58671
   *
58672
   * @returns An object that can be used to look up or iterate fields.
58673
   * @returns INCORRECT_TYPE If the JSON value is not an object.
58674
   */
58675
  simdjson_inline simdjson_result<object> get_object() noexcept;
58676
58677
  /**
58678
   * Cast this JSON value to an unsigned integer.
58679
   *
58680
   * @returns A unsigned 64-bit integer.
58681
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
58682
   */
58683
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
58684
58685
  /**
58686
   * Cast this JSON value (inside string) to a unsigned integer.
58687
   *
58688
   * @returns A unsigned 64-bit integer.
58689
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
58690
   */
58691
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
58692
58693
  /**
58694
   * Cast this JSON value to a signed integer.
58695
   *
58696
   * @returns A signed 64-bit integer.
58697
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
58698
   */
58699
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
58700
58701
  /**
58702
   * Cast this JSON value (inside string) to a signed integer.
58703
   *
58704
   * @returns A signed 64-bit integer.
58705
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
58706
   */
58707
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
58708
58709
  /**
58710
   * Cast this JSON value to a double.
58711
   *
58712
   * @returns A double.
58713
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
58714
   */
58715
  simdjson_inline simdjson_result<double> get_double() noexcept;
58716
58717
  /**
58718
   * Cast this JSON value (inside string) to a double
58719
   *
58720
   * @returns A double.
58721
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
58722
   */
58723
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
58724
58725
  /**
58726
   * Cast this JSON value to a string.
58727
   *
58728
   * The string is guaranteed to be valid UTF-8.
58729
   *
58730
   * Equivalent to get<std::string_view>().
58731
   *
58732
   * Important: a value should be consumed once. Calling get_string() twice on the same value
58733
   * is an error.
58734
   *
58735
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
58736
   *          time it parses a document or when it is destroyed.
58737
   * @returns INCORRECT_TYPE if the JSON value is not a string.
58738
   */
58739
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
58740
58741
  /**
58742
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
58743
   *
58744
   * The string is guaranteed to be valid UTF-8.
58745
   *
58746
   * Important: a value should be consumed once. Calling get_string() twice on the same value
58747
   * is an error.
58748
   *
58749
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
58750
   * We recommend you avoid allocating an std::string unless you need to.
58751
   *
58752
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
58753
   */
58754
  template <typename string_type>
58755
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
58756
58757
  /**
58758
   * Cast this JSON value to a "wobbly" string.
58759
   *
58760
   * The string is may not be a valid UTF-8 string.
58761
   * See https://simonsapin.github.io/wtf-8/
58762
   *
58763
   * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value
58764
   * is an error.
58765
   *
58766
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
58767
   *          time it parses a document or when it is destroyed.
58768
   * @returns INCORRECT_TYPE if the JSON value is not a string.
58769
   */
58770
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
58771
  /**
58772
   * Cast this JSON value to a raw_json_string.
58773
   *
58774
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
58775
   *
58776
   * @returns A pointer to the raw JSON for the given string.
58777
   * @returns INCORRECT_TYPE if the JSON value is not a string.
58778
   */
58779
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
58780
58781
  /**
58782
   * Cast this JSON value to a bool.
58783
   *
58784
   * @returns A bool value.
58785
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
58786
   */
58787
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
58788
58789
  /**
58790
   * Checks if this JSON value is null. If and only if the value is
58791
   * null, then it is consumed (we advance). If we find a token that
58792
   * begins with 'n' but is not 'null', then an error is returned.
58793
   *
58794
   * @returns Whether the value is null.
58795
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
58796
   */
58797
  simdjson_inline simdjson_result<bool> is_null() noexcept;
58798
58799
#if SIMDJSON_EXCEPTIONS
58800
  /**
58801
   * Cast this JSON value to an instance of type T. The programmer is responsible for
58802
   * providing an implementation of get<T> for the type T, if T is not one of the types
58803
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.).
58804
   *
58805
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
58806
   *
58807
   * @returns An instance of type T
58808
   */
58809
  template <class T>
58810
  explicit simdjson_inline operator T() noexcept(false);
58811
  /**
58812
   * Cast this JSON value to an array.
58813
   *
58814
   * @returns An object that can be used to iterate the array.
58815
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
58816
   */
58817
  simdjson_inline operator array() noexcept(false);
58818
  /**
58819
   * Cast this JSON value to an object.
58820
   *
58821
   * @returns An object that can be used to look up or iterate fields.
58822
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
58823
   */
58824
  simdjson_inline operator object() noexcept(false);
58825
  /**
58826
   * Cast this JSON value to an unsigned integer.
58827
   *
58828
   * @returns A signed 64-bit integer.
58829
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
58830
   */
58831
  simdjson_inline operator uint64_t() noexcept(false);
58832
  /**
58833
   * Cast this JSON value to a signed integer.
58834
   *
58835
   * @returns A signed 64-bit integer.
58836
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
58837
   */
58838
  simdjson_inline operator int64_t() noexcept(false);
58839
  /**
58840
   * Cast this JSON value to a double.
58841
   *
58842
   * @returns A double.
58843
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
58844
   */
58845
  simdjson_inline operator double() noexcept(false);
58846
  /**
58847
   * Cast this JSON value to a string.
58848
   *
58849
   * The string is guaranteed to be valid UTF-8.
58850
   *
58851
   * Equivalent to get<std::string_view>().
58852
   *
58853
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
58854
   *          time it parses a document or when it is destroyed.
58855
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
58856
   */
58857
  simdjson_inline operator std::string_view() noexcept(false);
58858
  /**
58859
   * Cast this JSON value to a raw_json_string.
58860
   *
58861
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
58862
   *
58863
   * @returns A pointer to the raw JSON for the given string.
58864
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
58865
   */
58866
  simdjson_inline operator raw_json_string() noexcept(false);
58867
  /**
58868
   * Cast this JSON value to a bool.
58869
   *
58870
   * @returns A bool value.
58871
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
58872
   */
58873
  simdjson_inline operator bool() noexcept(false);
58874
#endif
58875
58876
  /**
58877
   * Begin array iteration.
58878
   *
58879
   * Part of the std::iterable interface.
58880
   *
58881
   * @returns INCORRECT_TYPE If the JSON value is not an array.
58882
   */
58883
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
58884
  /**
58885
   * Sentinel representing the end of the array.
58886
   *
58887
   * Part of the std::iterable interface.
58888
   */
58889
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
58890
  /**
58891
   * This method scans the array and counts the number of elements.
58892
   * The count_elements method should always be called before you have begun
58893
   * iterating through the array: it is expected that you are pointing at
58894
   * the beginning of the array.
58895
   * The runtime complexity is linear in the size of the array. After
58896
   * calling this function, if successful, the array is 'rewinded' at its
58897
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
58898
   * there is a missing comma), then an error is returned and it is no longer
58899
   * safe to continue.
58900
   *
58901
   * Performance hint: You should only call count_elements() as a last
58902
   * resort as it may require scanning the document twice or more.
58903
   */
58904
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
58905
  /**
58906
   * This method scans the object and counts the number of key-value pairs.
58907
   * The count_fields method should always be called before you have begun
58908
   * iterating through the object: it is expected that you are pointing at
58909
   * the beginning of the object.
58910
   * The runtime complexity is linear in the size of the object. After
58911
   * calling this function, if successful, the object is 'rewinded' at its
58912
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
58913
   * there is a missing comma), then an error is returned and it is no longer
58914
   * safe to continue.
58915
   *
58916
   * To check that an object is empty, it is more performant to use
58917
   * the is_empty() method on the object instance.
58918
   *
58919
   * Performance hint: You should only call count_fields() as a last
58920
   * resort as it may require scanning the document twice or more.
58921
   */
58922
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
58923
  /**
58924
   * Get the value at the given index in the array. This function has linear-time complexity.
58925
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
58926
   *
58927
   * @return The value at the given index, or:
58928
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
58929
   */
58930
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
58931
  /**
58932
   * Look up a field by name on an object (order-sensitive).
58933
   *
58934
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
58935
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
58936
   *
58937
   * ```c++
58938
   * simdjson::ondemand::parser parser;
58939
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
58940
   * double z = obj.find_field("z");
58941
   * double y = obj.find_field("y");
58942
   * double x = obj.find_field("x");
58943
   * ```
58944
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
58945
   * that only one field is returned.
58946
58947
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
58948
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
58949
   *
58950
   * @param key The key to look up.
58951
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
58952
   */
58953
  simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept;
58954
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
58955
  simdjson_inline simdjson_result<value> find_field(const char *key) noexcept;
58956
58957
  /**
58958
   * Look up a field by name on an object, without regard to key order.
58959
   *
58960
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
58961
   * and often appears negligible. It starts out normally, starting out at the last field; but if
58962
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
58963
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
58964
   * in question is large. The fact that the extra code is there also bumps the executable size.
58965
   *
58966
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
58967
   * default behavior failed to look up a field just because it was in the wrong order--and many
58968
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
58969
   *
58970
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
58971
   * that only one field is returned.
58972
   *
58973
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
58974
   * field as not there when they are not in order).
58975
   *
58976
   * @param key The key to look up.
58977
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
58978
   */
58979
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
58980
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
58981
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
58982
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
58983
  simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept;
58984
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
58985
  simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
58986
58987
  /**
58988
   * Get the type of this JSON value. It does not validate or consume the value.
58989
   * E.g., you must still call "is_null()" to check that a value is null even if
58990
   * "type()" returns json_type::null.
58991
   *
58992
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
58993
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
58994
   * let it throw an exception).
58995
   *
58996
   * @return The type of JSON value (json_type::array, json_type::object, json_type::string,
58997
   *     json_type::number, json_type::boolean, or json_type::null).
58998
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
58999
   */
59000
  simdjson_inline simdjson_result<json_type> type() noexcept;
59001
59002
  /**
59003
   * Checks whether the value is a scalar (string, number, null, Boolean).
59004
   * Returns false when there it is an array or object.
59005
   *
59006
   * @returns true if the type is string, number, null, Boolean
59007
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
59008
   */
59009
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
59010
  /**
59011
   * Checks whether the value is a string.
59012
   *
59013
   * @returns true if the type is string
59014
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
59015
   */
59016
  simdjson_inline simdjson_result<bool> is_string() noexcept;
59017
59018
  /**
59019
   * Checks whether the value is a negative number.
59020
   *
59021
   * @returns true if the number if negative.
59022
   */
59023
  simdjson_inline bool is_negative() noexcept;
59024
  /**
59025
   * Checks whether the value is an integer number. Note that
59026
   * this requires to partially parse the number string. If
59027
   * the value is determined to be an integer, it may still
59028
   * not parse properly as an integer in subsequent steps
59029
   * (e.g., it might overflow).
59030
   *
59031
   * Performance note: if you call this function systematically
59032
   * before parsing a number, you may have fallen for a performance
59033
   * anti-pattern.
59034
   *
59035
   * @returns true if the number if negative.
59036
   */
59037
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
59038
  /**
59039
   * Determine the number type (integer or floating-point number) as quickly
59040
   * as possible. This function does not fully validate the input. It is
59041
   * useful when you only need to classify the numbers, without parsing them.
59042
   *
59043
   * If you are planning to retrieve the value or you need full validation,
59044
   * consider using the get_number() method instead: it will fully parse
59045
   * and validate the input, and give you access to the type:
59046
   * get_number().get_number_type().
59047
   *
59048
   * get_number_type() is number_type::unsigned_integer if we have
59049
   * an integer greater or equal to 9223372036854775808.
59050
   * get_number_type() is number_type::signed_integer if we have an
59051
   * integer that is less than 9223372036854775808.
59052
   * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits,
59053
   * in which case the digit_count is set to the length of the big integer string.
59054
   * Otherwise, get_number_type() has value number_type::floating_point_number.
59055
   *
59056
   * This function requires processing the number string, but it is expected
59057
   * to be faster than get_number().get_number_type() because it is does not
59058
   * parse the number value.
59059
   *
59060
   * @returns the type of the number
59061
   */
59062
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
59063
59064
  /**
59065
   * Attempt to parse an ondemand::number. An ondemand::number may
59066
   * contain an integer value or a floating-point value, the simdjson
59067
   * library will autodetect the type. Thus it is a dynamically typed
59068
   * number. Before accessing the value, you must determine the detected
59069
   * type.
59070
   *
59071
   * number.get_number_type() is number_type::signed_integer if we have
59072
   * an integer in [-9223372036854775808,9223372036854775808)
59073
   * You can recover the value by calling number.get_int64() and you
59074
   * have that number.is_int64() is true.
59075
   *
59076
   * number.get_number_type() is number_type::unsigned_integer if we have
59077
   * an integer in [9223372036854775808,18446744073709551616)
59078
   * You can recover the value by calling number.get_uint64() and you
59079
   * have that number.is_uint64() is true.
59080
   *
59081
   * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code.
59082
   *
59083
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
59084
   * and we have a binary64 number.
59085
   * You can recover the value by calling number.get_double() and you
59086
   * have that number.is_double() is true.
59087
   *
59088
   * You must check the type before accessing the value: it is an error
59089
   * to call "get_int64()" when number.get_number_type() is not
59090
   * number_type::signed_integer and when number.is_int64() is false.
59091
   *
59092
   * Performance note: this is designed with performance in mind. When
59093
   * calling 'get_number()', you scan the number string only once, determining
59094
   * efficiently the type and storing it in an efficient manner.
59095
   */
59096
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
59097
59098
  /**
59099
   * Get the raw JSON for this token.
59100
   *
59101
   * The string_view will always point into the input buffer.
59102
   *
59103
   * The string_view will start at the beginning of the token, and include the entire token
59104
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
59105
   * string token always begins with a " and is always terminated by the final ", possibly
59106
   * followed by a number of spaces.
59107
   *
59108
   * The string_view is *not* null-terminated. However, if this is a scalar (string, number,
59109
   * boolean, or null), the character after the end of the string_view is guaranteed to be
59110
   * a non-space token.
59111
   *
59112
   * Tokens include:
59113
   * - {
59114
   * - [
59115
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
59116
   * - -1.2e-100
59117
   * - true
59118
   * - false
59119
   * - null
59120
   *
59121
   * See also value::raw_json().
59122
   */
59123
  simdjson_inline std::string_view raw_json_token() noexcept;
59124
59125
  /**
59126
   * Get a string_view pointing at this value in the JSON document.
59127
   * If this element is an array or an object, it consumes the array or the object
59128
   * and returns a string_view instance corresponding to the
59129
   * array as represented in JSON. It points inside the original document.
59130
   * If this element is a scalar (string, number, Boolean, null), it returns what
59131
   * raw_json_token() would return.
59132
   */
59133
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
59134
59135
  /**
59136
   * Returns the current location in the document if in bounds.
59137
   */
59138
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
59139
59140
  /**
59141
   * Returns the current depth in the document if in bounds.
59142
   *
59143
   * E.g.,
59144
   *  0 = finished with document
59145
   *  1 = document root value (could be [ or {, not yet known)
59146
   *  2 = , or } inside root array/object
59147
   *  3 = key or value inside root array/object.
59148
   */
59149
  simdjson_inline int32_t current_depth() const noexcept;
59150
59151
  /**
59152
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
59153
   * https://tools.ietf.org/html/rfc6901 standard.
59154
   *
59155
   *   ondemand::parser parser;
59156
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
59157
   *   auto doc = parser.iterate(json);
59158
   *   doc.at_pointer("/foo/a/1") == 20
59159
   *
59160
   * It is allowed for a key to be the empty string:
59161
   *
59162
   *   ondemand::parser parser;
59163
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
59164
   *   auto doc = parser.iterate(json);
59165
   *   doc.at_pointer("//a/1") == 20
59166
   *
59167
   * Note that at_pointer() called on the document automatically calls the document's rewind
59168
   * method between each call. It invalidates all previously accessed arrays, objects and values
59169
   * that have not been consumed.
59170
   *
59171
   * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not
59172
   * standardized (by RFC 6901). We provide some experimental support for JSON pointers
59173
   * on non-document instances.  Yet it is not the case when calling at_pointer on an array
59174
   * or an object instance: there is no rewind and no invalidation.
59175
   *
59176
   * You may only call at_pointer on an array after it has been created, but before it has
59177
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
59178
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
59179
   * to call at_pointer on the same array.
59180
   *
59181
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
59182
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
59183
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
59184
   *
59185
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
59186
   *
59187
   * @return The value associated with the given JSON pointer, or:
59188
   *         - NO_SUCH_FIELD if a field does not exist in an object
59189
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
59190
   *         - INCORRECT_TYPE if a non-integer is used to access an array
59191
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
59192
   */
59193
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
59194
59195
  /**
59196
   * Get the value associated with the given JSONPath expression. We only support
59197
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
59198
   * names and array indices.
59199
   *
59200
   * @return The value associated with the given JSONPath expression, or:
59201
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
59202
   *         - NO_SUCH_FIELD if a field does not exist in an object
59203
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
59204
   *         - INCORRECT_TYPE if a non-integer is used to access an array
59205
   */
59206
  simdjson_inline simdjson_result<value> at_path(std::string_view at_path) noexcept;
59207
59208
59209
protected:
59210
  /**
59211
   * Create a value.
59212
   */
59213
  simdjson_inline value(const value_iterator &iter) noexcept;
59214
59215
  /**
59216
   * Skip this value, allowing iteration to continue.
59217
   */
59218
  simdjson_inline void skip() noexcept;
59219
59220
  /**
59221
   * Start a value at the current position.
59222
   *
59223
   * (It should already be started; this is just a self-documentation method.)
59224
   */
59225
  static simdjson_inline value start(const value_iterator &iter) noexcept;
59226
59227
  /**
59228
   * Resume a value.
59229
   */
59230
  static simdjson_inline value resume(const value_iterator &iter) noexcept;
59231
59232
  /**
59233
   * Get the object, starting or resuming it as necessary
59234
   */
59235
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
59236
59237
  // simdjson_inline void log_value(const char *type) const noexcept;
59238
  // simdjson_inline void log_error(const char *message) const noexcept;
59239
59240
  value_iterator iter{};
59241
59242
  friend class document;
59243
  friend class array_iterator;
59244
  friend class field;
59245
  friend class object;
59246
  friend struct simdjson_result<value>;
59247
  friend struct simdjson_result<field>;
59248
  friend class field;
59249
};
59250
59251
} // namespace ondemand
59252
} // namespace icelake
59253
} // namespace simdjson
59254
59255
namespace simdjson {
59256
59257
template<>
59258
struct simdjson_result<icelake::ondemand::value> : public icelake::implementation_simdjson_result_base<icelake::ondemand::value> {
59259
public:
59260
  simdjson_inline simdjson_result(icelake::ondemand::value &&value) noexcept; ///< @private
59261
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
59262
  simdjson_inline simdjson_result() noexcept = default;
59263
59264
  simdjson_inline simdjson_result<icelake::ondemand::array> get_array() noexcept;
59265
  simdjson_inline simdjson_result<icelake::ondemand::object> get_object() noexcept;
59266
59267
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
59268
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
59269
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
59270
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
59271
  simdjson_inline simdjson_result<double> get_double() noexcept;
59272
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
59273
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
59274
  template <typename string_type>
59275
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
59276
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
59277
  simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> get_raw_json_string() noexcept;
59278
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
59279
  simdjson_inline simdjson_result<bool> is_null() noexcept;
59280
59281
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
59282
59283
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
59284
59285
#if SIMDJSON_EXCEPTIONS
59286
  template <class T>
59287
  explicit simdjson_inline operator T() noexcept(false);
59288
  simdjson_inline operator icelake::ondemand::array() noexcept(false);
59289
  simdjson_inline operator icelake::ondemand::object() noexcept(false);
59290
  simdjson_inline operator uint64_t() noexcept(false);
59291
  simdjson_inline operator int64_t() noexcept(false);
59292
  simdjson_inline operator double() noexcept(false);
59293
  simdjson_inline operator std::string_view() noexcept(false);
59294
  simdjson_inline operator icelake::ondemand::raw_json_string() noexcept(false);
59295
  simdjson_inline operator bool() noexcept(false);
59296
#endif
59297
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
59298
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
59299
  simdjson_inline simdjson_result<icelake::ondemand::value> at(size_t index) noexcept;
59300
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> begin() & noexcept;
59301
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> end() & noexcept;
59302
59303
  /**
59304
   * Look up a field by name on an object (order-sensitive).
59305
   *
59306
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
59307
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
59308
   *
59309
   * ```c++
59310
   * simdjson::ondemand::parser parser;
59311
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
59312
   * double z = obj.find_field("z");
59313
   * double y = obj.find_field("y");
59314
   * double x = obj.find_field("x");
59315
   * ```
59316
   *
59317
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
59318
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
59319
   *
59320
   * @param key The key to look up.
59321
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
59322
   */
59323
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(std::string_view key) noexcept;
59324
  /** @overload simdjson_inline simdjson_result<icelake::ondemand::value> find_field(std::string_view key) noexcept; */
59325
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(const char *key) noexcept;
59326
59327
  /**
59328
   * Look up a field by name on an object, without regard to key order.
59329
   *
59330
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
59331
   * and often appears negligible. It starts out normally, starting out at the last field; but if
59332
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
59333
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
59334
   * in question is large. The fact that the extra code is there also bumps the executable size.
59335
   *
59336
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
59337
   * default behavior failed to look up a field just because it was in the wrong order--and many
59338
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
59339
   *
59340
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
59341
   * field as not there when they are not in order).
59342
   *
59343
   * @param key The key to look up.
59344
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
59345
   */
59346
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) noexcept;
59347
  /** @overload simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
59348
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(const char *key) noexcept;
59349
  /** @overload simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
59350
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](std::string_view key) noexcept;
59351
  /** @overload simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
59352
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](const char *key) noexcept;
59353
59354
  /**
59355
   * Get the type of this JSON value.
59356
   *
59357
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
59358
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
59359
   * let it throw an exception).
59360
   */
59361
  simdjson_inline simdjson_result<icelake::ondemand::json_type> type() noexcept;
59362
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
59363
  simdjson_inline simdjson_result<bool> is_string() noexcept;
59364
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
59365
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
59366
  simdjson_inline simdjson_result<icelake::number_type> get_number_type() noexcept;
59367
  simdjson_inline simdjson_result<icelake::ondemand::number> get_number() noexcept;
59368
59369
  /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
59370
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
59371
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
59372
59373
  /** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
59374
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
59375
  /** @copydoc simdjson_inline int32_t current_depth() const noexcept */
59376
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
59377
  simdjson_inline simdjson_result<icelake::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
59378
  simdjson_inline simdjson_result<icelake::ondemand::value> at_path(std::string_view json_path) noexcept;
59379
};
59380
59381
} // namespace simdjson
59382
59383
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H
59384
/* end file simdjson/generic/ondemand/value.h for icelake */
59385
/* including simdjson/generic/ondemand/logger.h for icelake: #include "simdjson/generic/ondemand/logger.h" */
59386
/* begin file simdjson/generic/ondemand/logger.h for icelake */
59387
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
59388
59389
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
59390
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_H */
59391
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
59392
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
59393
59394
namespace simdjson {
59395
namespace icelake {
59396
namespace ondemand {
59397
59398
// Logging should be free unless SIMDJSON_VERBOSE_LOGGING is set. Importantly, it is critical
59399
// that the call to the log functions be side-effect free. Thus, for example, you should not
59400
// create temporary std::string instances.
59401
namespace logger {
59402
59403
enum class log_level : int32_t {
59404
  info = 0,
59405
  error = 1
59406
};
59407
59408
#if SIMDJSON_VERBOSE_LOGGING
59409
  static constexpr const bool LOG_ENABLED = true;
59410
#else
59411
  static constexpr const bool LOG_ENABLED = false;
59412
#endif
59413
59414
// We do not want these functions to be 'really inlined' since real inlining is
59415
// for performance purposes and if you are using the loggers, you do not care about
59416
// performance (or should not).
59417
static inline void log_headers() noexcept;
59418
// If args are provided, title will be treated as format string
59419
template <typename... Args>
59420
static inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
59421
template <typename... Args>
59422
static inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
59423
static inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
59424
static inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
59425
static inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
59426
static inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
59427
static inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
59428
static inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
59429
59430
static inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail="") noexcept;
59431
static inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
59432
59433
static inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
59434
static inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
59435
static inline void log_start_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
59436
static inline void log_end_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
59437
static inline void log_error(const value_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
59438
59439
} // namespace logger
59440
} // namespace ondemand
59441
} // namespace icelake
59442
} // namespace simdjson
59443
59444
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
59445
/* end file simdjson/generic/ondemand/logger.h for icelake */
59446
/* including simdjson/generic/ondemand/token_iterator.h for icelake: #include "simdjson/generic/ondemand/token_iterator.h" */
59447
/* begin file simdjson/generic/ondemand/token_iterator.h for icelake */
59448
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
59449
59450
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
59451
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H */
59452
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
59453
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
59454
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
59455
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
59456
59457
namespace simdjson {
59458
namespace icelake {
59459
namespace ondemand {
59460
59461
/**
59462
 * Iterates through JSON tokens (`{` `}` `[` `]` `,` `:` `"<string>"` `123` `true` `false` `null`)
59463
 * detected by stage 1.
59464
 *
59465
 * @private This is not intended for external use.
59466
 */
59467
class token_iterator {
59468
public:
59469
  /**
59470
   * Create a new invalid token_iterator.
59471
   *
59472
   * Exists so you can declare a variable and later assign to it before use.
59473
   */
59474
  simdjson_inline token_iterator() noexcept = default;
59475
  simdjson_inline token_iterator(token_iterator &&other) noexcept = default;
59476
  simdjson_inline token_iterator &operator=(token_iterator &&other) noexcept = default;
59477
  simdjson_inline token_iterator(const token_iterator &other) noexcept = default;
59478
  simdjson_inline token_iterator &operator=(const token_iterator &other) noexcept = default;
59479
59480
  /**
59481
   * Advance to the next token (returning the current one).
59482
   */
59483
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
59484
  /**
59485
   * Reports the current offset in bytes from the start of the underlying buffer.
59486
   */
59487
  simdjson_inline uint32_t current_offset() const noexcept;
59488
  /**
59489
   * Get the JSON text for a given token (relative).
59490
   *
59491
   * This is not null-terminated; it is a view into the JSON.
59492
   *
59493
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
59494
   *              1 = next token, -1 = prev token.
59495
   *
59496
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
59497
   * it is not used...
59498
   */
59499
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
59500
  /**
59501
   * Get the maximum length of the JSON text for a given token.
59502
   *
59503
   * The length will include any whitespace at the end of the token.
59504
   *
59505
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
59506
   *              1 = next token, -1 = prev token.
59507
   */
59508
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
59509
59510
  /**
59511
   * Get the JSON text for a given token.
59512
   *
59513
   * This is not null-terminated; it is a view into the JSON.
59514
   *
59515
   * @param position The position of the token.
59516
   *
59517
   */
59518
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
59519
  /**
59520
   * Get the maximum length of the JSON text for a given token.
59521
   *
59522
   * The length will include any whitespace at the end of the token.
59523
   *
59524
   * @param position The position of the token.
59525
   */
59526
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
59527
  /**
59528
   * Get the maximum length of the JSON text for a root token.
59529
   *
59530
   * The length will include any whitespace at the end of the token.
59531
   *
59532
   * @param position The position of the token (start of the document).
59533
   */
59534
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
59535
  /**
59536
   * Return the current index.
59537
   */
59538
  simdjson_inline token_position position() const noexcept;
59539
  /**
59540
   * Reset to a previously saved index.
59541
   */
59542
  simdjson_inline void set_position(token_position target_position) noexcept;
59543
59544
  // NOTE: we don't support a full C++ iterator interface, because we expect people to make
59545
  // different calls to advance the iterator based on *their own* state.
59546
59547
  simdjson_inline bool operator==(const token_iterator &other) const noexcept;
59548
  simdjson_inline bool operator!=(const token_iterator &other) const noexcept;
59549
  simdjson_inline bool operator>(const token_iterator &other) const noexcept;
59550
  simdjson_inline bool operator>=(const token_iterator &other) const noexcept;
59551
  simdjson_inline bool operator<(const token_iterator &other) const noexcept;
59552
  simdjson_inline bool operator<=(const token_iterator &other) const noexcept;
59553
59554
protected:
59555
  simdjson_inline token_iterator(const uint8_t *buf, token_position position) noexcept;
59556
59557
  /**
59558
   * Get the index of the JSON text for a given token (relative).
59559
   *
59560
   * This is not null-terminated; it is a view into the JSON.
59561
   *
59562
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
59563
   *              1 = next token, -1 = prev token.
59564
   */
59565
  simdjson_inline uint32_t peek_index(int32_t delta=0) const noexcept;
59566
  /**
59567
   * Get the index of the JSON text for a given token.
59568
   *
59569
   * This is not null-terminated; it is a view into the JSON.
59570
   *
59571
   * @param position The position of the token.
59572
   *
59573
   */
59574
  simdjson_inline uint32_t peek_index(token_position position) const noexcept;
59575
59576
  const uint8_t *buf{};
59577
  token_position _position{};
59578
59579
  friend class json_iterator;
59580
  friend class value_iterator;
59581
  friend class object;
59582
  template <typename... Args>
59583
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
59584
  template <typename... Args>
59585
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
59586
};
59587
59588
} // namespace ondemand
59589
} // namespace icelake
59590
} // namespace simdjson
59591
59592
namespace simdjson {
59593
59594
template<>
59595
struct simdjson_result<icelake::ondemand::token_iterator> : public icelake::implementation_simdjson_result_base<icelake::ondemand::token_iterator> {
59596
public:
59597
  simdjson_inline simdjson_result(icelake::ondemand::token_iterator &&value) noexcept; ///< @private
59598
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
59599
  simdjson_inline simdjson_result() noexcept = default;
59600
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
59601
};
59602
59603
} // namespace simdjson
59604
59605
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
59606
/* end file simdjson/generic/ondemand/token_iterator.h for icelake */
59607
/* including simdjson/generic/ondemand/json_iterator.h for icelake: #include "simdjson/generic/ondemand/json_iterator.h" */
59608
/* begin file simdjson/generic/ondemand/json_iterator.h for icelake */
59609
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
59610
59611
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
59612
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H */
59613
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
59614
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
59615
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
59616
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
59617
59618
namespace simdjson {
59619
namespace icelake {
59620
namespace ondemand {
59621
59622
/**
59623
 * Iterates through JSON tokens, keeping track of depth and string buffer.
59624
 *
59625
 * @private This is not intended for external use.
59626
 */
59627
class json_iterator {
59628
protected:
59629
  token_iterator token{};
59630
  ondemand::parser *parser{};
59631
  /**
59632
   * Next free location in the string buffer.
59633
   *
59634
   * Used by raw_json_string::unescape() to have a place to unescape strings to.
59635
   */
59636
  uint8_t *_string_buf_loc{};
59637
  /**
59638
   * JSON error, if there is one.
59639
   *
59640
   * INCORRECT_TYPE and NO_SUCH_FIELD are *not* stored here, ever.
59641
   *
59642
   * PERF NOTE: we *hope* this will be elided into control flow, as it is only used (a) in the first
59643
   * iteration of the loop, or (b) for the final iteration after a missing comma is found in ++. If
59644
   * this is not elided, we should make sure it's at least not using up a register. Failing that,
59645
   * we should store it in document so there's only one of them.
59646
   */
59647
  error_code error{SUCCESS};
59648
  /**
59649
   * Depth of the current token in the JSON.
59650
   *
59651
   * - 0 = finished with document
59652
   * - 1 = document root value (could be [ or {, not yet known)
59653
   * - 2 = , or } inside root array/object
59654
   * - 3 = key or value inside root array/object.
59655
   */
59656
  depth_t _depth{};
59657
  /**
59658
   * Beginning of the document indexes.
59659
   * Normally we have root == parser->implementation->structural_indexes.get()
59660
   * but this may differ, especially in streaming mode (where we have several
59661
   * documents);
59662
   */
59663
  token_position _root{};
59664
  /**
59665
   * Normally, a json_iterator operates over a single document, but in
59666
   * some cases, we may have a stream of documents. This attribute is meant
59667
   * as meta-data: the json_iterator works the same irrespective of the
59668
   * value of this attribute.
59669
   */
59670
  bool _streaming{false};
59671
59672
public:
59673
  simdjson_inline json_iterator() noexcept = default;
59674
  simdjson_inline json_iterator(json_iterator &&other) noexcept;
59675
  simdjson_inline json_iterator &operator=(json_iterator &&other) noexcept;
59676
  simdjson_inline explicit json_iterator(const json_iterator &other) noexcept = default;
59677
  simdjson_inline json_iterator &operator=(const json_iterator &other) noexcept = default;
59678
  /**
59679
   * Skips a JSON value, whether it is a scalar, array or object.
59680
   */
59681
  simdjson_warn_unused simdjson_inline error_code skip_child(depth_t parent_depth) noexcept;
59682
59683
  /**
59684
   * Tell whether the iterator is still at the start
59685
   */
59686
  simdjson_inline bool at_root() const noexcept;
59687
59688
  /**
59689
   * Tell whether we should be expected to run in streaming
59690
   * mode (iterating over many documents). It is pure metadata
59691
   * that does not affect how the iterator works. It is used by
59692
   * start_root_array() and start_root_object().
59693
   */
59694
  simdjson_inline bool streaming() const noexcept;
59695
59696
  /**
59697
   * Get the root value iterator
59698
   */
59699
  simdjson_inline token_position root_position() const noexcept;
59700
  /**
59701
   * Assert that we are at the document depth (== 1)
59702
   */
59703
  simdjson_inline void assert_at_document_depth() const noexcept;
59704
  /**
59705
   * Assert that we are at the root of the document
59706
   */
59707
  simdjson_inline void assert_at_root() const noexcept;
59708
59709
  /**
59710
   * Tell whether the iterator is at the EOF mark
59711
   */
59712
  simdjson_inline bool at_end() const noexcept;
59713
59714
  /**
59715
   * Tell whether the iterator is live (has not been moved).
59716
   */
59717
  simdjson_inline bool is_alive() const noexcept;
59718
59719
  /**
59720
   * Abandon this iterator, setting depth to 0 (as if the document is finished).
59721
   */
59722
  simdjson_inline void abandon() noexcept;
59723
59724
  /**
59725
   * Advance the current token without modifying depth.
59726
   */
59727
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
59728
59729
  /**
59730
   * Returns true if there is a single token in the index (i.e., it is
59731
   * a JSON with a scalar value such as a single number).
59732
   *
59733
   * @return whether there is a single token
59734
   */
59735
  simdjson_inline bool is_single_token() const noexcept;
59736
59737
  /**
59738
   * Assert that there are at least the given number of tokens left.
59739
   *
59740
   * Has no effect in release builds.
59741
   */
59742
  simdjson_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
59743
  /**
59744
   * Assert that the given position addresses an actual token (is within bounds).
59745
   *
59746
   * Has no effect in release builds.
59747
   */
59748
  simdjson_inline void assert_valid_position(token_position position) const noexcept;
59749
  /**
59750
   * Get the JSON text for a given token (relative).
59751
   *
59752
   * This is not null-terminated; it is a view into the JSON.
59753
   *
59754
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
59755
   *
59756
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
59757
   * it is not used ...
59758
   */
59759
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
59760
  /**
59761
   * Get the maximum length of the JSON text for the current token (or relative).
59762
   *
59763
   * The length will include any whitespace at the end of the token.
59764
   *
59765
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
59766
   */
59767
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
59768
  /**
59769
   * Get a pointer to the current location in the input buffer.
59770
   *
59771
   * This is not null-terminated; it is a view into the JSON.
59772
   *
59773
   * You may be pointing outside of the input buffer: it is not generally
59774
   * safe to dereference this pointer.
59775
   */
59776
  simdjson_inline const uint8_t *unsafe_pointer() const noexcept;
59777
  /**
59778
   * Get the JSON text for a given token.
59779
   *
59780
   * This is not null-terminated; it is a view into the JSON.
59781
   *
59782
   * @param position The position of the token to retrieve.
59783
   *
59784
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
59785
   * it is not used ...
59786
   */
59787
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
59788
  /**
59789
   * Get the maximum length of the JSON text for the current token (or relative).
59790
   *
59791
   * The length will include any whitespace at the end of the token.
59792
   *
59793
   * @param position The position of the token to retrieve.
59794
   */
59795
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
59796
  /**
59797
   * Get the maximum length of the JSON text for the current root token.
59798
   *
59799
   * The length will include any whitespace at the end of the token.
59800
   *
59801
   * @param position The position of the token to retrieve.
59802
   */
59803
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
59804
  /**
59805
   * Get the JSON text for the last token in the document.
59806
   *
59807
   * This is not null-terminated; it is a view into the JSON.
59808
   *
59809
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
59810
   * it is not used ...
59811
   */
59812
  simdjson_inline const uint8_t *peek_last() const noexcept;
59813
59814
  /**
59815
   * Ascend one level.
59816
   *
59817
   * Validates that the depth - 1 == parent_depth.
59818
   *
59819
   * @param parent_depth the expected parent depth.
59820
   */
59821
  simdjson_inline void ascend_to(depth_t parent_depth) noexcept;
59822
59823
  /**
59824
   * Descend one level.
59825
   *
59826
   * Validates that the new depth == child_depth.
59827
   *
59828
   * @param child_depth the expected child depth.
59829
   */
59830
  simdjson_inline void descend_to(depth_t child_depth) noexcept;
59831
  simdjson_inline void descend_to(depth_t child_depth, int32_t delta) noexcept;
59832
59833
  /**
59834
   * Get current depth.
59835
   */
59836
  simdjson_inline depth_t depth() const noexcept;
59837
59838
  /**
59839
   * Get current (writeable) location in the string buffer.
59840
   */
59841
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
59842
59843
  /**
59844
   * Report an unrecoverable error, preventing further iteration.
59845
   *
59846
   * @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
59847
   * @param message An error message to report with the error.
59848
   */
59849
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
59850
59851
  /**
59852
   * Log error, but don't stop iteration.
59853
   * @param error The error to report. Must be INCORRECT_TYPE, or NO_SUCH_FIELD.
59854
   * @param message An error message to report with the error.
59855
   */
59856
  simdjson_inline error_code optional_error(error_code error, const char *message) noexcept;
59857
59858
  /**
59859
   * Take an input in json containing max_len characters and attempt to copy it over to tmpbuf, a buffer with
59860
   * N bytes of capacity. It will return false if N is too small (smaller than max_len) of if it is zero.
59861
   * The buffer (tmpbuf) is padded with space characters.
59862
   */
59863
  simdjson_warn_unused simdjson_inline bool copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept;
59864
59865
  simdjson_inline token_position position() const noexcept;
59866
  /**
59867
   * Write the raw_json_string to the string buffer and return a string_view.
59868
   * Each raw_json_string should be unescaped once, or else the string buffer might
59869
   * overflow.
59870
   */
59871
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
59872
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
59873
59874
  simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
59875
59876
  simdjson_inline error_code consume_character(char c) noexcept;
59877
#if SIMDJSON_DEVELOPMENT_CHECKS
59878
  simdjson_inline token_position start_position(depth_t depth) const noexcept;
59879
  simdjson_inline void set_start_position(depth_t depth, token_position position) noexcept;
59880
#endif
59881
59882
  /* Useful for debugging and logging purposes. */
59883
  inline std::string to_string() const noexcept;
59884
59885
  /**
59886
   * Returns the current location in the document if in bounds.
59887
   */
59888
  inline simdjson_result<const char *> current_location() const noexcept;
59889
59890
  /**
59891
   * Updates this json iterator so that it is back at the beginning of the document,
59892
   * as if it had just been created.
59893
   */
59894
  inline void rewind() noexcept;
59895
  /**
59896
   * This checks whether the {,},[,] are balanced so that the document
59897
   * ends with proper zero depth. This requires scanning the whole document
59898
   * and it may be expensive. It is expected that it will be rarely called.
59899
   * It does not attempt to match { with } and [ with ].
59900
   */
59901
  inline bool balanced() const noexcept;
59902
protected:
59903
  simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
59904
  /// The last token before the end
59905
  simdjson_inline token_position last_position() const noexcept;
59906
  /// The token *at* the end. This points at gibberish and should only be used for comparison.
59907
  simdjson_inline token_position end_position() const noexcept;
59908
  /// The end of the buffer.
59909
  simdjson_inline token_position end() const noexcept;
59910
59911
  friend class document;
59912
  friend class document_stream;
59913
  friend class object;
59914
  friend class array;
59915
  friend class value;
59916
  friend class raw_json_string;
59917
  friend class parser;
59918
  friend class value_iterator;
59919
  friend class field;
59920
  template <typename... Args>
59921
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
59922
  template <typename... Args>
59923
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
59924
}; // json_iterator
59925
59926
} // namespace ondemand
59927
} // namespace icelake
59928
} // namespace simdjson
59929
59930
namespace simdjson {
59931
59932
template<>
59933
struct simdjson_result<icelake::ondemand::json_iterator> : public icelake::implementation_simdjson_result_base<icelake::ondemand::json_iterator> {
59934
public:
59935
  simdjson_inline simdjson_result(icelake::ondemand::json_iterator &&value) noexcept; ///< @private
59936
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
59937
59938
  simdjson_inline simdjson_result() noexcept = default;
59939
};
59940
59941
} // namespace simdjson
59942
59943
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
59944
/* end file simdjson/generic/ondemand/json_iterator.h for icelake */
59945
/* including simdjson/generic/ondemand/json_type.h for icelake: #include "simdjson/generic/ondemand/json_type.h" */
59946
/* begin file simdjson/generic/ondemand/json_type.h for icelake */
59947
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
59948
59949
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
59950
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H */
59951
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
59952
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
59953
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
59954
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
59955
59956
namespace simdjson {
59957
namespace icelake {
59958
namespace ondemand {
59959
59960
/**
59961
 * The type of a JSON value.
59962
 */
59963
enum class json_type {
59964
    // Start at 1 to catch uninitialized / default values more easily
59965
    array=1, ///< A JSON array   ( [ 1, 2, 3 ... ] )
59966
    object,  ///< A JSON object  ( { "a": 1, "b" 2, ... } )
59967
    number,  ///< A JSON number  ( 1 or -2.3 or 4.5e6 ...)
59968
    string,  ///< A JSON string  ( "a" or "hello world\n" ...)
59969
    boolean, ///< A JSON boolean (true or false)
59970
    null     ///< A JSON null    (null)
59971
};
59972
59973
/**
59974
 * A type representing a JSON number.
59975
 * The design of the struct is deliberately straight-forward. All
59976
 * functions return standard values with no error check.
59977
 */
59978
struct number {
59979
59980
  /**
59981
   * return the automatically determined type of
59982
   * the number: number_type::floating_point_number,
59983
   * number_type::signed_integer or number_type::unsigned_integer.
59984
   *
59985
   *    enum class number_type {
59986
   *        floating_point_number=1, /// a binary64 number
59987
   *        signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
59988
   *        unsigned_integer         /// a positive integer larger or equal to 1<<63
59989
   *    };
59990
   */
59991
  simdjson_inline ondemand::number_type get_number_type() const noexcept;
59992
  /**
59993
   * return true if the automatically determined type of
59994
   * the number is number_type::unsigned_integer.
59995
   */
59996
  simdjson_inline bool is_uint64() const noexcept;
59997
  /**
59998
   * return the value as a uint64_t, only valid if is_uint64() is true.
59999
   */
60000
  simdjson_inline uint64_t get_uint64() const noexcept;
60001
  simdjson_inline operator uint64_t() const noexcept;
60002
60003
  /**
60004
   * return true if the automatically determined type of
60005
   * the number is number_type::signed_integer.
60006
   */
60007
  simdjson_inline bool is_int64() const noexcept;
60008
  /**
60009
   * return the value as a int64_t, only valid if is_int64() is true.
60010
   */
60011
  simdjson_inline int64_t get_int64() const noexcept;
60012
  simdjson_inline operator int64_t() const noexcept;
60013
60014
60015
  /**
60016
   * return true if the automatically determined type of
60017
   * the number is number_type::floating_point_number.
60018
   */
60019
  simdjson_inline bool is_double() const noexcept;
60020
  /**
60021
   * return the value as a double, only valid if is_double() is true.
60022
   */
60023
  simdjson_inline double get_double() const noexcept;
60024
  simdjson_inline operator double() const noexcept;
60025
60026
  /**
60027
   * Convert the number to a double. Though it always succeed, the conversion
60028
   * may be lossy if the number cannot be represented exactly.
60029
   */
60030
  simdjson_inline double as_double() const noexcept;
60031
60032
60033
protected:
60034
  /**
60035
   * The next block of declaration is designed so that we can call the number parsing
60036
   * functions on a number type. They are protected and should never be used outside
60037
   * of the core simdjson library.
60038
   */
60039
  friend class value_iterator;
60040
  template<typename W>
60041
  friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
60042
  template<typename W>
60043
  friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
60044
  /** Store a signed 64-bit value to the number. */
60045
  simdjson_inline void append_s64(int64_t value) noexcept;
60046
  /** Store an unsigned 64-bit value to the number. */
60047
  simdjson_inline void append_u64(uint64_t value) noexcept;
60048
  /** Store a double value to the number. */
60049
  simdjson_inline void append_double(double value) noexcept;
60050
  /** Specifies that the value is a double, but leave it undefined. */
60051
  simdjson_inline void skip_double() noexcept;
60052
  /**
60053
   * End of friend declarations.
60054
   */
60055
60056
  /**
60057
   * Our attributes are a union type (size = 64 bits)
60058
   * followed by a type indicator.
60059
   */
60060
  union {
60061
    double floating_point_number;
60062
    int64_t signed_integer;
60063
    uint64_t unsigned_integer;
60064
  } payload{0};
60065
  number_type type{number_type::signed_integer};
60066
};
60067
60068
/**
60069
 * Write the JSON type to the output stream
60070
 *
60071
 * @param out The output stream.
60072
 * @param type The json_type.
60073
 */
60074
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
60075
60076
#if SIMDJSON_EXCEPTIONS
60077
/**
60078
 * Send JSON type to an output stream.
60079
 *
60080
 * @param out The output stream.
60081
 * @param type The json_type.
60082
 * @throw simdjson_error if the result being printed has an error. If there is an error with the
60083
 *        underlying output stream, that error will be propagated (simdjson_error will not be
60084
 *        thrown).
60085
 */
60086
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false);
60087
#endif
60088
60089
} // namespace ondemand
60090
} // namespace icelake
60091
} // namespace simdjson
60092
60093
namespace simdjson {
60094
60095
template<>
60096
struct simdjson_result<icelake::ondemand::json_type> : public icelake::implementation_simdjson_result_base<icelake::ondemand::json_type> {
60097
public:
60098
  simdjson_inline simdjson_result(icelake::ondemand::json_type &&value) noexcept; ///< @private
60099
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
60100
  simdjson_inline simdjson_result() noexcept = default;
60101
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
60102
};
60103
60104
} // namespace simdjson
60105
60106
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
60107
/* end file simdjson/generic/ondemand/json_type.h for icelake */
60108
/* including simdjson/generic/ondemand/raw_json_string.h for icelake: #include "simdjson/generic/ondemand/raw_json_string.h" */
60109
/* begin file simdjson/generic/ondemand/raw_json_string.h for icelake */
60110
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
60111
60112
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
60113
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H */
60114
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
60115
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
60116
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
60117
60118
namespace simdjson {
60119
namespace icelake {
60120
namespace ondemand {
60121
60122
/**
60123
 * A string escaped per JSON rules, terminated with quote ("). They are used to represent
60124
 * unescaped keys inside JSON documents.
60125
 *
60126
 * (In other words, a pointer to the beginning of a string, just after the start quote, inside a
60127
 * JSON file.)
60128
 *
60129
 * This class is deliberately simplistic and has little functionality. You can
60130
 * compare a raw_json_string instance with an unescaped C string, but
60131
 * that is nearly all you can do.
60132
 *
60133
 * The raw_json_string is unescaped. If you wish to write an unescaped version of it to your own
60134
 * buffer, you may do so using the parser.unescape(string, buff) method, using an ondemand::parser
60135
 * instance. Doing so requires you to have a sufficiently large buffer.
60136
 *
60137
 * The raw_json_string instances originate typically from field instance which in turn represent
60138
 * key-value pairs from object instances. From a field instance, you get the raw_json_string
60139
 * instance by calling key(). You can, if you want a more usable string_view instance, call
60140
 * the unescaped_key() method on the field instance. You may also create a raw_json_string from
60141
 * any other string value, with the value.get_raw_json_string() method. Again, you can get
60142
 * a more usable string_view instance by calling get_string().
60143
 *
60144
 */
60145
class raw_json_string {
60146
public:
60147
  /**
60148
   * Create a new invalid raw_json_string.
60149
   *
60150
   * Exists so you can declare a variable and later assign to it before use.
60151
   */
60152
  simdjson_inline raw_json_string() noexcept = default;
60153
60154
  /**
60155
   * Create a new invalid raw_json_string pointed at the given location in the JSON.
60156
   *
60157
   * The given location must be just *after* the beginning quote (") in the JSON file.
60158
   *
60159
   * It *must* be terminated by a ", and be a valid JSON string.
60160
   */
60161
  simdjson_inline raw_json_string(const uint8_t * _buf) noexcept;
60162
  /**
60163
   * Get the raw pointer to the beginning of the string in the JSON (just after the ").
60164
   *
60165
   * It is possible for this function to return a null pointer if the instance
60166
   * has outlived its existence.
60167
   */
60168
  simdjson_inline const char * raw() const noexcept;
60169
60170
  /**
60171
   * This compares the current instance to the std::string_view target: returns true if
60172
   * they are byte-by-byte equal (no escaping is done) on target.size() characters,
60173
   * and if the raw_json_string instance has a quote character at byte index target.size().
60174
   * We never read more than length + 1 bytes in the raw_json_string instance.
60175
   * If length is smaller than target.size(), this will return false.
60176
   *
60177
   * The std::string_view instance may contain any characters. However, the caller
60178
   * is responsible for setting length so that length bytes may be read in the
60179
   * raw_json_string.
60180
   *
60181
   * Performance: the comparison may be done using memcmp which may be efficient
60182
   * for long strings.
60183
   */
60184
  simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept;
60185
60186
  /**
60187
   * This compares the current instance to the std::string_view target: returns true if
60188
   * they are byte-by-byte equal (no escaping is done).
60189
   * The std::string_view instance should not contain unescaped quote characters:
60190
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
60191
   *
60192
   * Performance: the comparison is done byte-by-byte which might be inefficient for
60193
   * long strings.
60194
   *
60195
   * If target is a compile-time constant, and your compiler likes you,
60196
   * you should be able to do the following without performance penalty...
60197
   *
60198
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
60199
   *   s.unsafe_is_equal(target);
60200
   */
60201
  simdjson_inline bool unsafe_is_equal(std::string_view target) const noexcept;
60202
60203
  /**
60204
   * This compares the current instance to the C string target: returns true if
60205
   * they are byte-by-byte equal (no escaping is done).
60206
   * The provided C string should not contain an unescaped quote character:
60207
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
60208
   *
60209
   * If target is a compile-time constant, and your compiler likes you,
60210
   * you should be able to do the following without performance penalty...
60211
   *
60212
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
60213
   *   s.unsafe_is_equal(target);
60214
   */
60215
  simdjson_inline bool unsafe_is_equal(const char* target) const noexcept;
60216
60217
  /**
60218
   * This compares the current instance to the std::string_view target: returns true if
60219
   * they are byte-by-byte equal (no escaping is done).
60220
   */
60221
  simdjson_inline bool is_equal(std::string_view target) const noexcept;
60222
60223
  /**
60224
   * This compares the current instance to the C string target: returns true if
60225
   * they are byte-by-byte equal (no escaping is done).
60226
   */
60227
  simdjson_inline bool is_equal(const char* target) const noexcept;
60228
60229
  /**
60230
   * Returns true if target is free from unescaped quote. If target is known at
60231
   * compile-time, we might expect the computation to happen at compile time with
60232
   * many compilers (not all!).
60233
   */
60234
  static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
60235
  static simdjson_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
60236
60237
private:
60238
60239
60240
  /**
60241
   * This will set the inner pointer to zero, effectively making
60242
   * this instance unusable.
60243
   */
60244
  simdjson_inline void consume() noexcept { buf = nullptr; }
60245
60246
  /**
60247
   * Checks whether the inner pointer is non-null and thus usable.
60248
   */
60249
  simdjson_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
60250
60251
  /**
60252
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
60253
   * The result will be a valid UTF-8.
60254
   *
60255
   * ## IMPORTANT: string_view lifetime
60256
   *
60257
   * The string_view is only valid until the next parse() call on the parser.
60258
   *
60259
   * @param iter A json_iterator, which contains a buffer where the string will be written.
60260
   * @param allow_replacement Whether we allow replacement of invalid surrogate pairs.
60261
   */
60262
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(json_iterator &iter, bool allow_replacement) const noexcept;
60263
60264
  /**
60265
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
60266
   * The result may not be a valid UTF-8. https://simonsapin.github.io/wtf-8/
60267
   *
60268
   * ## IMPORTANT: string_view lifetime
60269
   *
60270
   * The string_view is only valid until the next parse() call on the parser.
60271
   *
60272
   * @param iter A json_iterator, which contains a buffer where the string will be written.
60273
   */
60274
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(json_iterator &iter) const noexcept;
60275
  const uint8_t * buf{};
60276
  friend class object;
60277
  friend class field;
60278
  friend class parser;
60279
  friend struct simdjson_result<raw_json_string>;
60280
};
60281
60282
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &, const raw_json_string &) noexcept;
60283
60284
/**
60285
 * Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user is responsible
60286
 * for providing a string with no unescaped quote. Note that unescaped quotes cannot be present in valid JSON strings.
60287
 */
60288
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept;
60289
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept;
60290
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept;
60291
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept;
60292
60293
60294
} // namespace ondemand
60295
} // namespace icelake
60296
} // namespace simdjson
60297
60298
namespace simdjson {
60299
60300
template<>
60301
struct simdjson_result<icelake::ondemand::raw_json_string> : public icelake::implementation_simdjson_result_base<icelake::ondemand::raw_json_string> {
60302
public:
60303
  simdjson_inline simdjson_result(icelake::ondemand::raw_json_string &&value) noexcept; ///< @private
60304
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
60305
  simdjson_inline simdjson_result() noexcept = default;
60306
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
60307
60308
  simdjson_inline simdjson_result<const char *> raw() const noexcept;
60309
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(icelake::ondemand::json_iterator &iter, bool allow_replacement) const noexcept;
60310
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(icelake::ondemand::json_iterator &iter) const noexcept;
60311
};
60312
60313
} // namespace simdjson
60314
60315
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
60316
/* end file simdjson/generic/ondemand/raw_json_string.h for icelake */
60317
/* including simdjson/generic/ondemand/parser.h for icelake: #include "simdjson/generic/ondemand/parser.h" */
60318
/* begin file simdjson/generic/ondemand/parser.h for icelake */
60319
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_H
60320
60321
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
60322
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_H */
60323
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
60324
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
60325
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
60326
60327
#include <memory>
60328
60329
namespace simdjson {
60330
namespace icelake {
60331
namespace ondemand {
60332
60333
/**
60334
 * The default batch size for document_stream instances for this On Demand kernel.
60335
 * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value
60336
 * in the future.
60337
 */
60338
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
60339
/**
60340
 * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
60341
 * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
60342
 * most users will want a much larger batch size.
60343
 *
60344
 * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
60345
 * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
60346
 */
60347
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
60348
60349
/**
60350
 * A JSON fragment iterator.
60351
 *
60352
 * This holds the actual iterator as well as the buffer for writing strings.
60353
 */
60354
class parser {
60355
public:
60356
  /**
60357
   * Create a JSON parser.
60358
   *
60359
   * The new parser will have zero capacity.
60360
   */
60361
  inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
60362
60363
  inline parser(parser &&other) noexcept = default;
60364
  simdjson_inline parser(const parser &other) = delete;
60365
  simdjson_inline parser &operator=(const parser &other) = delete;
60366
  simdjson_inline parser &operator=(parser &&other) noexcept = default;
60367
60368
  /** Deallocate the JSON parser. */
60369
  inline ~parser() noexcept = default;
60370
60371
  /**
60372
   * Start iterating an on-demand JSON document.
60373
   *
60374
   *   ondemand::parser parser;
60375
   *   document doc = parser.iterate(json);
60376
   *
60377
   * It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
60378
   * Otherwise the iterate method may return an error. In particular, the whole input should be
60379
   * valid: we do not attempt to tolerate incorrect content either before or after a JSON
60380
   * document. If there is a UTF-8 BOM, the parser skips it.
60381
   *
60382
   * ### IMPORTANT: Validate what you use
60383
   *
60384
   * Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
60385
   * iterate does not parse and validate the whole document.
60386
   *
60387
   * ### IMPORTANT: Buffer Lifetime
60388
   *
60389
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
60390
   * long as the document iteration.
60391
   *
60392
   * ### IMPORTANT: Document Lifetime
60393
   *
60394
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
60395
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
60396
   * you call parse() again or destroy the parser.
60397
   *
60398
   * ### REQUIRED: Buffer Padding
60399
   *
60400
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
60401
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
60402
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
60403
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
60404
   *
60405
   * @param json The JSON to parse.
60406
   * @param len The length of the JSON.
60407
   * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
60408
   *
60409
   * @return The document, or an error:
60410
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
60411
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
60412
   *           allocation fails.
60413
   *         - EMPTY if the document is all whitespace.
60414
   *         - UTF8_ERROR if the document is not valid UTF-8.
60415
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
60416
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
60417
   */
60418
  simdjson_warn_unused simdjson_result<document> iterate(padded_string_view json) & noexcept;
60419
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60420
  simdjson_warn_unused simdjson_result<document> iterate(const char *json, size_t len, size_t capacity) & noexcept;
60421
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60422
  simdjson_warn_unused simdjson_result<document> iterate(const uint8_t *json, size_t len, size_t capacity) & noexcept;
60423
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60424
  simdjson_warn_unused simdjson_result<document> iterate(std::string_view json, size_t capacity) & noexcept;
60425
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60426
  simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
60427
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60428
  simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
60429
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60430
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
60431
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60432
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
60433
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
60434
  simdjson_warn_unused simdjson_result<document> iterate(padded_string &&json) & noexcept = delete;
60435
60436
  /**
60437
   * @private
60438
   *
60439
   * Start iterating an on-demand JSON document.
60440
   *
60441
   *   ondemand::parser parser;
60442
   *   json_iterator doc = parser.iterate(json);
60443
   *
60444
   * ### IMPORTANT: Buffer Lifetime
60445
   *
60446
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
60447
   * long as the document iteration.
60448
   *
60449
   * ### IMPORTANT: Document Lifetime
60450
   *
60451
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
60452
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
60453
   * you call parse() again or destroy the parser.
60454
   *
60455
   * The ondemand::document instance holds the iterator. The document must remain in scope
60456
   * while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
60457
   *
60458
   * ### REQUIRED: Buffer Padding
60459
   *
60460
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
60461
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
60462
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
60463
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
60464
   *
60465
   * @param json The JSON to parse.
60466
   *
60467
   * @return The iterator, or an error:
60468
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
60469
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
60470
   *           allocation fails.
60471
   *         - EMPTY if the document is all whitespace.
60472
   *         - UTF8_ERROR if the document is not valid UTF-8.
60473
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
60474
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
60475
   */
60476
  simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
60477
60478
60479
  /**
60480
   * Parse a buffer containing many JSON documents.
60481
   *
60482
   *   auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
60483
   *   ondemand::parser parser;
60484
   *   ondemand::document_stream docs = parser.iterate_many(json);
60485
   *   for (auto & doc : docs) {
60486
   *     std::cout << doc["foo"] << std::endl;
60487
   *   }
60488
   *   // Prints 1 2 3
60489
   *
60490
   * No copy of the input buffer is made.
60491
   *
60492
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
60493
   *
60494
   * The caller is responsabile to ensure that the input string data remains unchanged and is
60495
   * not deleted during the loop.
60496
   *
60497
   * ### Format
60498
   *
60499
   * The buffer must contain a series of one or more JSON documents, concatenated into a single
60500
   * buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
60501
   * then starts parsing the next document at that point. (It does this with more parallelism and
60502
   * lookahead than you might think, though.)
60503
   *
60504
   * documents that consist of an object or array may omit the whitespace between them, concatenating
60505
   * with no separator. Documents that consist of a single primitive (i.e. documents that are not
60506
   * arrays or objects) MUST be separated with ASCII whitespace.
60507
   *
60508
   * The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
60509
   * If there is a UTF-8 BOM, the parser skips it.
60510
   *
60511
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
60512
   * Setting batch_size to excessively large or excessively small values may impact negatively the
60513
   * performance.
60514
   *
60515
   * ### REQUIRED: Buffer Padding
60516
   *
60517
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
60518
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
60519
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
60520
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
60521
   *
60522
   * ### Threads
60523
   *
60524
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
60525
   * hood to do some lookahead.
60526
   *
60527
   * ### Parser Capacity
60528
   *
60529
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
60530
   * to handle it (up to max_capacity).
60531
   *
60532
   * @param buf The concatenated JSON to parse.
60533
   * @param len The length of the concatenated JSON.
60534
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
60535
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
60536
   *                   parse as many documents as possible in one tight loop.
60537
   *                   Defaults to 10MB, which has been a reasonable sweet spot in our tests.
60538
   * @param allow_comma_separated (defaults on false) This allows a mode where the documents are
60539
   *                   separated by commas instead of whitespace. It comes with a performance
60540
   *                   penalty because the entire document is indexed at once (and the document must be
60541
   *                   less than 4 GB), and there is no multithreading. In this mode, the batch_size parameter
60542
   *                   is effectively ignored, as it is set to at least the document size.
60543
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
60544
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails
60545
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
60546
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
60547
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
60548
   */
60549
  inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
60550
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
60551
  inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
60552
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
60553
  inline simdjson_result<document_stream> iterate_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
60554
  inline simdjson_result<document_stream> iterate_many(const std::string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
60555
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
60556
  inline simdjson_result<document_stream> iterate_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
60557
  inline simdjson_result<document_stream> iterate_many(const padded_string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
60558
60559
  /** @private We do not want to allow implicit conversion from C string to std::string. */
60560
  simdjson_result<document_stream> iterate_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
60561
60562
  /** The capacity of this parser (the largest document it can process). */
60563
  simdjson_inline size_t capacity() const noexcept;
60564
  /** The maximum capacity of this parser (the largest document it is allowed to process). */
60565
  simdjson_inline size_t max_capacity() const noexcept;
60566
  simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
60567
  /**
60568
   * The maximum depth of this parser (the most deeply nested objects and arrays it can process).
60569
   * This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
60570
   * The document's instance current_depth() method should be used to monitor the parsing
60571
   * depth and limit it if desired.
60572
   */
60573
  simdjson_inline size_t max_depth() const noexcept;
60574
60575
  /**
60576
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
60577
   * and `max_depth` depth.
60578
   *
60579
   * The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
60580
   * The document's instance current_depth() method should be used to monitor the parsing
60581
   * depth and limit it if desired.
60582
   *
60583
   * @param capacity The new capacity.
60584
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
60585
   * @return The error, if there is one.
60586
   */
60587
  simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
60588
60589
  #ifdef SIMDJSON_THREADS_ENABLED
60590
  /**
60591
   * The parser instance can use threads when they are available to speed up some
60592
   * operations. It is enabled by default. Changing this attribute will change the
60593
   * behavior of the parser for future operations.
60594
   */
60595
  bool threaded{true};
60596
  #endif
60597
60598
  /**
60599
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
60600
   * The result must be valid UTF-8.
60601
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
60602
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
60603
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
60604
   *
60605
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
60606
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
60607
   * instead of get_raw_json_string()).
60608
   *
60609
   * ## IMPORTANT: string_view lifetime
60610
   *
60611
   * The string_view is only valid as long as the bytes in dst.
60612
   *
60613
   * @param raw_json_string input
60614
   * @param dst A pointer to a buffer at least large enough to write this string as well as
60615
   *            an additional SIMDJSON_PADDING bytes.
60616
   * @param allow_replacement Whether we allow a replacement if the input string contains unmatched surrogate pairs.
60617
   * @return A string_view pointing at the unescaped string in dst
60618
   * @error STRING_ERROR if escapes are incorrect.
60619
   */
60620
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement = false) const noexcept;
60621
60622
  /**
60623
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
60624
   * The result may not be valid UTF-8. See https://simonsapin.github.io/wtf-8/
60625
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
60626
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
60627
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
60628
   *
60629
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
60630
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
60631
   * instead of get_raw_json_string()).
60632
   *
60633
   * ## IMPORTANT: string_view lifetime
60634
   *
60635
   * The string_view is only valid as long as the bytes in dst.
60636
   *
60637
   * @param raw_json_string input
60638
   * @param dst A pointer to a buffer at least large enough to write this string as well as
60639
   *            an additional SIMDJSON_PADDING bytes.
60640
   * @return A string_view pointing at the unescaped string in dst
60641
   * @error STRING_ERROR if escapes are incorrect.
60642
   */
60643
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept;
60644
60645
private:
60646
  /** @private [for benchmarking access] The implementation to use */
60647
  std::unique_ptr<internal::dom_parser_implementation> implementation{};
60648
  size_t _capacity{0};
60649
  size_t _max_capacity;
60650
  size_t _max_depth{DEFAULT_MAX_DEPTH};
60651
  std::unique_ptr<uint8_t[]> string_buf{};
60652
#if SIMDJSON_DEVELOPMENT_CHECKS
60653
  std::unique_ptr<token_position[]> start_positions{};
60654
#endif
60655
60656
  friend class json_iterator;
60657
  friend class document_stream;
60658
};
60659
60660
} // namespace ondemand
60661
} // namespace icelake
60662
} // namespace simdjson
60663
60664
namespace simdjson {
60665
60666
template<>
60667
struct simdjson_result<icelake::ondemand::parser> : public icelake::implementation_simdjson_result_base<icelake::ondemand::parser> {
60668
public:
60669
  simdjson_inline simdjson_result(icelake::ondemand::parser &&value) noexcept; ///< @private
60670
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
60671
  simdjson_inline simdjson_result() noexcept = default;
60672
};
60673
60674
} // namespace simdjson
60675
60676
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_H
60677
/* end file simdjson/generic/ondemand/parser.h for icelake */
60678
60679
// All other declarations
60680
/* including simdjson/generic/ondemand/array.h for icelake: #include "simdjson/generic/ondemand/array.h" */
60681
/* begin file simdjson/generic/ondemand/array.h for icelake */
60682
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
60683
60684
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
60685
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H */
60686
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
60687
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
60688
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
60689
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
60690
60691
namespace simdjson {
60692
namespace icelake {
60693
namespace ondemand {
60694
60695
/**
60696
 * A forward-only JSON array.
60697
 */
60698
class array {
60699
public:
60700
  /**
60701
   * Create a new invalid array.
60702
   *
60703
   * Exists so you can declare a variable and later assign to it before use.
60704
   */
60705
  simdjson_inline array() noexcept = default;
60706
60707
  /**
60708
   * Begin array iteration.
60709
   *
60710
   * Part of the std::iterable interface.
60711
   */
60712
  simdjson_inline simdjson_result<array_iterator> begin() noexcept;
60713
  /**
60714
   * Sentinel representing the end of the array.
60715
   *
60716
   * Part of the std::iterable interface.
60717
   */
60718
  simdjson_inline simdjson_result<array_iterator> end() noexcept;
60719
  /**
60720
   * This method scans the array and counts the number of elements.
60721
   * The count_elements method should always be called before you have begun
60722
   * iterating through the array: it is expected that you are pointing at
60723
   * the beginning of the array.
60724
   * The runtime complexity is linear in the size of the array. After
60725
   * calling this function, if successful, the array is 'rewinded' at its
60726
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
60727
   * there is a missing comma), then an error is returned and it is no longer
60728
   * safe to continue.
60729
   *
60730
   * To check that an array is empty, it is more performant to use
60731
   * the is_empty() method.
60732
   */
60733
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
60734
  /**
60735
   * This method scans the beginning of the array and checks whether the
60736
   * array is empty.
60737
   * The runtime complexity is constant time. After
60738
   * calling this function, if successful, the array is 'rewinded' at its
60739
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
60740
   * there is a missing comma), then an error is returned and it is no longer
60741
   * safe to continue.
60742
   */
60743
  simdjson_inline simdjson_result<bool> is_empty() & noexcept;
60744
  /**
60745
   * Reset the iterator so that we are pointing back at the
60746
   * beginning of the array. You should still consume values only once even if you
60747
   * can iterate through the array more than once. If you unescape a string
60748
   * within the array more than once, you have unsafe code. Note that rewinding
60749
   * an array means that you may need to reparse it anew: it is not a free
60750
   * operation.
60751
   *
60752
   * @returns true if the array contains some elements (not empty)
60753
   */
60754
  inline simdjson_result<bool> reset() & noexcept;
60755
  /**
60756
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
60757
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
60758
   * as the root of its own JSON document.
60759
   *
60760
   *   ondemand::parser parser;
60761
   *   auto json = R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded;
60762
   *   auto doc = parser.iterate(json);
60763
   *   doc.at_pointer("/0/foo/a/1") == 20
60764
   *
60765
   * Note that at_pointer() called on the document automatically calls the document's rewind
60766
   * method between each call. It invalidates all previously accessed arrays, objects and values
60767
   * that have not been consumed. Yet it is not the case when calling at_pointer on an array
60768
   * instance: there is no rewind and no invalidation.
60769
   *
60770
   * You may only call at_pointer on an array after it has been created, but before it has
60771
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
60772
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
60773
   * to call at_pointer on the same array.
60774
   *
60775
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
60776
   *
60777
   * @return The value associated with the given JSON pointer, or:
60778
   *         - NO_SUCH_FIELD if a field does not exist in an object
60779
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
60780
   *         - INCORRECT_TYPE if a non-integer is used to access an array
60781
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
60782
   */
60783
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
60784
60785
  /**
60786
   * Get the value associated with the given JSONPath expression. We only support
60787
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
60788
   * names and array indices.
60789
   *
60790
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
60791
   *
60792
   * @return The value associated with the given JSONPath expression, or:
60793
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
60794
   *         - NO_SUCH_FIELD if a field does not exist in an object
60795
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
60796
   *         - INCORRECT_TYPE if a non-integer is used to access an array
60797
  */
60798
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
60799
60800
  /**
60801
   * Consumes the array and returns a string_view instance corresponding to the
60802
   * array as represented in JSON. It points inside the original document.
60803
   */
60804
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
60805
60806
  /**
60807
   * Get the value at the given index. This function has linear-time complexity.
60808
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
60809
   *
60810
   * @return The value at the given index, or:
60811
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
60812
   */
60813
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
60814
protected:
60815
  /**
60816
   * Go to the end of the array, no matter where you are right now.
60817
   */
60818
  simdjson_inline error_code consume() noexcept;
60819
60820
  /**
60821
   * Begin array iteration.
60822
   *
60823
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
60824
   *        resulting array.
60825
   * @error INCORRECT_TYPE if the iterator is not at [.
60826
   */
60827
  static simdjson_inline simdjson_result<array> start(value_iterator &iter) noexcept;
60828
  /**
60829
   * Begin array iteration from the root.
60830
   *
60831
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
60832
   *        resulting array.
60833
   * @error INCORRECT_TYPE if the iterator is not at [.
60834
   * @error TAPE_ERROR if there is no closing ] at the end of the document.
60835
   */
60836
  static simdjson_inline simdjson_result<array> start_root(value_iterator &iter) noexcept;
60837
  /**
60838
   * Begin array iteration.
60839
   *
60840
   * This version of the method should be called after the initial [ has been verified, and is
60841
   * intended for use by switch statements that check the type of a value.
60842
   *
60843
   * @param iter The iterator. Must be after the initial [. Will be *moved* into the resulting array.
60844
   */
60845
  static simdjson_inline simdjson_result<array> started(value_iterator &iter) noexcept;
60846
60847
  /**
60848
   * Create an array at the given Internal array creation. Call array::start() or array::started() instead of this.
60849
   *
60850
   * @param iter The iterator. Must either be at the start of the first element with iter.is_alive()
60851
   *        == true, or past the [] with is_alive() == false if the array is empty. Will be *moved*
60852
   *        into the resulting array.
60853
   */
60854
  simdjson_inline array(const value_iterator &iter) noexcept;
60855
60856
  /**
60857
   * Iterator marking current position.
60858
   *
60859
   * iter.is_alive() == false indicates iteration is complete.
60860
   */
60861
  value_iterator iter{};
60862
60863
  friend class value;
60864
  friend class document;
60865
  friend struct simdjson_result<value>;
60866
  friend struct simdjson_result<array>;
60867
  friend class array_iterator;
60868
};
60869
60870
} // namespace ondemand
60871
} // namespace icelake
60872
} // namespace simdjson
60873
60874
namespace simdjson {
60875
60876
template<>
60877
struct simdjson_result<icelake::ondemand::array> : public icelake::implementation_simdjson_result_base<icelake::ondemand::array> {
60878
public:
60879
  simdjson_inline simdjson_result(icelake::ondemand::array &&value) noexcept; ///< @private
60880
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
60881
  simdjson_inline simdjson_result() noexcept = default;
60882
60883
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> begin() noexcept;
60884
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> end() noexcept;
60885
  inline simdjson_result<size_t> count_elements() & noexcept;
60886
  inline simdjson_result<bool> is_empty() & noexcept;
60887
  inline simdjson_result<bool> reset() & noexcept;
60888
  simdjson_inline simdjson_result<icelake::ondemand::value> at(size_t index) noexcept;
60889
  simdjson_inline simdjson_result<icelake::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
60890
  simdjson_inline simdjson_result<icelake::ondemand::value> at_path(std::string_view json_path) noexcept;
60891
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
60892
60893
};
60894
60895
} // namespace simdjson
60896
60897
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
60898
/* end file simdjson/generic/ondemand/array.h for icelake */
60899
/* including simdjson/generic/ondemand/array_iterator.h for icelake: #include "simdjson/generic/ondemand/array_iterator.h" */
60900
/* begin file simdjson/generic/ondemand/array_iterator.h for icelake */
60901
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
60902
60903
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
60904
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H */
60905
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
60906
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
60907
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
60908
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
60909
60910
60911
namespace simdjson {
60912
namespace icelake {
60913
namespace ondemand {
60914
60915
/**
60916
 * A forward-only JSON array.
60917
 *
60918
 * This is an input_iterator, meaning:
60919
 * - It is forward-only
60920
 * - * must be called exactly once per element.
60921
 * - ++ must be called exactly once in between each * (*, ++, *, ++, * ...)
60922
 */
60923
class array_iterator {
60924
public:
60925
  /** Create a new, invalid array iterator. */
60926
  simdjson_inline array_iterator() noexcept = default;
60927
60928
  //
60929
  // Iterator interface
60930
  //
60931
60932
  /**
60933
   * Get the current element.
60934
   *
60935
   * Part of the std::iterator interface.
60936
   */
60937
  simdjson_inline simdjson_result<value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
60938
  /**
60939
   * Check if we are at the end of the JSON.
60940
   *
60941
   * Part of the std::iterator interface.
60942
   *
60943
   * @return true if there are no more elements in the JSON array.
60944
   */
60945
  simdjson_inline bool operator==(const array_iterator &) const noexcept;
60946
  /**
60947
   * Check if there are more elements in the JSON array.
60948
   *
60949
   * Part of the std::iterator interface.
60950
   *
60951
   * @return true if there are more elements in the JSON array.
60952
   */
60953
  simdjson_inline bool operator!=(const array_iterator &) const noexcept;
60954
  /**
60955
   * Move to the next element.
60956
   *
60957
   * Part of the std::iterator interface.
60958
   */
60959
  simdjson_inline array_iterator &operator++() noexcept;
60960
60961
private:
60962
  value_iterator iter{};
60963
60964
  simdjson_inline array_iterator(const value_iterator &iter) noexcept;
60965
60966
  friend class array;
60967
  friend class value;
60968
  friend struct simdjson_result<array_iterator>;
60969
};
60970
60971
} // namespace ondemand
60972
} // namespace icelake
60973
} // namespace simdjson
60974
60975
namespace simdjson {
60976
60977
template<>
60978
struct simdjson_result<icelake::ondemand::array_iterator> : public icelake::implementation_simdjson_result_base<icelake::ondemand::array_iterator> {
60979
public:
60980
  simdjson_inline simdjson_result(icelake::ondemand::array_iterator &&value) noexcept; ///< @private
60981
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
60982
  simdjson_inline simdjson_result() noexcept = default;
60983
60984
  //
60985
  // Iterator interface
60986
  //
60987
60988
  simdjson_inline simdjson_result<icelake::ondemand::value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
60989
  simdjson_inline bool operator==(const simdjson_result<icelake::ondemand::array_iterator> &) const noexcept;
60990
  simdjson_inline bool operator!=(const simdjson_result<icelake::ondemand::array_iterator> &) const noexcept;
60991
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> &operator++() noexcept;
60992
};
60993
60994
} // namespace simdjson
60995
60996
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
60997
/* end file simdjson/generic/ondemand/array_iterator.h for icelake */
60998
/* including simdjson/generic/ondemand/document.h for icelake: #include "simdjson/generic/ondemand/document.h" */
60999
/* begin file simdjson/generic/ondemand/document.h for icelake */
61000
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
61001
61002
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
61003
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */
61004
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
61005
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
61006
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
61007
61008
namespace simdjson {
61009
namespace icelake {
61010
namespace ondemand {
61011
61012
/**
61013
 * A JSON document. It holds a json_iterator instance.
61014
 *
61015
 * Used by tokens to get text, and string buffer location.
61016
 *
61017
 * You must keep the document around during iteration.
61018
 */
61019
class document {
61020
public:
61021
  /**
61022
   * Create a new invalid document.
61023
   *
61024
   * Exists so you can declare a variable and later assign to it before use.
61025
   */
61026
  simdjson_inline document() noexcept = default;
61027
  simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
61028
  simdjson_inline document(document &&other) noexcept = default;
61029
  simdjson_inline document &operator=(const document &other) noexcept = delete;
61030
  simdjson_inline document &operator=(document &&other) noexcept = default;
61031
61032
  /**
61033
   * Cast this JSON value to an array.
61034
   *
61035
   * @returns An object that can be used to iterate the array.
61036
   * @returns INCORRECT_TYPE If the JSON value is not an array.
61037
   */
61038
  simdjson_inline simdjson_result<array> get_array() & noexcept;
61039
  /**
61040
   * Cast this JSON value to an object.
61041
   *
61042
   * @returns An object that can be used to look up or iterate fields.
61043
   * @returns INCORRECT_TYPE If the JSON value is not an object.
61044
   */
61045
  simdjson_inline simdjson_result<object> get_object() & noexcept;
61046
  /**
61047
   * Cast this JSON value to an unsigned integer.
61048
   *
61049
   * @returns A signed 64-bit integer.
61050
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
61051
   */
61052
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
61053
  /**
61054
   * Cast this JSON value (inside string) to an unsigned integer.
61055
   *
61056
   * @returns A signed 64-bit integer.
61057
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
61058
   */
61059
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
61060
  /**
61061
   * Cast this JSON value to a signed integer.
61062
   *
61063
   * @returns A signed 64-bit integer.
61064
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
61065
   */
61066
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
61067
  /**
61068
   * Cast this JSON value (inside string) to a signed integer.
61069
   *
61070
   * @returns A signed 64-bit integer.
61071
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
61072
   */
61073
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
61074
  /**
61075
   * Cast this JSON value to a double.
61076
   *
61077
   * @returns A double.
61078
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
61079
   */
61080
  simdjson_inline simdjson_result<double> get_double() noexcept;
61081
61082
  /**
61083
   * Cast this JSON value (inside string) to a double.
61084
   *
61085
   * @returns A double.
61086
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
61087
   */
61088
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
61089
  /**
61090
   * Cast this JSON value to a string.
61091
   *
61092
   * The string is guaranteed to be valid UTF-8.
61093
   *
61094
   * Important: Calling get_string() twice on the same document is an error.
61095
   *
61096
   * @param Whether to allow a replacement character for unmatched surrogate pairs.
61097
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
61098
   *          time it parses a document or when it is destroyed.
61099
   * @returns INCORRECT_TYPE if the JSON value is not a string.
61100
   */
61101
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
61102
  /**
61103
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
61104
   *
61105
   * The string is guaranteed to be valid UTF-8.
61106
   *
61107
   * Important: a value should be consumed once. Calling get_string() twice on the same value
61108
   * is an error.
61109
   *
61110
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
61111
   * We recommend you avoid allocating an std::string unless you need to.
61112
   *
61113
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
61114
   */
61115
  template <typename string_type>
61116
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
61117
  /**
61118
   * Cast this JSON value to a string.
61119
   *
61120
   * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/
61121
   *
61122
   * Important: Calling get_wobbly_string() twice on the same document is an error.
61123
   *
61124
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
61125
   *          time it parses a document or when it is destroyed.
61126
   * @returns INCORRECT_TYPE if the JSON value is not a string.
61127
   */
61128
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
61129
  /**
61130
   * Cast this JSON value to a raw_json_string.
61131
   *
61132
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
61133
   *
61134
   * @returns A pointer to the raw JSON for the given string.
61135
   * @returns INCORRECT_TYPE if the JSON value is not a string.
61136
   */
61137
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
61138
  /**
61139
   * Cast this JSON value to a bool.
61140
   *
61141
   * @returns A bool value.
61142
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
61143
   */
61144
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
61145
  /**
61146
   * Cast this JSON value to a value when the document is an object or an array.
61147
   *
61148
   * You must not have begun iterating through the object or array. When
61149
   * SIMDJSON_DEVELOPMENT_CHECKS is set to 1 (which is the case when building in Debug mode
61150
   * by default), and you have already begun iterating,
61151
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
61152
   * rewind() to reset the document to its initial state before calling this method.
61153
   *
61154
   * @returns A value if a JSON array or object cannot be found.
61155
   * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
61156
   */
61157
  simdjson_inline simdjson_result<value> get_value() noexcept;
61158
61159
  /**
61160
   * Checks if this JSON value is null.  If and only if the value is
61161
   * null, then it is consumed (we advance). If we find a token that
61162
   * begins with 'n' but is not 'null', then an error is returned.
61163
   *
61164
   * @returns Whether the value is null.
61165
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
61166
   */
61167
  simdjson_inline simdjson_result<bool> is_null() noexcept;
61168
61169
  /**
61170
   * Get this value as the given type.
61171
   *
61172
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
61173
   *
61174
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
61175
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
61176
   *
61177
   * @returns A value of the given type, parsed from the JSON.
61178
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
61179
   */
61180
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
61181
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
61182
    // immediately fail.
61183
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
61184
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
61185
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
61186
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
61187
      " You may also add support for custom types, see our documentation.");
61188
  }
61189
  /** @overload template<typename T> simdjson_result<T> get() & noexcept */
61190
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
61191
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
61192
    // immediately fail.
61193
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
61194
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
61195
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
61196
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
61197
      " You may also add support for custom types, see our documentation.");
61198
  }
61199
61200
  /**
61201
   * Get this value as the given type.
61202
   *
61203
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
61204
   *
61205
   * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
61206
   *
61207
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
61208
   * @returns INCORRECT_TYPE If the JSON value is not an object.
61209
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
61210
   */
61211
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
61212
  /** @overload template<typename T> error_code get(T &out) & noexcept */
61213
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
61214
61215
#if SIMDJSON_EXCEPTIONS
61216
  /**
61217
   * Cast this JSON value to an instance of type T. The programmer is responsible for
61218
   * providing an implementation of get<T> for the type T, if T is not one of the types
61219
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.)
61220
   *
61221
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
61222
   *
61223
   * @returns An instance of type T
61224
   */
61225
  template <class T>
61226
  explicit simdjson_inline operator T() noexcept(false);
61227
  /**
61228
   * Cast this JSON value to an array.
61229
   *
61230
   * @returns An object that can be used to iterate the array.
61231
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
61232
   */
61233
  simdjson_inline operator array() & noexcept(false);
61234
  /**
61235
   * Cast this JSON value to an object.
61236
   *
61237
   * @returns An object that can be used to look up or iterate fields.
61238
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
61239
   */
61240
  simdjson_inline operator object() & noexcept(false);
61241
  /**
61242
   * Cast this JSON value to an unsigned integer.
61243
   *
61244
   * @returns A signed 64-bit integer.
61245
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
61246
   */
61247
  simdjson_inline operator uint64_t() noexcept(false);
61248
  /**
61249
   * Cast this JSON value to a signed integer.
61250
   *
61251
   * @returns A signed 64-bit integer.
61252
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
61253
   */
61254
  simdjson_inline operator int64_t() noexcept(false);
61255
  /**
61256
   * Cast this JSON value to a double.
61257
   *
61258
   * @returns A double.
61259
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
61260
   */
61261
  simdjson_inline operator double() noexcept(false);
61262
  /**
61263
   * Cast this JSON value to a string.
61264
   *
61265
   * The string is guaranteed to be valid UTF-8.
61266
   *
61267
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
61268
   *          time it parses a document or when it is destroyed.
61269
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
61270
   */
61271
  simdjson_inline operator std::string_view() noexcept(false);
61272
  /**
61273
   * Cast this JSON value to a raw_json_string.
61274
   *
61275
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
61276
   *
61277
   * @returns A pointer to the raw JSON for the given string.
61278
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
61279
   */
61280
  simdjson_inline operator raw_json_string() noexcept(false);
61281
  /**
61282
   * Cast this JSON value to a bool.
61283
   *
61284
   * @returns A bool value.
61285
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
61286
   */
61287
  simdjson_inline operator bool() noexcept(false);
61288
  /**
61289
   * Cast this JSON value to a value when the document is an object or an array.
61290
   *
61291
   * You must not have begun iterating through the object or array. When
61292
   * SIMDJSON_DEVELOPMENT_CHECKS is defined, and you have already begun iterating,
61293
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
61294
   * rewind() to reset the document to its initial state before calling this method.
61295
   *
61296
   * @returns A value value if a JSON array or object cannot be found.
61297
   * @exception SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
61298
   */
61299
  simdjson_inline operator value() noexcept(false);
61300
#endif
61301
  /**
61302
   * This method scans the array and counts the number of elements.
61303
   * The count_elements method should always be called before you have begun
61304
   * iterating through the array: it is expected that you are pointing at
61305
   * the beginning of the array.
61306
   * The runtime complexity is linear in the size of the array. After
61307
   * calling this function, if successful, the array is 'rewinded' at its
61308
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
61309
   * there is a missing comma), then an error is returned and it is no longer
61310
   * safe to continue.
61311
   */
61312
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
61313
   /**
61314
   * This method scans the object and counts the number of key-value pairs.
61315
   * The count_fields method should always be called before you have begun
61316
   * iterating through the object: it is expected that you are pointing at
61317
   * the beginning of the object.
61318
   * The runtime complexity is linear in the size of the object. After
61319
   * calling this function, if successful, the object is 'rewinded' at its
61320
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
61321
   * there is a missing comma), then an error is returned and it is no longer
61322
   * safe to continue.
61323
   *
61324
   * To check that an object is empty, it is more performant to use
61325
   * the is_empty() method.
61326
   */
61327
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
61328
  /**
61329
   * Get the value at the given index in the array. This function has linear-time complexity.
61330
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
61331
   *
61332
   * @return The value at the given index, or:
61333
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
61334
   */
61335
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
61336
  /**
61337
   * Begin array iteration.
61338
   *
61339
   * Part of the std::iterable interface.
61340
   */
61341
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
61342
  /**
61343
   * Sentinel representing the end of the array.
61344
   *
61345
   * Part of the std::iterable interface.
61346
   */
61347
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
61348
61349
  /**
61350
   * Look up a field by name on an object (order-sensitive).
61351
   *
61352
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
61353
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
61354
   *
61355
   * ```c++
61356
   * simdjson::ondemand::parser parser;
61357
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
61358
   * double z = obj.find_field("z");
61359
   * double y = obj.find_field("y");
61360
   * double x = obj.find_field("x");
61361
   * ```
61362
   *
61363
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
61364
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
61365
   *
61366
   *
61367
   * You must consume the fields on an object one at a time. A request for a new key
61368
   * invalidates previous field values: it makes them unsafe. E.g., the array
61369
   * given by content["bids"].get_array() should not be accessed after you have called
61370
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
61371
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
61372
   * OUT_OF_ORDER_ITERATION error is generated.
61373
   *
61374
   * You are expected to access keys only once. You should access the value corresponding to
61375
   * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
61376
   * is an error.
61377
   *
61378
   * @param key The key to look up.
61379
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
61380
   */
61381
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
61382
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
61383
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
61384
61385
  /**
61386
   * Look up a field by name on an object, without regard to key order.
61387
   *
61388
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
61389
   * and often appears negligible. It starts out normally, starting out at the last field; but if
61390
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
61391
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
61392
   * in question is large. The fact that the extra code is there also bumps the executable size.
61393
   *
61394
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
61395
   * default behavior failed to look up a field just because it was in the wrong order--and many
61396
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
61397
   *
61398
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
61399
   * field was not there when they are not in order).
61400
   *
61401
   * You must consume the fields on an object one at a time. A request for a new key
61402
   * invalidates previous field values: it makes them unsafe. E.g., the array
61403
   * given by content["bids"].get_array() should not be accessed after you have called
61404
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
61405
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
61406
   * OUT_OF_ORDER_ITERATION error is generated.
61407
   *
61408
   * You are expected to access keys only once. You should access the value corresponding to a key
61409
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
61410
   * is an error.
61411
   *
61412
   * @param key The key to look up.
61413
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
61414
   */
61415
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
61416
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
61417
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
61418
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
61419
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
61420
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
61421
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
61422
61423
  /**
61424
   * Get the type of this JSON value. It does not validate or consume the value.
61425
   * E.g., you must still call "is_null()" to check that a value is null even if
61426
   * "type()" returns json_type::null.
61427
   *
61428
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
61429
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
61430
   * let it throw an exception).
61431
   *
61432
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
61433
   */
61434
  simdjson_inline simdjson_result<json_type> type() noexcept;
61435
61436
  /**
61437
   * Checks whether the document is a scalar (string, number, null, Boolean).
61438
   * Returns false when there it is an array or object.
61439
   *
61440
   * @returns true if the type is string, number, null, Boolean
61441
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
61442
   */
61443
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
61444
61445
  /**
61446
   * Checks whether the document is a string.
61447
   *
61448
   * @returns true if the type is string
61449
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
61450
   */
61451
  simdjson_inline simdjson_result<bool> is_string() noexcept;
61452
61453
  /**
61454
   * Checks whether the document is a negative number.
61455
   *
61456
   * @returns true if the number if negative.
61457
   */
61458
  simdjson_inline bool is_negative() noexcept;
61459
  /**
61460
   * Checks whether the document is an integer number. Note that
61461
   * this requires to partially parse the number string. If
61462
   * the value is determined to be an integer, it may still
61463
   * not parse properly as an integer in subsequent steps
61464
   * (e.g., it might overflow).
61465
   *
61466
   * @returns true if the number if negative.
61467
   */
61468
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
61469
  /**
61470
   * Determine the number type (integer or floating-point number) as quickly
61471
   * as possible. This function does not fully validate the input. It is
61472
   * useful when you only need to classify the numbers, without parsing them.
61473
   *
61474
   * If you are planning to retrieve the value or you need full validation,
61475
   * consider using the get_number() method instead: it will fully parse
61476
   * and validate the input, and give you access to the type:
61477
   * get_number().get_number_type().
61478
   *
61479
   * get_number_type() is number_type::unsigned_integer if we have
61480
   * an integer greater or equal to 9223372036854775808 and no larger than 18446744073709551615.
61481
   * get_number_type() is number_type::signed_integer if we have an
61482
   * integer that is less than 9223372036854775808 and greater or equal to -9223372036854775808.
61483
   * get_number_type() is number_type::big_integer if we have an integer outside
61484
   * of those ranges (either larger than 18446744073709551615 or smaller than -9223372036854775808).
61485
   * Otherwise, get_number_type() has value number_type::floating_point_number
61486
   *
61487
   * This function requires processing the number string, but it is expected
61488
   * to be faster than get_number().get_number_type() because it is does not
61489
   * parse the number value.
61490
   *
61491
   * @returns the type of the number
61492
   */
61493
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
61494
61495
  /**
61496
   * Attempt to parse an ondemand::number. An ondemand::number may
61497
   * contain an integer value or a floating-point value, the simdjson
61498
   * library will autodetect the type. Thus it is a dynamically typed
61499
   * number. Before accessing the value, you must determine the detected
61500
   * type.
61501
   *
61502
   * number.get_number_type() is number_type::signed_integer if we have
61503
   * an integer in [-9223372036854775808,9223372036854775808)
61504
   * You can recover the value by calling number.get_int64() and you
61505
   * have that number.is_int64() is true.
61506
   *
61507
   * number.get_number_type() is number_type::unsigned_integer if we have
61508
   * an integer in [9223372036854775808,18446744073709551616)
61509
   * You can recover the value by calling number.get_uint64() and you
61510
   * have that number.is_uint64() is true.
61511
   *
61512
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
61513
   * and we have a binary64 number.
61514
   * You can recover the value by calling number.get_double() and you
61515
   * have that number.is_double() is true.
61516
   *
61517
   * You must check the type before accessing the value: it is an error
61518
   * to call "get_int64()" when number.get_number_type() is not
61519
   * number_type::signed_integer and when number.is_int64() is false.
61520
   */
61521
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
61522
61523
  /**
61524
   * Get the raw JSON for this token.
61525
   *
61526
   * The string_view will always point into the input buffer.
61527
   *
61528
   * The string_view will start at the beginning of the token, and include the entire token
61529
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
61530
   * string token always begins with a " and is always terminated by the final ", possibly
61531
   * followed by a number of spaces.
61532
   *
61533
   * The string_view is *not* null-terminated. If this is a scalar (string, number,
61534
   * boolean, or null), the character after the end of the string_view may be the padded buffer.
61535
   *
61536
   * Tokens include:
61537
   * - {
61538
   * - [
61539
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
61540
   * - -1.2e-100
61541
   * - true
61542
   * - false
61543
   * - null
61544
   */
61545
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
61546
61547
  /**
61548
   * Reset the iterator inside the document instance so we are pointing back at the
61549
   * beginning of the document, as if it had just been created. It invalidates all
61550
   * values, objects and arrays that you have created so far (including unescaped strings).
61551
   */
61552
  inline void rewind() noexcept;
61553
  /**
61554
   * Returns debugging information.
61555
   */
61556
  inline std::string to_debug_string() noexcept;
61557
  /**
61558
   * Some unrecoverable error conditions may render the document instance unusable.
61559
   * The is_alive() method returns true when the document is still suitable.
61560
   */
61561
  inline bool is_alive() noexcept;
61562
61563
  /**
61564
   * Returns the current location in the document if in bounds.
61565
   */
61566
  inline simdjson_result<const char *> current_location() const noexcept;
61567
61568
  /**
61569
   * Returns true if this document has been fully parsed.
61570
   * If you have consumed the whole document and at_end() returns
61571
   * false, then there may be trailing content.
61572
   */
61573
  inline bool at_end() const noexcept;
61574
61575
  /**
61576
   * Returns the current depth in the document if in bounds.
61577
   *
61578
   * E.g.,
61579
   *  0 = finished with document
61580
   *  1 = document root value (could be [ or {, not yet known)
61581
   *  2 = , or } inside root array/object
61582
   *  3 = key or value inside root array/object.
61583
   */
61584
  simdjson_inline int32_t current_depth() const noexcept;
61585
61586
  /**
61587
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
61588
   * https://tools.ietf.org/html/rfc6901 standard.
61589
   *
61590
   *   ondemand::parser parser;
61591
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
61592
   *   auto doc = parser.iterate(json);
61593
   *   doc.at_pointer("/foo/a/1") == 20
61594
   *
61595
   * It is allowed for a key to be the empty string:
61596
   *
61597
   *   ondemand::parser parser;
61598
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
61599
   *   auto doc = parser.iterate(json);
61600
   *   doc.at_pointer("//a/1") == 20
61601
   *
61602
   * Key values are matched exactly, without unescaping or Unicode normalization.
61603
   * We do a byte-by-byte comparison. E.g.
61604
   *
61605
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
61606
   *   auto doc = parser.iterate(json);
61607
   *   doc.at_pointer("/\\u00E9") == 123
61608
   *   doc.at_pointer((const char*)u8"/\u00E9") returns an error (NO_SUCH_FIELD)
61609
   *
61610
   * Note that at_pointer() automatically calls rewind between each call. Thus
61611
   * all values, objects and arrays that you have created so far (including unescaped strings)
61612
   * are invalidated. After calling at_pointer, you need to consume the result: string values
61613
   * should be stored in your own variables, arrays should be decoded and stored in your own array-like
61614
   * structures and so forth.
61615
   *
61616
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
61617
   *
61618
   * @return The value associated with the given JSON pointer, or:
61619
   *         - NO_SUCH_FIELD if a field does not exist in an object
61620
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
61621
   *         - INCORRECT_TYPE if a non-integer is used to access an array
61622
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
61623
   *         - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
61624
   */
61625
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
61626
61627
  /**
61628
   * Get the value associated with the given JSONPath expression. We only support
61629
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
61630
   * names and array indices.
61631
   *
61632
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
61633
   *
61634
   * Key values are matched exactly, without unescaping or Unicode normalization.
61635
   * We do a byte-by-byte comparison. E.g.
61636
   *
61637
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
61638
   *   auto doc = parser.iterate(json);
61639
   *   doc.at_path(".\\u00E9") == 123
61640
   *   doc.at_path((const char*)u8".\u00E9") returns an error (NO_SUCH_FIELD)
61641
   *
61642
   * @return The value associated with the given JSONPath expression, or:
61643
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
61644
   *         - NO_SUCH_FIELD if a field does not exist in an object
61645
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
61646
   *         - INCORRECT_TYPE if a non-integer is used to access an array
61647
   */
61648
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
61649
61650
  /**
61651
   * Consumes the document and returns a string_view instance corresponding to the
61652
   * document as represented in JSON. It points inside the original byte array containing
61653
   * the JSON document.
61654
   */
61655
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
61656
protected:
61657
  /**
61658
   * Consumes the document.
61659
   */
61660
  simdjson_inline error_code consume() noexcept;
61661
61662
  simdjson_inline document(ondemand::json_iterator &&iter) noexcept;
61663
  simdjson_inline const uint8_t *text(uint32_t idx) const noexcept;
61664
61665
  simdjson_inline value_iterator resume_value_iterator() noexcept;
61666
  simdjson_inline value_iterator get_root_value_iterator() noexcept;
61667
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
61668
  static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept;
61669
61670
  //
61671
  // Fields
61672
  //
61673
  json_iterator iter{}; ///< Current position in the document
61674
  static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0
61675
61676
  friend class array_iterator;
61677
  friend class value;
61678
  friend class ondemand::parser;
61679
  friend class object;
61680
  friend class array;
61681
  friend class field;
61682
  friend class token;
61683
  friend class document_stream;
61684
  friend class document_reference;
61685
};
61686
61687
61688
/**
61689
 * A document_reference is a thin wrapper around a document reference instance.
61690
 */
61691
class document_reference {
61692
public:
61693
  simdjson_inline document_reference() noexcept;
61694
  simdjson_inline document_reference(document &d) noexcept;
61695
  simdjson_inline document_reference(const document_reference &other) noexcept = default;
61696
  simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default;
61697
  simdjson_inline void rewind() noexcept;
61698
  simdjson_inline simdjson_result<array> get_array() & noexcept;
61699
  simdjson_inline simdjson_result<object> get_object() & noexcept;
61700
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
61701
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
61702
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
61703
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
61704
  simdjson_inline simdjson_result<double> get_double() noexcept;
61705
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
61706
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
61707
  template <typename string_type>
61708
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
61709
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
61710
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
61711
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
61712
  simdjson_inline simdjson_result<value> get_value() noexcept;
61713
61714
  simdjson_inline simdjson_result<bool> is_null() noexcept;
61715
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
61716
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
61717
  simdjson_inline operator document&() const noexcept;
61718
#if SIMDJSON_EXCEPTIONS
61719
  template <class T>
61720
  explicit simdjson_inline operator T() noexcept(false);
61721
  simdjson_inline operator array() & noexcept(false);
61722
  simdjson_inline operator object() & noexcept(false);
61723
  simdjson_inline operator uint64_t() noexcept(false);
61724
  simdjson_inline operator int64_t() noexcept(false);
61725
  simdjson_inline operator double() noexcept(false);
61726
  simdjson_inline operator std::string_view() noexcept(false);
61727
  simdjson_inline operator raw_json_string() noexcept(false);
61728
  simdjson_inline operator bool() noexcept(false);
61729
  simdjson_inline operator value() noexcept(false);
61730
#endif
61731
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
61732
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
61733
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
61734
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
61735
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
61736
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
61737
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
61738
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
61739
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
61740
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
61741
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
61742
61743
  simdjson_inline simdjson_result<json_type> type() noexcept;
61744
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
61745
  simdjson_inline simdjson_result<bool> is_string() noexcept;
61746
61747
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
61748
  simdjson_inline int32_t current_depth() const noexcept;
61749
  simdjson_inline bool is_negative() noexcept;
61750
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
61751
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
61752
  simdjson_inline simdjson_result<number> get_number() noexcept;
61753
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
61754
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
61755
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
61756
61757
private:
61758
  document *doc{nullptr};
61759
};
61760
} // namespace ondemand
61761
} // namespace icelake
61762
} // namespace simdjson
61763
61764
namespace simdjson {
61765
61766
template<>
61767
struct simdjson_result<icelake::ondemand::document> : public icelake::implementation_simdjson_result_base<icelake::ondemand::document> {
61768
public:
61769
  simdjson_inline simdjson_result(icelake::ondemand::document &&value) noexcept; ///< @private
61770
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
61771
  simdjson_inline simdjson_result() noexcept = default;
61772
  simdjson_inline error_code rewind() noexcept;
61773
61774
  simdjson_inline simdjson_result<icelake::ondemand::array> get_array() & noexcept;
61775
  simdjson_inline simdjson_result<icelake::ondemand::object> get_object() & noexcept;
61776
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
61777
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
61778
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
61779
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
61780
  simdjson_inline simdjson_result<double> get_double() noexcept;
61781
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
61782
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
61783
  template <typename string_type>
61784
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
61785
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
61786
  simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> get_raw_json_string() noexcept;
61787
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
61788
  simdjson_inline simdjson_result<icelake::ondemand::value> get_value() noexcept;
61789
  simdjson_inline simdjson_result<bool> is_null() noexcept;
61790
61791
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
61792
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept;
61793
61794
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
61795
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
61796
#if SIMDJSON_EXCEPTIONS
61797
  template <class T, typename std::enable_if<std::is_same<T, icelake::ondemand::document>::value == false>::type>
61798
  explicit simdjson_inline operator T() noexcept(false);
61799
  simdjson_inline operator icelake::ondemand::array() & noexcept(false);
61800
  simdjson_inline operator icelake::ondemand::object() & noexcept(false);
61801
  simdjson_inline operator uint64_t() noexcept(false);
61802
  simdjson_inline operator int64_t() noexcept(false);
61803
  simdjson_inline operator double() noexcept(false);
61804
  simdjson_inline operator std::string_view() noexcept(false);
61805
  simdjson_inline operator icelake::ondemand::raw_json_string() noexcept(false);
61806
  simdjson_inline operator bool() noexcept(false);
61807
  simdjson_inline operator icelake::ondemand::value() noexcept(false);
61808
#endif
61809
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
61810
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
61811
  simdjson_inline simdjson_result<icelake::ondemand::value> at(size_t index) & noexcept;
61812
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> begin() & noexcept;
61813
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> end() & noexcept;
61814
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(std::string_view key) & noexcept;
61815
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(const char *key) & noexcept;
61816
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](std::string_view key) & noexcept;
61817
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](const char *key) & noexcept;
61818
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
61819
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(const char *key) & noexcept;
61820
  simdjson_inline simdjson_result<icelake::ondemand::json_type> type() noexcept;
61821
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
61822
  simdjson_inline simdjson_result<bool> is_string() noexcept;
61823
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
61824
  simdjson_inline int32_t current_depth() const noexcept;
61825
  simdjson_inline bool at_end() const noexcept;
61826
  simdjson_inline bool is_negative() noexcept;
61827
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
61828
  simdjson_inline simdjson_result<icelake::number_type> get_number_type() noexcept;
61829
  simdjson_inline simdjson_result<icelake::ondemand::number> get_number() noexcept;
61830
  /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */
61831
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
61832
61833
  simdjson_inline simdjson_result<icelake::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
61834
  simdjson_inline simdjson_result<icelake::ondemand::value> at_path(std::string_view json_path) noexcept;
61835
};
61836
61837
61838
} // namespace simdjson
61839
61840
61841
61842
namespace simdjson {
61843
61844
template<>
61845
struct simdjson_result<icelake::ondemand::document_reference> : public icelake::implementation_simdjson_result_base<icelake::ondemand::document_reference> {
61846
public:
61847
  simdjson_inline simdjson_result(icelake::ondemand::document_reference value, error_code error) noexcept;
61848
  simdjson_inline simdjson_result() noexcept = default;
61849
  simdjson_inline error_code rewind() noexcept;
61850
61851
  simdjson_inline simdjson_result<icelake::ondemand::array> get_array() & noexcept;
61852
  simdjson_inline simdjson_result<icelake::ondemand::object> get_object() & noexcept;
61853
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
61854
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
61855
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
61856
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
61857
  simdjson_inline simdjson_result<double> get_double() noexcept;
61858
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
61859
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
61860
  template <typename string_type>
61861
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
61862
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
61863
  simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> get_raw_json_string() noexcept;
61864
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
61865
  simdjson_inline simdjson_result<icelake::ondemand::value> get_value() noexcept;
61866
  simdjson_inline simdjson_result<bool> is_null() noexcept;
61867
#if SIMDJSON_EXCEPTIONS
61868
  template <class T, typename std::enable_if<std::is_same<T, icelake::ondemand::document_reference>::value == false>::type>
61869
  explicit simdjson_inline operator T() noexcept(false);
61870
  simdjson_inline operator icelake::ondemand::array() & noexcept(false);
61871
  simdjson_inline operator icelake::ondemand::object() & noexcept(false);
61872
  simdjson_inline operator uint64_t() noexcept(false);
61873
  simdjson_inline operator int64_t() noexcept(false);
61874
  simdjson_inline operator double() noexcept(false);
61875
  simdjson_inline operator std::string_view() noexcept(false);
61876
  simdjson_inline operator icelake::ondemand::raw_json_string() noexcept(false);
61877
  simdjson_inline operator bool() noexcept(false);
61878
  simdjson_inline operator icelake::ondemand::value() noexcept(false);
61879
#endif
61880
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
61881
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
61882
  simdjson_inline simdjson_result<icelake::ondemand::value> at(size_t index) & noexcept;
61883
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> begin() & noexcept;
61884
  simdjson_inline simdjson_result<icelake::ondemand::array_iterator> end() & noexcept;
61885
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(std::string_view key) & noexcept;
61886
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(const char *key) & noexcept;
61887
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](std::string_view key) & noexcept;
61888
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](const char *key) & noexcept;
61889
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
61890
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(const char *key) & noexcept;
61891
  simdjson_inline simdjson_result<icelake::ondemand::json_type> type() noexcept;
61892
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
61893
  simdjson_inline simdjson_result<bool> is_string() noexcept;
61894
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
61895
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
61896
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
61897
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
61898
  simdjson_inline simdjson_result<icelake::number_type> get_number_type() noexcept;
61899
  simdjson_inline simdjson_result<icelake::ondemand::number> get_number() noexcept;
61900
  /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */
61901
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
61902
61903
  simdjson_inline simdjson_result<icelake::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
61904
  simdjson_inline simdjson_result<icelake::ondemand::value> at_path(std::string_view json_path) noexcept;
61905
};
61906
61907
61908
} // namespace simdjson
61909
61910
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
61911
/* end file simdjson/generic/ondemand/document.h for icelake */
61912
/* including simdjson/generic/ondemand/document_stream.h for icelake: #include "simdjson/generic/ondemand/document_stream.h" */
61913
/* begin file simdjson/generic/ondemand/document_stream.h for icelake */
61914
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
61915
61916
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
61917
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H */
61918
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
61919
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
61920
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
61921
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
61922
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
61923
61924
#ifdef SIMDJSON_THREADS_ENABLED
61925
#include <thread>
61926
#include <mutex>
61927
#include <condition_variable>
61928
#endif
61929
61930
namespace simdjson {
61931
namespace icelake {
61932
namespace ondemand {
61933
61934
#ifdef SIMDJSON_THREADS_ENABLED
61935
/** @private Custom worker class **/
61936
struct stage1_worker {
61937
  stage1_worker() noexcept = default;
61938
  stage1_worker(const stage1_worker&) = delete;
61939
  stage1_worker(stage1_worker&&) = delete;
61940
  stage1_worker operator=(const stage1_worker&) = delete;
61941
  ~stage1_worker();
61942
  /**
61943
   * We only start the thread when it is needed, not at object construction, this may throw.
61944
   * You should only call this once.
61945
   **/
61946
  void start_thread();
61947
  /**
61948
   * Start a stage 1 job. You should first call 'run', then 'finish'.
61949
   * You must call start_thread once before.
61950
   */
61951
  void run(document_stream * ds, parser * stage1, size_t next_batch_start);
61952
  /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
61953
  void finish();
61954
61955
private:
61956
61957
  /**
61958
   * Normally, we would never stop the thread. But we do in the destructor.
61959
   * This function is only safe assuming that you are not waiting for results. You
61960
   * should have called run, then finish, and be done.
61961
   **/
61962
  void stop_thread();
61963
61964
  std::thread thread{};
61965
  /** These three variables define the work done by the thread. **/
61966
  ondemand::parser * stage1_thread_parser{};
61967
  size_t _next_batch_start{};
61968
  document_stream * owner{};
61969
  /**
61970
   * We have two state variables. This could be streamlined to one variable in the future but
61971
   * we use two for clarity.
61972
   */
61973
  bool has_work{false};
61974
  bool can_work{true};
61975
61976
  /**
61977
   * We lock using a mutex.
61978
   */
61979
  std::mutex locking_mutex{};
61980
  std::condition_variable cond_var{};
61981
61982
  friend class document_stream;
61983
};
61984
#endif  // SIMDJSON_THREADS_ENABLED
61985
61986
/**
61987
 * A forward-only stream of documents.
61988
 *
61989
 * Produced by parser::iterate_many.
61990
 *
61991
 */
61992
class document_stream {
61993
public:
61994
  /**
61995
   * Construct an uninitialized document_stream.
61996
   *
61997
   *  ```c++
61998
   *  document_stream docs;
61999
   *  auto error = parser.iterate_many(json).get(docs);
62000
   *  ```
62001
   */
62002
  simdjson_inline document_stream() noexcept;
62003
  /** Move one document_stream to another. */
62004
  simdjson_inline document_stream(document_stream &&other) noexcept = default;
62005
  /** Move one document_stream to another. */
62006
  simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
62007
62008
  simdjson_inline ~document_stream() noexcept;
62009
62010
  /**
62011
   * Returns the input size in bytes.
62012
   */
62013
  inline size_t size_in_bytes() const noexcept;
62014
62015
  /**
62016
   * After iterating through the stream, this method
62017
   * returns the number of bytes that were not parsed at the end
62018
   * of the stream. If truncated_bytes() differs from zero,
62019
   * then the input was truncated maybe because incomplete JSON
62020
   * documents were found at the end of the stream. You
62021
   * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
62022
   *
62023
   * You should only call truncated_bytes() after streaming through all
62024
   * documents, like so:
62025
   *
62026
   *   document_stream stream = parser.iterate_many(json,window);
62027
   *   for(auto & doc : stream) {
62028
   *      // do something with doc
62029
   *   }
62030
   *   size_t truncated = stream.truncated_bytes();
62031
   *
62032
   */
62033
  inline size_t truncated_bytes() const noexcept;
62034
62035
  class iterator {
62036
  public:
62037
    using value_type = simdjson_result<document>;
62038
    using reference  = simdjson_result<ondemand::document_reference>;
62039
    using pointer    = void;
62040
    using difference_type   = std::ptrdiff_t;
62041
    using iterator_category = std::input_iterator_tag;
62042
62043
    /**
62044
     * Default constructor.
62045
     */
62046
    simdjson_inline iterator() noexcept;
62047
    /**
62048
     * Get the current document (or error).
62049
     */
62050
    simdjson_inline reference operator*() noexcept;
62051
    /**
62052
     * Advance to the next document (prefix).
62053
     */
62054
    inline iterator& operator++() noexcept;
62055
    /**
62056
     * Check if we're at the end yet.
62057
     * @param other the end iterator to compare to.
62058
     */
62059
    simdjson_inline bool operator!=(const iterator &other) const noexcept;
62060
    /**
62061
     * @private
62062
     *
62063
     * Gives the current index in the input document in bytes.
62064
     *
62065
     *   document_stream stream = parser.parse_many(json,window);
62066
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
62067
     *      auto doc = *i;
62068
     *      size_t index = i.current_index();
62069
     *   }
62070
     *
62071
     * This function (current_index()) is experimental and the usage
62072
     * may change in future versions of simdjson: we find the API somewhat
62073
     * awkward and we would like to offer something friendlier.
62074
     */
62075
     simdjson_inline size_t current_index() const noexcept;
62076
62077
     /**
62078
     * @private
62079
     *
62080
     * Gives a view of the current document at the current position.
62081
     *
62082
     *   document_stream stream = parser.iterate_many(json,window);
62083
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
62084
     *      std::string_view v = i.source();
62085
     *   }
62086
     *
62087
     * The returned string_view instance is simply a map to the (unparsed)
62088
     * source string: it may thus include white-space characters and all manner
62089
     * of padding.
62090
     *
62091
     * This function (source()) is experimental and the usage
62092
     * may change in future versions of simdjson: we find the API somewhat
62093
     * awkward and we would like to offer something friendlier.
62094
     *
62095
     */
62096
     simdjson_inline std::string_view source() const noexcept;
62097
62098
    /**
62099
     * Returns error of the stream (if any).
62100
     */
62101
     inline error_code error() const noexcept;
62102
62103
  private:
62104
    simdjson_inline iterator(document_stream *s, bool finished) noexcept;
62105
    /** The document_stream we're iterating through. */
62106
    document_stream* stream;
62107
    /** Whether we're finished or not. */
62108
    bool finished;
62109
62110
    friend class document;
62111
    friend class document_stream;
62112
    friend class json_iterator;
62113
  };
62114
62115
  /**
62116
   * Start iterating the documents in the stream.
62117
   */
62118
  simdjson_inline iterator begin() noexcept;
62119
  /**
62120
   * The end of the stream, for iterator comparison purposes.
62121
   */
62122
  simdjson_inline iterator end() noexcept;
62123
62124
private:
62125
62126
  document_stream &operator=(const document_stream &) = delete; // Disallow copying
62127
  document_stream(const document_stream &other) = delete; // Disallow copying
62128
62129
  /**
62130
   * Construct a document_stream. Does not allocate or parse anything until the iterator is
62131
   * used.
62132
   *
62133
   * @param parser is a reference to the parser instance used to generate this document_stream
62134
   * @param buf is the raw byte buffer we need to process
62135
   * @param len is the length of the raw byte buffer in bytes
62136
   * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
62137
   */
62138
  simdjson_inline document_stream(
62139
    ondemand::parser &parser,
62140
    const uint8_t *buf,
62141
    size_t len,
62142
    size_t batch_size,
62143
    bool allow_comma_separated
62144
  ) noexcept;
62145
62146
  /**
62147
   * Parse the first document in the buffer. Used by begin(), to handle allocation and
62148
   * initialization.
62149
   */
62150
  inline void start() noexcept;
62151
62152
  /**
62153
   * Parse the next document found in the buffer previously given to document_stream.
62154
   *
62155
   * The content should be a valid JSON document encoded as UTF-8. If there is a
62156
   * UTF-8 BOM, the parser skips it.
62157
   *
62158
   * You do NOT need to pre-allocate a parser.  This function takes care of
62159
   * pre-allocating a capacity defined by the batch_size defined when creating the
62160
   * document_stream object.
62161
   *
62162
   * The function returns simdjson::EMPTY if there is no more data to be parsed.
62163
   *
62164
   * The function returns simdjson::SUCCESS (as integer = 0) in case of success
62165
   * and indicates that the buffer has successfully been parsed to the end.
62166
   * Every document it contained has been parsed without error.
62167
   *
62168
   * The function returns an error code from simdjson/simdjson.h in case of failure
62169
   * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
62170
   * the simdjson::error_message function converts these error codes into a string).
62171
   *
62172
   * You can also check validity by calling parser.is_valid(). The same parser can
62173
   * and should be reused for the other documents in the buffer.
62174
   */
62175
  inline void next() noexcept;
62176
62177
  /** Move the json_iterator of the document to the location of the next document in the stream. */
62178
  inline void next_document() noexcept;
62179
62180
  /** Get the next document index. */
62181
  inline size_t next_batch_start() const noexcept;
62182
62183
  /** Pass the next batch through stage 1 with the given parser. */
62184
  inline error_code run_stage1(ondemand::parser &p, size_t batch_start) noexcept;
62185
62186
  // Fields
62187
  ondemand::parser *parser;
62188
  const uint8_t *buf;
62189
  size_t len;
62190
  size_t batch_size;
62191
  bool allow_comma_separated;
62192
  /**
62193
   * We are going to use just one document instance. The document owns
62194
   * the json_iterator. It implies that we only ever pass a reference
62195
   * to the document to the users.
62196
   */
62197
  document doc{};
62198
  /** The error (or lack thereof) from the current document. */
62199
  error_code error;
62200
  size_t batch_start{0};
62201
  size_t doc_index{};
62202
62203
  #ifdef SIMDJSON_THREADS_ENABLED
62204
  /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
62205
  bool use_thread;
62206
62207
  inline void load_from_stage1_thread() noexcept;
62208
62209
  /** Start a thread to run stage 1 on the next batch. */
62210
  inline void start_stage1_thread() noexcept;
62211
62212
  /** Wait for the stage 1 thread to finish and capture the results. */
62213
  inline void finish_stage1_thread() noexcept;
62214
62215
  /** The error returned from the stage 1 thread. */
62216
  error_code stage1_thread_error{UNINITIALIZED};
62217
  /** The thread used to run stage 1 against the next batch in the background. */
62218
  std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
62219
  /**
62220
   * The parser used to run stage 1 in the background. Will be swapped
62221
   * with the regular parser when finished.
62222
   */
62223
  ondemand::parser stage1_thread_parser{};
62224
62225
  friend struct stage1_worker;
62226
  #endif // SIMDJSON_THREADS_ENABLED
62227
62228
  friend class parser;
62229
  friend class document;
62230
  friend class json_iterator;
62231
  friend struct simdjson_result<ondemand::document_stream>;
62232
  friend struct internal::simdjson_result_base<ondemand::document_stream>;
62233
};  // document_stream
62234
62235
} // namespace ondemand
62236
} // namespace icelake
62237
} // namespace simdjson
62238
62239
namespace simdjson {
62240
template<>
62241
struct simdjson_result<icelake::ondemand::document_stream> : public icelake::implementation_simdjson_result_base<icelake::ondemand::document_stream> {
62242
public:
62243
  simdjson_inline simdjson_result(icelake::ondemand::document_stream &&value) noexcept; ///< @private
62244
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
62245
  simdjson_inline simdjson_result() noexcept = default;
62246
};
62247
62248
} // namespace simdjson
62249
62250
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
62251
/* end file simdjson/generic/ondemand/document_stream.h for icelake */
62252
/* including simdjson/generic/ondemand/field.h for icelake: #include "simdjson/generic/ondemand/field.h" */
62253
/* begin file simdjson/generic/ondemand/field.h for icelake */
62254
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
62255
62256
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
62257
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_H */
62258
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
62259
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
62260
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
62261
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
62262
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
62263
62264
namespace simdjson {
62265
namespace icelake {
62266
namespace ondemand {
62267
62268
/**
62269
 * A JSON field (key/value pair) in an object.
62270
 *
62271
 * Returned from object iteration.
62272
 *
62273
 * Extends from std::pair<raw_json_string, value> so you can use C++ algorithms that rely on pairs.
62274
 */
62275
class field : public std::pair<raw_json_string, value> {
62276
public:
62277
  /**
62278
   * Create a new invalid field.
62279
   *
62280
   * Exists so you can declare a variable and later assign to it before use.
62281
   */
62282
  simdjson_inline field() noexcept;
62283
62284
  /**
62285
   * Get the key as a string_view (for higher speed, consider raw_key).
62286
   * We deliberately use a more cumbersome name (unescaped_key) to force users
62287
   * to think twice about using it.
62288
   *
62289
   * This consumes the key: once you have called unescaped_key(), you cannot
62290
   * call it again nor can you call key().
62291
   */
62292
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescaped_key(bool allow_replacement) noexcept;
62293
  /**
62294
   * Get the key as a raw_json_string. Can be used for direct comparison with
62295
   * an unescaped C string: e.g., key() == "test".
62296
   */
62297
  simdjson_inline raw_json_string key() const noexcept;
62298
  /**
62299
   * Get the unprocessed key as a string_view. This includes the quotes and may include
62300
   * some spaces after the last quote.
62301
   */
62302
  simdjson_inline std::string_view key_raw_json_token() const noexcept;
62303
  /**
62304
   * Get the field value.
62305
   */
62306
  simdjson_inline ondemand::value &value() & noexcept;
62307
  /**
62308
   * @overload ondemand::value &ondemand::value() & noexcept
62309
   */
62310
  simdjson_inline ondemand::value value() && noexcept;
62311
62312
protected:
62313
  simdjson_inline field(raw_json_string key, ondemand::value &&value) noexcept;
62314
  static simdjson_inline simdjson_result<field> start(value_iterator &parent_iter) noexcept;
62315
  static simdjson_inline simdjson_result<field> start(const value_iterator &parent_iter, raw_json_string key) noexcept;
62316
  friend struct simdjson_result<field>;
62317
  friend class object_iterator;
62318
};
62319
62320
} // namespace ondemand
62321
} // namespace icelake
62322
} // namespace simdjson
62323
62324
namespace simdjson {
62325
62326
template<>
62327
struct simdjson_result<icelake::ondemand::field> : public icelake::implementation_simdjson_result_base<icelake::ondemand::field> {
62328
public:
62329
  simdjson_inline simdjson_result(icelake::ondemand::field &&value) noexcept; ///< @private
62330
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
62331
  simdjson_inline simdjson_result() noexcept = default;
62332
62333
  simdjson_inline simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
62334
  simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> key() noexcept;
62335
  simdjson_inline simdjson_result<std::string_view> key_raw_json_token() noexcept;
62336
  simdjson_inline simdjson_result<icelake::ondemand::value> value() noexcept;
62337
};
62338
62339
} // namespace simdjson
62340
62341
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_H
62342
/* end file simdjson/generic/ondemand/field.h for icelake */
62343
/* including simdjson/generic/ondemand/object.h for icelake: #include "simdjson/generic/ondemand/object.h" */
62344
/* begin file simdjson/generic/ondemand/object.h for icelake */
62345
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
62346
62347
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
62348
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_H */
62349
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
62350
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
62351
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
62352
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
62353
62354
namespace simdjson {
62355
namespace icelake {
62356
namespace ondemand {
62357
62358
/**
62359
 * A forward-only JSON object field iterator.
62360
 */
62361
class object {
62362
public:
62363
  /**
62364
   * Create a new invalid object.
62365
   *
62366
   * Exists so you can declare a variable and later assign to it before use.
62367
   */
62368
  simdjson_inline object() noexcept = default;
62369
62370
  simdjson_inline simdjson_result<object_iterator> begin() noexcept;
62371
  simdjson_inline simdjson_result<object_iterator> end() noexcept;
62372
  /**
62373
   * Look up a field by name on an object (order-sensitive).
62374
   *
62375
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
62376
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
62377
   *
62378
   * ```c++
62379
   * simdjson::ondemand::parser parser;
62380
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
62381
   * double z = obj.find_field("z");
62382
   * double y = obj.find_field("y");
62383
   * double x = obj.find_field("x");
62384
   * ```
62385
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
62386
   * that only one field is returned.
62387
   *
62388
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
62389
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
62390
   *
62391
   * You must consume the fields on an object one at a time. A request for a new key
62392
   * invalidates previous field values: it makes them unsafe. The value instance you get
62393
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
62394
   * given by content["bids"].get_array() should not be accessed after you have called
62395
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
62396
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
62397
   * OUT_OF_ORDER_ITERATION error is generated.
62398
   *
62399
   * You are expected to access keys only once. You should access the value corresponding to a
62400
   * key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
62401
   * is an error.
62402
   *
62403
   * @param key The key to look up.
62404
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
62405
   */
62406
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
62407
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
62408
  simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
62409
62410
  /**
62411
   * Look up a field by name on an object, without regard to key order.
62412
   *
62413
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
62414
   * and often appears negligible. It starts out normally, starting out at the last field; but if
62415
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
62416
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
62417
   * in question is large. The fact that the extra code is there also bumps the executable size.
62418
   *
62419
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
62420
   * default behavior failed to look up a field just because it was in the wrong order--and many
62421
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
62422
   *
62423
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
62424
   * field was not there when they are not in order).
62425
   *
62426
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
62427
   * that only one field is returned.
62428
   *
62429
   * You must consume the fields on an object one at a time. A request for a new key
62430
   * invalidates previous field values: it makes them unsafe. The value instance you get
62431
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
62432
   * given by content["bids"].get_array() should not be accessed after you have called
62433
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
62434
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
62435
   * OUT_OF_ORDER_ITERATION error is generated.
62436
   *
62437
   * You are expected to access keys only once. You should access the value corresponding to a key
62438
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
62439
   *
62440
   * @param key The key to look up.
62441
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
62442
   */
62443
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
62444
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
62445
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
62446
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
62447
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
62448
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
62449
  simdjson_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
62450
62451
  /**
62452
   * Get the value associated with the given JSON pointer. We use the RFC 6901
62453
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
62454
   * as the root of its own JSON document.
62455
   *
62456
   *   ondemand::parser parser;
62457
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
62458
   *   auto doc = parser.iterate(json);
62459
   *   doc.at_pointer("/foo/a/1") == 20
62460
   *
62461
   * It is allowed for a key to be the empty string:
62462
   *
62463
   *   ondemand::parser parser;
62464
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
62465
   *   auto doc = parser.iterate(json);
62466
   *   doc.at_pointer("//a/1") == 20
62467
   *
62468
   * Note that at_pointer() called on the document automatically calls the document's rewind
62469
   * method between each call. It invalidates all previously accessed arrays, objects and values
62470
   * that have not been consumed. Yet it is not the case when calling at_pointer on an object
62471
   * instance: there is no rewind and no invalidation.
62472
   *
62473
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
62474
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
62475
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
62476
   *
62477
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
62478
   *
62479
   * @return The value associated with the given JSON pointer, or:
62480
   *         - NO_SUCH_FIELD if a field does not exist in an object
62481
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
62482
   *         - INCORRECT_TYPE if a non-integer is used to access an array
62483
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
62484
   */
62485
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
62486
62487
  /**
62488
   * Get the value associated with the given JSONPath expression. We only support
62489
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
62490
   * names and array indices.
62491
   *
62492
   * @return The value associated with the given JSONPath expression, or:
62493
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
62494
   *         - NO_SUCH_FIELD if a field does not exist in an object
62495
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
62496
   *         - INCORRECT_TYPE if a non-integer is used to access an array
62497
   */
62498
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
62499
62500
  /**
62501
   * Reset the iterator so that we are pointing back at the
62502
   * beginning of the object. You should still consume values only once even if you
62503
   * can iterate through the object more than once. If you unescape a string within
62504
   * the object more than once, you have unsafe code. Note that rewinding an object
62505
   * means that you may need to reparse it anew: it is not a free operation.
62506
   *
62507
   * @returns true if the object contains some elements (not empty)
62508
   */
62509
  inline simdjson_result<bool> reset() & noexcept;
62510
  /**
62511
   * This method scans the beginning of the object and checks whether the
62512
   * object is empty.
62513
   * The runtime complexity is constant time. After
62514
   * calling this function, if successful, the object is 'rewinded' at its
62515
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
62516
   * there is a missing comma), then an error is returned and it is no longer
62517
   * safe to continue.
62518
   */
62519
  inline simdjson_result<bool> is_empty() & noexcept;
62520
  /**
62521
   * This method scans the object and counts the number of key-value pairs.
62522
   * The count_fields method should always be called before you have begun
62523
   * iterating through the object: it is expected that you are pointing at
62524
   * the beginning of the object.
62525
   * The runtime complexity is linear in the size of the object. After
62526
   * calling this function, if successful, the object is 'rewinded' at its
62527
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
62528
   * there is a missing comma), then an error is returned and it is no longer
62529
   * safe to continue.
62530
   *
62531
   * To check that an object is empty, it is more performant to use
62532
   * the is_empty() method.
62533
   *
62534
   * Performance hint: You should only call count_fields() as a last
62535
   * resort as it may require scanning the document twice or more.
62536
   */
62537
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
62538
  /**
62539
   * Consumes the object and returns a string_view instance corresponding to the
62540
   * object as represented in JSON. It points inside the original byte array containing
62541
   * the JSON document.
62542
   */
62543
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
62544
62545
protected:
62546
  /**
62547
   * Go to the end of the object, no matter where you are right now.
62548
   */
62549
  simdjson_inline error_code consume() noexcept;
62550
  static simdjson_inline simdjson_result<object> start(value_iterator &iter) noexcept;
62551
  static simdjson_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
62552
  static simdjson_inline simdjson_result<object> started(value_iterator &iter) noexcept;
62553
  static simdjson_inline object resume(const value_iterator &iter) noexcept;
62554
  simdjson_inline object(const value_iterator &iter) noexcept;
62555
62556
  simdjson_warn_unused simdjson_inline error_code find_field_raw(const std::string_view key) noexcept;
62557
62558
  value_iterator iter{};
62559
62560
  friend class value;
62561
  friend class document;
62562
  friend struct simdjson_result<object>;
62563
};
62564
62565
} // namespace ondemand
62566
} // namespace icelake
62567
} // namespace simdjson
62568
62569
namespace simdjson {
62570
62571
template<>
62572
struct simdjson_result<icelake::ondemand::object> : public icelake::implementation_simdjson_result_base<icelake::ondemand::object> {
62573
public:
62574
  simdjson_inline simdjson_result(icelake::ondemand::object &&value) noexcept; ///< @private
62575
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
62576
  simdjson_inline simdjson_result() noexcept = default;
62577
62578
  simdjson_inline simdjson_result<icelake::ondemand::object_iterator> begin() noexcept;
62579
  simdjson_inline simdjson_result<icelake::ondemand::object_iterator> end() noexcept;
62580
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(std::string_view key) & noexcept;
62581
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field(std::string_view key) && noexcept;
62582
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
62583
  simdjson_inline simdjson_result<icelake::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
62584
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](std::string_view key) & noexcept;
62585
  simdjson_inline simdjson_result<icelake::ondemand::value> operator[](std::string_view key) && noexcept;
62586
  simdjson_inline simdjson_result<icelake::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
62587
  simdjson_inline simdjson_result<icelake::ondemand::value> at_path(std::string_view json_path) noexcept;
62588
62589
  inline simdjson_result<bool> reset() noexcept;
62590
  inline simdjson_result<bool> is_empty() noexcept;
62591
  inline simdjson_result<size_t> count_fields() & noexcept;
62592
  inline simdjson_result<std::string_view> raw_json() noexcept;
62593
62594
};
62595
62596
} // namespace simdjson
62597
62598
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
62599
/* end file simdjson/generic/ondemand/object.h for icelake */
62600
/* including simdjson/generic/ondemand/object_iterator.h for icelake: #include "simdjson/generic/ondemand/object_iterator.h" */
62601
/* begin file simdjson/generic/ondemand/object_iterator.h for icelake */
62602
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
62603
62604
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
62605
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H */
62606
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
62607
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
62608
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
62609
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
62610
62611
namespace simdjson {
62612
namespace icelake {
62613
namespace ondemand {
62614
62615
class object_iterator {
62616
public:
62617
  /**
62618
   * Create a new invalid object_iterator.
62619
   *
62620
   * Exists so you can declare a variable and later assign to it before use.
62621
   */
62622
  simdjson_inline object_iterator() noexcept = default;
62623
62624
  //
62625
  // Iterator interface
62626
  //
62627
62628
  // Reads key and value, yielding them to the user.
62629
  // MUST ONLY BE CALLED ONCE PER ITERATION.
62630
  simdjson_inline simdjson_result<field> operator*() noexcept;
62631
  // Assumes it's being compared with the end. true if depth < iter->depth.
62632
  simdjson_inline bool operator==(const object_iterator &) const noexcept;
62633
  // Assumes it's being compared with the end. true if depth >= iter->depth.
62634
  simdjson_inline bool operator!=(const object_iterator &) const noexcept;
62635
  // Checks for ']' and ','
62636
  simdjson_inline object_iterator &operator++() noexcept;
62637
62638
private:
62639
  /**
62640
   * The underlying JSON iterator.
62641
   *
62642
   * PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
62643
   * is first used, and never changes afterwards.
62644
   */
62645
  value_iterator iter{};
62646
62647
  simdjson_inline object_iterator(const value_iterator &iter) noexcept;
62648
  friend struct simdjson_result<object_iterator>;
62649
  friend class object;
62650
};
62651
62652
} // namespace ondemand
62653
} // namespace icelake
62654
} // namespace simdjson
62655
62656
namespace simdjson {
62657
62658
template<>
62659
struct simdjson_result<icelake::ondemand::object_iterator> : public icelake::implementation_simdjson_result_base<icelake::ondemand::object_iterator> {
62660
public:
62661
  simdjson_inline simdjson_result(icelake::ondemand::object_iterator &&value) noexcept; ///< @private
62662
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
62663
  simdjson_inline simdjson_result() noexcept = default;
62664
62665
  //
62666
  // Iterator interface
62667
  //
62668
62669
  // Reads key and value, yielding them to the user.
62670
  simdjson_inline simdjson_result<icelake::ondemand::field> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
62671
  // Assumes it's being compared with the end. true if depth < iter->depth.
62672
  simdjson_inline bool operator==(const simdjson_result<icelake::ondemand::object_iterator> &) const noexcept;
62673
  // Assumes it's being compared with the end. true if depth >= iter->depth.
62674
  simdjson_inline bool operator!=(const simdjson_result<icelake::ondemand::object_iterator> &) const noexcept;
62675
  // Checks for ']' and ','
62676
  simdjson_inline simdjson_result<icelake::ondemand::object_iterator> &operator++() noexcept;
62677
};
62678
62679
} // namespace simdjson
62680
62681
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
62682
/* end file simdjson/generic/ondemand/object_iterator.h for icelake */
62683
/* including simdjson/generic/ondemand/serialization.h for icelake: #include "simdjson/generic/ondemand/serialization.h" */
62684
/* begin file simdjson/generic/ondemand/serialization.h for icelake */
62685
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
62686
62687
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
62688
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H */
62689
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
62690
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
62691
62692
namespace simdjson {
62693
/**
62694
 * Create a string-view instance out of a document instance. The string-view instance
62695
 * contains JSON text that is suitable to be parsed as JSON again. It does not
62696
 * validate the content.
62697
 */
62698
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::document& x) noexcept;
62699
/**
62700
 * Create a string-view instance out of a value instance. The string-view instance
62701
 * contains JSON text that is suitable to be parsed as JSON again. The value must
62702
 * not have been accessed previously. It does not
62703
 * validate the content.
62704
 */
62705
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::value& x) noexcept;
62706
/**
62707
 * Create a string-view instance out of an object instance. The string-view instance
62708
 * contains JSON text that is suitable to be parsed as JSON again. It does not
62709
 * validate the content.
62710
 */
62711
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::object& x) noexcept;
62712
/**
62713
 * Create a string-view instance out of an array instance. The string-view instance
62714
 * contains JSON text that is suitable to be parsed as JSON again. It does not
62715
 * validate the content.
62716
 */
62717
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::array& x) noexcept;
62718
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::document> x);
62719
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::value> x);
62720
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::object> x);
62721
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::array> x);
62722
} // namespace simdjson
62723
62724
/**
62725
 * We want to support argument-dependent lookup (ADL).
62726
 * Hence we should define operator<< in the namespace
62727
 * where the argument (here value, object, etc.) resides.
62728
 * Credit: @madhur4127
62729
 * See https://github.com/simdjson/simdjson/issues/1768
62730
 */
62731
namespace simdjson { namespace icelake { namespace ondemand {
62732
62733
/**
62734
 * Print JSON to an output stream.  It does not
62735
 * validate the content.
62736
 *
62737
 * @param out The output stream.
62738
 * @param value The element.
62739
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
62740
 */
62741
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::value x);
62742
#if SIMDJSON_EXCEPTIONS
62743
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::value> x);
62744
#endif
62745
/**
62746
 * Print JSON to an output stream. It does not
62747
 * validate the content.
62748
 *
62749
 * @param out The output stream.
62750
 * @param value The array.
62751
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
62752
 */
62753
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::array value);
62754
#if SIMDJSON_EXCEPTIONS
62755
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::array> x);
62756
#endif
62757
/**
62758
 * Print JSON to an output stream. It does not
62759
 * validate the content.
62760
 *
62761
 * @param out The output stream.
62762
 * @param value The array.
62763
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
62764
 */
62765
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::document& value);
62766
#if SIMDJSON_EXCEPTIONS
62767
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::document>&& x);
62768
#endif
62769
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::document_reference& value);
62770
#if SIMDJSON_EXCEPTIONS
62771
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::document_reference>&& x);
62772
#endif
62773
/**
62774
 * Print JSON to an output stream. It does not
62775
 * validate the content.
62776
 *
62777
 * @param out The output stream.
62778
 * @param value The object.
62779
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
62780
 */
62781
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::object value);
62782
#if SIMDJSON_EXCEPTIONS
62783
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::object> x);
62784
#endif
62785
}}} // namespace simdjson::icelake::ondemand
62786
62787
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
62788
/* end file simdjson/generic/ondemand/serialization.h for icelake */
62789
62790
// Inline definitions
62791
/* including simdjson/generic/ondemand/array-inl.h for icelake: #include "simdjson/generic/ondemand/array-inl.h" */
62792
/* begin file simdjson/generic/ondemand/array-inl.h for icelake */
62793
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
62794
62795
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
62796
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H */
62797
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
62798
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
62799
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator-inl.h" */
62800
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
62801
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
62802
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
62803
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
62804
62805
namespace simdjson {
62806
namespace icelake {
62807
namespace ondemand {
62808
62809
//
62810
// ### Live States
62811
//
62812
// While iterating or looking up values, depth >= iter->depth. at_start may vary. Error is
62813
// always SUCCESS:
62814
//
62815
// - Start: This is the state when the array is first found and the iterator is just past the `{`.
62816
//   In this state, at_start == true.
62817
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
62818
//   iterate over, the iterator is at the `,` before the next value (or `]`). In this state,
62819
//   depth == iter->depth, at_start == false, and error == SUCCESS.
62820
// - Unfinished Business: When we hand an array/object to the user which they do not fully
62821
//   iterate over, we need to finish that iteration by skipping child values until we reach the
62822
//   Next state. In this state, depth > iter->depth, at_start == false, and error == SUCCESS.
62823
//
62824
// ## Error States
62825
//
62826
// In error states, we will yield exactly one more value before stopping. iter->depth == depth
62827
// and at_start is always false. We decrement after yielding the error, moving to the Finished
62828
// state.
62829
//
62830
// - Chained Error: When the array iterator is part of an error chain--for example, in
62831
//   `for (auto tweet : doc["tweets"])`, where the tweet element may be missing or not be an
62832
//   array--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
62833
//   iter->depth == depth, and at_start == false. We decrement depth when we yield the error.
62834
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between elements,
62835
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
62836
//   error == TAPE_ERROR, iter->depth == depth, and at_start == false.
62837
//
62838
// ## Terminal State
62839
//
62840
// The terminal state has iter->depth < depth. at_start is always false.
62841
//
62842
// - Finished: When we have reached a `]` or have reported an error, we are finished. We signal this
62843
//   by decrementing depth. In this state, iter->depth < depth, at_start == false, and
62844
//   error == SUCCESS.
62845
//
62846
62847
simdjson_inline array::array(const value_iterator &_iter) noexcept
62848
  : iter{_iter}
62849
{
62850
}
62851
62852
simdjson_inline simdjson_result<array> array::start(value_iterator &iter) noexcept {
62853
  // We don't need to know if the array is empty to start iteration, but we do want to know if there
62854
  // is an error--thus `simdjson_unused`.
62855
  simdjson_unused bool has_value;
62856
  SIMDJSON_TRY( iter.start_array().get(has_value) );
62857
  return array(iter);
62858
}
62859
simdjson_inline simdjson_result<array> array::start_root(value_iterator &iter) noexcept {
62860
  simdjson_unused bool has_value;
62861
  SIMDJSON_TRY( iter.start_root_array().get(has_value) );
62862
  return array(iter);
62863
}
62864
simdjson_inline simdjson_result<array> array::started(value_iterator &iter) noexcept {
62865
  bool has_value;
62866
  SIMDJSON_TRY(iter.started_array().get(has_value));
62867
  return array(iter);
62868
}
62869
62870
simdjson_inline simdjson_result<array_iterator> array::begin() noexcept {
62871
#if SIMDJSON_DEVELOPMENT_CHECKS
62872
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
62873
#endif
62874
  return array_iterator(iter);
62875
}
62876
simdjson_inline simdjson_result<array_iterator> array::end() noexcept {
62877
  return array_iterator(iter);
62878
}
62879
simdjson_inline error_code array::consume() noexcept {
62880
  auto error = iter.json_iter().skip_child(iter.depth()-1);
62881
  if(error) { iter.abandon(); }
62882
  return error;
62883
}
62884
62885
simdjson_inline simdjson_result<std::string_view> array::raw_json() noexcept {
62886
  const uint8_t * starting_point{iter.peek_start()};
62887
  auto error = consume();
62888
  if(error) { return error; }
62889
  // After 'consume()', we could be left pointing just beyond the document, but that
62890
  // is ok because we are not going to dereference the final pointer position, we just
62891
  // use it to compute the length in bytes.
62892
  const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
62893
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
62894
}
62895
62896
SIMDJSON_PUSH_DISABLE_WARNINGS
62897
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
62898
simdjson_inline simdjson_result<size_t> array::count_elements() & noexcept {
62899
  size_t count{0};
62900
  // Important: we do not consume any of the values.
62901
  for(simdjson_unused auto v : *this) { count++; }
62902
  // The above loop will always succeed, but we want to report errors.
62903
  if(iter.error()) { return iter.error(); }
62904
  // We need to move back at the start because we expect users to iterate through
62905
  // the array after counting the number of elements.
62906
  iter.reset_array();
62907
  return count;
62908
}
62909
SIMDJSON_POP_DISABLE_WARNINGS
62910
62911
simdjson_inline simdjson_result<bool> array::is_empty() & noexcept {
62912
  bool is_not_empty;
62913
  auto error = iter.reset_array().get(is_not_empty);
62914
  if(error) { return error; }
62915
  return !is_not_empty;
62916
}
62917
62918
inline simdjson_result<bool> array::reset() & noexcept {
62919
  return iter.reset_array();
62920
}
62921
62922
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
62923
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
62924
  json_pointer = json_pointer.substr(1);
62925
  // - means "the append position" or "the element after the end of the array"
62926
  // We don't support this, because we're returning a real element, not a position.
62927
  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
62928
62929
  // Read the array index
62930
  size_t array_index = 0;
62931
  size_t i;
62932
  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
62933
    uint8_t digit = uint8_t(json_pointer[i] - '0');
62934
    // Check for non-digit in array index. If it's there, we're trying to get a field in an object
62935
    if (digit > 9) { return INCORRECT_TYPE; }
62936
    array_index = array_index*10 + digit;
62937
  }
62938
62939
  // 0 followed by other digits is invalid
62940
  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
62941
62942
  // Empty string is invalid; so is a "/" with no digits before it
62943
  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
62944
  // Get the child
62945
  auto child = at(array_index);
62946
  // If there is an error, it ends here
62947
  if(child.error()) {
62948
    return child;
62949
  }
62950
62951
  // If there is a /, we're not done yet, call recursively.
62952
  if (i < json_pointer.length()) {
62953
    child = child.at_pointer(json_pointer.substr(i));
62954
  }
62955
  return child;
62956
}
62957
62958
inline std::string json_path_to_pointer_conversion(std::string_view json_path) {
62959
  if (json_path.empty() || (json_path.front() != '.' &&
62960
      json_path.front() != '[')) {
62961
    return "-1"; // This is just a sentinel value, the caller should check for this and return an error.
62962
  }
62963
62964
  std::string result;
62965
  // Reserve space to reduce allocations, adjusting for potential increases due
62966
  // to escaping.
62967
  result.reserve(json_path.size() * 2);
62968
62969
  size_t i = 0;
62970
62971
  while (i < json_path.length()) {
62972
    if (json_path[i] == '.') {
62973
      result += '/';
62974
    } else if (json_path[i] == '[') {
62975
      result += '/';
62976
      ++i; // Move past the '['
62977
      while (i < json_path.length() && json_path[i] != ']') {
62978
          if (json_path[i] == '~') {
62979
            result += "~0";
62980
          } else if (json_path[i] == '/') {
62981
            result += "~1";
62982
          } else {
62983
            result += json_path[i];
62984
          }
62985
          ++i;
62986
      }
62987
      if (i == json_path.length() || json_path[i] != ']') {
62988
          return "-1"; // Using sentinel value that will be handled as an error by the caller.
62989
      }
62990
    } else {
62991
      if (json_path[i] == '~') {
62992
          result += "~0";
62993
      } else if (json_path[i] == '/') {
62994
          result += "~1";
62995
      } else {
62996
          result += json_path[i];
62997
      }
62998
    }
62999
    ++i;
63000
  }
63001
63002
  return result;
63003
}
63004
63005
inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept {
63006
  auto json_pointer = json_path_to_pointer_conversion(json_path);
63007
  if (json_pointer == "-1") { return INVALID_JSON_POINTER; }
63008
  return at_pointer(json_pointer);
63009
}
63010
63011
simdjson_inline simdjson_result<value> array::at(size_t index) noexcept {
63012
  size_t i = 0;
63013
  for (auto value : *this) {
63014
    if (i == index) { return value; }
63015
    i++;
63016
  }
63017
  return INDEX_OUT_OF_BOUNDS;
63018
}
63019
63020
} // namespace ondemand
63021
} // namespace icelake
63022
} // namespace simdjson
63023
63024
namespace simdjson {
63025
63026
simdjson_inline simdjson_result<icelake::ondemand::array>::simdjson_result(
63027
  icelake::ondemand::array &&value
63028
) noexcept
63029
  : implementation_simdjson_result_base<icelake::ondemand::array>(
63030
      std::forward<icelake::ondemand::array>(value)
63031
    )
63032
{
63033
}
63034
simdjson_inline simdjson_result<icelake::ondemand::array>::simdjson_result(
63035
  error_code error
63036
) noexcept
63037
  : implementation_simdjson_result_base<icelake::ondemand::array>(error)
63038
{
63039
}
63040
63041
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::array>::begin() noexcept {
63042
  if (error()) { return error(); }
63043
  return first.begin();
63044
}
63045
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::array>::end() noexcept {
63046
  if (error()) { return error(); }
63047
  return first.end();
63048
}
63049
simdjson_inline  simdjson_result<size_t> simdjson_result<icelake::ondemand::array>::count_elements() & noexcept {
63050
  if (error()) { return error(); }
63051
  return first.count_elements();
63052
}
63053
simdjson_inline  simdjson_result<bool> simdjson_result<icelake::ondemand::array>::is_empty() & noexcept {
63054
  if (error()) { return error(); }
63055
  return first.is_empty();
63056
}
63057
simdjson_inline  simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::array>::at(size_t index) noexcept {
63058
  if (error()) { return error(); }
63059
  return first.at(index);
63060
}
63061
simdjson_inline  simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::array>::at_pointer(std::string_view json_pointer) noexcept {
63062
  if (error()) { return error(); }
63063
  return first.at_pointer(json_pointer);
63064
}
63065
simdjson_inline  simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::array>::at_path(std::string_view json_path) noexcept {
63066
  if (error()) { return error(); }
63067
  return first.at_path(json_path);
63068
}
63069
simdjson_inline  simdjson_result<std::string_view> simdjson_result<icelake::ondemand::array>::raw_json() noexcept {
63070
  if (error()) { return error(); }
63071
  return first.raw_json();
63072
}
63073
} // namespace simdjson
63074
63075
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
63076
/* end file simdjson/generic/ondemand/array-inl.h for icelake */
63077
/* including simdjson/generic/ondemand/array_iterator-inl.h for icelake: #include "simdjson/generic/ondemand/array_iterator-inl.h" */
63078
/* begin file simdjson/generic/ondemand/array_iterator-inl.h for icelake */
63079
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
63080
63081
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
63082
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H */
63083
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
63084
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
63085
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
63086
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
63087
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
63088
63089
namespace simdjson {
63090
namespace icelake {
63091
namespace ondemand {
63092
63093
simdjson_inline array_iterator::array_iterator(const value_iterator &_iter) noexcept
63094
  : iter{_iter}
63095
{}
63096
63097
simdjson_inline simdjson_result<value> array_iterator::operator*() noexcept {
63098
  if (iter.error()) { iter.abandon(); return iter.error(); }
63099
  return value(iter.child());
63100
}
63101
simdjson_inline bool array_iterator::operator==(const array_iterator &other) const noexcept {
63102
  return !(*this != other);
63103
}
63104
simdjson_inline bool array_iterator::operator!=(const array_iterator &) const noexcept {
63105
  return iter.is_open();
63106
}
63107
simdjson_inline array_iterator &array_iterator::operator++() noexcept {
63108
  error_code error;
63109
  // PERF NOTE this is a safety rail ... users should exit loops as soon as they receive an error, so we'll never get here.
63110
  // However, it does not seem to make a perf difference, so we add it out of an abundance of caution.
63111
  if (( error = iter.error() )) { return *this; }
63112
  if (( error = iter.skip_child() )) { return *this; }
63113
  if (( error = iter.has_next_element().error() )) { return *this; }
63114
  return *this;
63115
}
63116
63117
} // namespace ondemand
63118
} // namespace icelake
63119
} // namespace simdjson
63120
63121
namespace simdjson {
63122
63123
simdjson_inline simdjson_result<icelake::ondemand::array_iterator>::simdjson_result(
63124
  icelake::ondemand::array_iterator &&value
63125
) noexcept
63126
  : icelake::implementation_simdjson_result_base<icelake::ondemand::array_iterator>(std::forward<icelake::ondemand::array_iterator>(value))
63127
{
63128
  first.iter.assert_is_valid();
63129
}
63130
simdjson_inline simdjson_result<icelake::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
63131
  : icelake::implementation_simdjson_result_base<icelake::ondemand::array_iterator>({}, error)
63132
{
63133
}
63134
63135
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::array_iterator>::operator*() noexcept {
63136
  if (error()) { return error(); }
63137
  return *first;
63138
}
63139
simdjson_inline bool simdjson_result<icelake::ondemand::array_iterator>::operator==(const simdjson_result<icelake::ondemand::array_iterator> &other) const noexcept {
63140
  if (!first.iter.is_valid()) { return !error(); }
63141
  return first == other.first;
63142
}
63143
simdjson_inline bool simdjson_result<icelake::ondemand::array_iterator>::operator!=(const simdjson_result<icelake::ondemand::array_iterator> &other) const noexcept {
63144
  if (!first.iter.is_valid()) { return error(); }
63145
  return first != other.first;
63146
}
63147
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> &simdjson_result<icelake::ondemand::array_iterator>::operator++() noexcept {
63148
  // Clear the error if there is one, so we don't yield it twice
63149
  if (error()) { second = SUCCESS; return *this; }
63150
  ++(first);
63151
  return *this;
63152
}
63153
63154
} // namespace simdjson
63155
63156
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
63157
/* end file simdjson/generic/ondemand/array_iterator-inl.h for icelake */
63158
/* including simdjson/generic/ondemand/document-inl.h for icelake: #include "simdjson/generic/ondemand/document-inl.h" */
63159
/* begin file simdjson/generic/ondemand/document-inl.h for icelake */
63160
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
63161
63162
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
63163
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */
63164
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
63165
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */
63166
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
63167
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
63168
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
63169
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
63170
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
63171
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
63172
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */
63173
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
63174
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
63175
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
63176
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
63177
63178
namespace simdjson {
63179
namespace icelake {
63180
namespace ondemand {
63181
63182
simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept
63183
  : iter{std::forward<json_iterator>(_iter)}
63184
{
63185
  logger::log_start_value(iter, "document");
63186
}
63187
63188
simdjson_inline document document::start(json_iterator &&iter) noexcept {
63189
  return document(std::forward<json_iterator>(iter));
63190
}
63191
63192
inline void document::rewind() noexcept {
63193
  iter.rewind();
63194
}
63195
63196
inline std::string document::to_debug_string() noexcept {
63197
  return iter.to_string();
63198
}
63199
63200
inline simdjson_result<const char *> document::current_location() const noexcept {
63201
  return iter.current_location();
63202
}
63203
63204
inline int32_t document::current_depth() const noexcept {
63205
  return iter.depth();
63206
}
63207
63208
inline bool document::at_end() const noexcept {
63209
  return iter.at_end();
63210
}
63211
63212
63213
inline bool document::is_alive() noexcept {
63214
  return iter.is_alive();
63215
}
63216
simdjson_inline value_iterator document::resume_value_iterator() noexcept {
63217
  return value_iterator(&iter, 1, iter.root_position());
63218
}
63219
simdjson_inline value_iterator document::get_root_value_iterator() noexcept {
63220
  return resume_value_iterator();
63221
}
63222
simdjson_inline simdjson_result<object> document::start_or_resume_object() noexcept {
63223
  if (iter.at_root()) {
63224
    return get_object();
63225
  } else {
63226
    return object::resume(resume_value_iterator());
63227
  }
63228
}
63229
simdjson_inline simdjson_result<value> document::get_value() noexcept {
63230
  // Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
63231
  // gets called.
63232
63233
  // It is the convention throughout the code that  the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether
63234
  // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error.
63235
#if SIMDJSON_DEVELOPMENT_CHECKS
63236
  if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; }
63237
#endif
63238
  // assert_at_root() serves two purposes: in Debug mode, whether or not
63239
  // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of
63240
  // the document (this will typically be redundant). In release mode, it generates
63241
  // SIMDJSON_ASSUME statements to allow the compiler to make assumptions.
63242
  iter.assert_at_root();
63243
  switch (*iter.peek()) {
63244
    case '[': {
63245
      // The following lines check that the document ends with ].
63246
      auto value_iterator = get_root_value_iterator();
63247
      auto error = value_iterator.check_root_array();
63248
      if(error) { return error; }
63249
      return value(get_root_value_iterator());
63250
    }
63251
    case '{': {
63252
      // The following lines would check that the document ends with }.
63253
      auto value_iterator = get_root_value_iterator();
63254
      auto error = value_iterator.check_root_object();
63255
      if(error) { return error; }
63256
      return value(get_root_value_iterator());
63257
    }
63258
    default:
63259
      // Unfortunately, scalar documents are a special case in simdjson and they cannot
63260
      // be safely converted to value instances.
63261
      return SCALAR_DOCUMENT_AS_VALUE;
63262
  }
63263
}
63264
simdjson_inline simdjson_result<array> document::get_array() & noexcept {
63265
  auto value = get_root_value_iterator();
63266
  return array::start_root(value);
63267
}
63268
simdjson_inline simdjson_result<object> document::get_object() & noexcept {
63269
  auto value = get_root_value_iterator();
63270
  return object::start_root(value);
63271
}
63272
63273
/**
63274
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
63275
 * give an error, so we check for trailing content. We want to disallow trailing
63276
 * content.
63277
 * Thus, in several implementations below, we pass a 'true' parameter value to
63278
 * a get_root_value_iterator() method: this indicates that we disallow trailing content.
63279
 */
63280
63281
simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
63282
  return get_root_value_iterator().get_root_uint64(true);
63283
}
63284
simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
63285
  return get_root_value_iterator().get_root_uint64_in_string(true);
63286
}
63287
simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
63288
  return get_root_value_iterator().get_root_int64(true);
63289
}
63290
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
63291
  return get_root_value_iterator().get_root_int64_in_string(true);
63292
}
63293
simdjson_inline simdjson_result<double> document::get_double() noexcept {
63294
  return get_root_value_iterator().get_root_double(true);
63295
}
63296
simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
63297
  return get_root_value_iterator().get_root_double_in_string(true);
63298
}
63299
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
63300
  return get_root_value_iterator().get_root_string(true, allow_replacement);
63301
}
63302
template <typename string_type>
63303
simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
63304
  return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
63305
}
63306
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
63307
  return get_root_value_iterator().get_root_wobbly_string(true);
63308
}
63309
simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
63310
  return get_root_value_iterator().get_root_raw_json_string(true);
63311
}
63312
simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
63313
  return get_root_value_iterator().get_root_bool(true);
63314
}
63315
simdjson_inline simdjson_result<bool> document::is_null() noexcept {
63316
  return get_root_value_iterator().is_root_null(true);
63317
}
63318
63319
template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
63320
template<> simdjson_inline simdjson_result<object> document::get() & noexcept { return get_object(); }
63321
template<> simdjson_inline simdjson_result<raw_json_string> document::get() & noexcept { return get_raw_json_string(); }
63322
template<> simdjson_inline simdjson_result<std::string_view> document::get() & noexcept { return get_string(false); }
63323
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
63324
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
63325
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
63326
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
63327
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
63328
63329
template<> simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
63330
template<> simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
63331
template<> simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
63332
template<> simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
63333
template<> simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
63334
template<> simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
63335
template<> simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
63336
63337
template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
63338
  return get<T>().get(out);
63339
}
63340
template<typename T> simdjson_inline error_code document::get(T &out) && noexcept {
63341
  return std::forward<document>(*this).get<T>().get(out);
63342
}
63343
63344
#if SIMDJSON_EXCEPTIONS
63345
template <class T>
63346
simdjson_inline document::operator T() noexcept(false) { return get<T>(); }
63347
simdjson_inline document::operator array() & noexcept(false) { return get_array(); }
63348
simdjson_inline document::operator object() & noexcept(false) { return get_object(); }
63349
simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); }
63350
simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); }
63351
simdjson_inline document::operator double() noexcept(false) { return get_double(); }
63352
simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); }
63353
simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
63354
simdjson_inline document::operator bool() noexcept(false) { return get_bool(); }
63355
simdjson_inline document::operator value() noexcept(false) { return get_value(); }
63356
63357
#endif
63358
simdjson_inline simdjson_result<size_t> document::count_elements() & noexcept {
63359
  auto a = get_array();
63360
  simdjson_result<size_t> answer = a.count_elements();
63361
  /* If there was an array, we are now left pointing at its first element. */
63362
  if(answer.error() == SUCCESS) { rewind(); }
63363
  return answer;
63364
}
63365
simdjson_inline simdjson_result<size_t> document::count_fields() & noexcept {
63366
  auto a = get_object();
63367
  simdjson_result<size_t> answer = a.count_fields();
63368
  /* If there was an object, we are now left pointing at its first element. */
63369
  if(answer.error() == SUCCESS) { rewind(); }
63370
  return answer;
63371
}
63372
simdjson_inline simdjson_result<value> document::at(size_t index) & noexcept {
63373
  auto a = get_array();
63374
  return a.at(index);
63375
}
63376
simdjson_inline simdjson_result<array_iterator> document::begin() & noexcept {
63377
  return get_array().begin();
63378
}
63379
simdjson_inline simdjson_result<array_iterator> document::end() & noexcept {
63380
  return {};
63381
}
63382
63383
simdjson_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
63384
  return start_or_resume_object().find_field(key);
63385
}
63386
simdjson_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
63387
  return start_or_resume_object().find_field(key);
63388
}
63389
simdjson_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
63390
  return start_or_resume_object().find_field_unordered(key);
63391
}
63392
simdjson_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
63393
  return start_or_resume_object().find_field_unordered(key);
63394
}
63395
simdjson_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
63396
  return start_or_resume_object()[key];
63397
}
63398
simdjson_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
63399
  return start_or_resume_object()[key];
63400
}
63401
63402
simdjson_inline error_code document::consume() noexcept {
63403
  auto error = iter.skip_child(0);
63404
  if(error) { iter.abandon(); }
63405
  return error;
63406
}
63407
63408
simdjson_inline simdjson_result<std::string_view> document::raw_json() noexcept {
63409
  auto _iter = get_root_value_iterator();
63410
  const uint8_t * starting_point{_iter.peek_start()};
63411
  auto error = consume();
63412
  if(error) { return error; }
63413
  // After 'consume()', we could be left pointing just beyond the document, but that
63414
  // is ok because we are not going to dereference the final pointer position, we just
63415
  // use it to compute the length in bytes.
63416
  const uint8_t * final_point{iter.unsafe_pointer()};
63417
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
63418
}
63419
63420
simdjson_inline simdjson_result<json_type> document::type() noexcept {
63421
  return get_root_value_iterator().type();
63422
}
63423
63424
simdjson_inline simdjson_result<bool> document::is_scalar() noexcept {
63425
  json_type this_type;
63426
  auto error = type().get(this_type);
63427
  if(error) { return error; }
63428
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
63429
}
63430
63431
simdjson_inline simdjson_result<bool> document::is_string() noexcept {
63432
  json_type this_type;
63433
  auto error = type().get(this_type);
63434
  if(error) { return error; }
63435
  return (this_type == json_type::string);
63436
}
63437
63438
simdjson_inline bool document::is_negative() noexcept {
63439
  return get_root_value_iterator().is_root_negative();
63440
}
63441
63442
simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
63443
  return get_root_value_iterator().is_root_integer(true);
63444
}
63445
63446
simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
63447
  return get_root_value_iterator().get_root_number_type(true);
63448
}
63449
63450
simdjson_inline simdjson_result<number> document::get_number() noexcept {
63451
  return get_root_value_iterator().get_root_number(true);
63452
}
63453
63454
63455
simdjson_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
63456
  auto _iter = get_root_value_iterator();
63457
  return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_root_length());
63458
}
63459
63460
simdjson_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
63461
  rewind(); // Rewind the document each time at_pointer is called
63462
  if (json_pointer.empty()) {
63463
    return this->get_value();
63464
  }
63465
  json_type t;
63466
  SIMDJSON_TRY(type().get(t));
63467
  switch (t)
63468
  {
63469
    case json_type::array:
63470
      return (*this).get_array().at_pointer(json_pointer);
63471
    case json_type::object:
63472
      return (*this).get_object().at_pointer(json_pointer);
63473
    default:
63474
      return INVALID_JSON_POINTER;
63475
  }
63476
}
63477
63478
simdjson_inline simdjson_result<value> document::at_path(std::string_view json_path) noexcept {
63479
  rewind(); // Rewind the document each time at_pointer is called
63480
  if (json_path.empty()) {
63481
      return this->get_value();
63482
  }
63483
  json_type t;
63484
  SIMDJSON_TRY(type().get(t));
63485
  switch (t) {
63486
  case json_type::array:
63487
      return (*this).get_array().at_path(json_path);
63488
  case json_type::object:
63489
      return (*this).get_object().at_path(json_path);
63490
  default:
63491
      return INVALID_JSON_POINTER;
63492
  }
63493
}
63494
63495
} // namespace ondemand
63496
} // namespace icelake
63497
} // namespace simdjson
63498
63499
namespace simdjson {
63500
63501
simdjson_inline simdjson_result<icelake::ondemand::document>::simdjson_result(
63502
  icelake::ondemand::document &&value
63503
) noexcept :
63504
    implementation_simdjson_result_base<icelake::ondemand::document>(
63505
      std::forward<icelake::ondemand::document>(value)
63506
    )
63507
{
63508
}
63509
simdjson_inline simdjson_result<icelake::ondemand::document>::simdjson_result(
63510
  error_code error
63511
) noexcept :
63512
    implementation_simdjson_result_base<icelake::ondemand::document>(
63513
      error
63514
    )
63515
{
63516
}
63517
simdjson_inline simdjson_result<size_t> simdjson_result<icelake::ondemand::document>::count_elements() & noexcept {
63518
  if (error()) { return error(); }
63519
  return first.count_elements();
63520
}
63521
simdjson_inline simdjson_result<size_t> simdjson_result<icelake::ondemand::document>::count_fields() & noexcept {
63522
  if (error()) { return error(); }
63523
  return first.count_fields();
63524
}
63525
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::at(size_t index) & noexcept {
63526
  if (error()) { return error(); }
63527
  return first.at(index);
63528
}
63529
simdjson_inline error_code simdjson_result<icelake::ondemand::document>::rewind() noexcept {
63530
  if (error()) { return error(); }
63531
  first.rewind();
63532
  return SUCCESS;
63533
}
63534
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::document>::begin() & noexcept {
63535
  if (error()) { return error(); }
63536
  return first.begin();
63537
}
63538
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::document>::end() & noexcept {
63539
  return {};
63540
}
63541
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
63542
  if (error()) { return error(); }
63543
  return first.find_field_unordered(key);
63544
}
63545
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::find_field_unordered(const char *key) & noexcept {
63546
  if (error()) { return error(); }
63547
  return first.find_field_unordered(key);
63548
}
63549
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::operator[](std::string_view key) & noexcept {
63550
  if (error()) { return error(); }
63551
  return first[key];
63552
}
63553
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::operator[](const char *key) & noexcept {
63554
  if (error()) { return error(); }
63555
  return first[key];
63556
}
63557
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::find_field(std::string_view key) & noexcept {
63558
  if (error()) { return error(); }
63559
  return first.find_field(key);
63560
}
63561
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::find_field(const char *key) & noexcept {
63562
  if (error()) { return error(); }
63563
  return first.find_field(key);
63564
}
63565
simdjson_inline simdjson_result<icelake::ondemand::array> simdjson_result<icelake::ondemand::document>::get_array() & noexcept {
63566
  if (error()) { return error(); }
63567
  return first.get_array();
63568
}
63569
simdjson_inline simdjson_result<icelake::ondemand::object> simdjson_result<icelake::ondemand::document>::get_object() & noexcept {
63570
  if (error()) { return error(); }
63571
  return first.get_object();
63572
}
63573
simdjson_inline simdjson_result<uint64_t> simdjson_result<icelake::ondemand::document>::get_uint64() noexcept {
63574
  if (error()) { return error(); }
63575
  return first.get_uint64();
63576
}
63577
simdjson_inline simdjson_result<uint64_t> simdjson_result<icelake::ondemand::document>::get_uint64_in_string() noexcept {
63578
  if (error()) { return error(); }
63579
  return first.get_uint64_in_string();
63580
}
63581
simdjson_inline simdjson_result<int64_t> simdjson_result<icelake::ondemand::document>::get_int64() noexcept {
63582
  if (error()) { return error(); }
63583
  return first.get_int64();
63584
}
63585
simdjson_inline simdjson_result<int64_t> simdjson_result<icelake::ondemand::document>::get_int64_in_string() noexcept {
63586
  if (error()) { return error(); }
63587
  return first.get_int64_in_string();
63588
}
63589
simdjson_inline simdjson_result<double> simdjson_result<icelake::ondemand::document>::get_double() noexcept {
63590
  if (error()) { return error(); }
63591
  return first.get_double();
63592
}
63593
simdjson_inline simdjson_result<double> simdjson_result<icelake::ondemand::document>::get_double_in_string() noexcept {
63594
  if (error()) { return error(); }
63595
  return first.get_double_in_string();
63596
}
63597
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::document>::get_string(bool allow_replacement) noexcept {
63598
  if (error()) { return error(); }
63599
  return first.get_string(allow_replacement);
63600
}
63601
template <typename string_type>
63602
simdjson_inline error_code simdjson_result<icelake::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
63603
  if (error()) { return error(); }
63604
  return first.get_string(receiver, allow_replacement);
63605
}
63606
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::document>::get_wobbly_string() noexcept {
63607
  if (error()) { return error(); }
63608
  return first.get_wobbly_string();
63609
}
63610
simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> simdjson_result<icelake::ondemand::document>::get_raw_json_string() noexcept {
63611
  if (error()) { return error(); }
63612
  return first.get_raw_json_string();
63613
}
63614
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document>::get_bool() noexcept {
63615
  if (error()) { return error(); }
63616
  return first.get_bool();
63617
}
63618
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::get_value() noexcept {
63619
  if (error()) { return error(); }
63620
  return first.get_value();
63621
}
63622
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document>::is_null() noexcept {
63623
  if (error()) { return error(); }
63624
  return first.is_null();
63625
}
63626
63627
template<typename T>
63628
simdjson_inline simdjson_result<T> simdjson_result<icelake::ondemand::document>::get() & noexcept {
63629
  if (error()) { return error(); }
63630
  return first.get<T>();
63631
}
63632
template<typename T>
63633
simdjson_inline simdjson_result<T> simdjson_result<icelake::ondemand::document>::get() && noexcept {
63634
  if (error()) { return error(); }
63635
  return std::forward<icelake::ondemand::document>(first).get<T>();
63636
}
63637
template<typename T>
63638
simdjson_inline error_code simdjson_result<icelake::ondemand::document>::get(T &out) & noexcept {
63639
  if (error()) { return error(); }
63640
  return first.get<T>(out);
63641
}
63642
template<typename T>
63643
simdjson_inline error_code simdjson_result<icelake::ondemand::document>::get(T &out) && noexcept {
63644
  if (error()) { return error(); }
63645
  return std::forward<icelake::ondemand::document>(first).get<T>(out);
63646
}
63647
63648
template<> simdjson_inline simdjson_result<icelake::ondemand::document> simdjson_result<icelake::ondemand::document>::get<icelake::ondemand::document>() & noexcept = delete;
63649
template<> simdjson_inline simdjson_result<icelake::ondemand::document> simdjson_result<icelake::ondemand::document>::get<icelake::ondemand::document>() && noexcept {
63650
  if (error()) { return error(); }
63651
  return std::forward<icelake::ondemand::document>(first);
63652
}
63653
template<> simdjson_inline error_code simdjson_result<icelake::ondemand::document>::get<icelake::ondemand::document>(icelake::ondemand::document &out) & noexcept = delete;
63654
template<> simdjson_inline error_code simdjson_result<icelake::ondemand::document>::get<icelake::ondemand::document>(icelake::ondemand::document &out) && noexcept {
63655
  if (error()) { return error(); }
63656
  out = std::forward<icelake::ondemand::document>(first);
63657
  return SUCCESS;
63658
}
63659
63660
simdjson_inline simdjson_result<icelake::ondemand::json_type> simdjson_result<icelake::ondemand::document>::type() noexcept {
63661
  if (error()) { return error(); }
63662
  return first.type();
63663
}
63664
63665
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document>::is_scalar() noexcept {
63666
  if (error()) { return error(); }
63667
  return first.is_scalar();
63668
}
63669
63670
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document>::is_string() noexcept {
63671
  if (error()) { return error(); }
63672
  return first.is_string();
63673
}
63674
63675
simdjson_inline bool simdjson_result<icelake::ondemand::document>::is_negative() noexcept {
63676
  if (error()) { return error(); }
63677
  return first.is_negative();
63678
}
63679
63680
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document>::is_integer() noexcept {
63681
  if (error()) { return error(); }
63682
  return first.is_integer();
63683
}
63684
63685
simdjson_inline simdjson_result<icelake::number_type> simdjson_result<icelake::ondemand::document>::get_number_type() noexcept {
63686
  if (error()) { return error(); }
63687
  return first.get_number_type();
63688
}
63689
63690
simdjson_inline simdjson_result<icelake::ondemand::number> simdjson_result<icelake::ondemand::document>::get_number() noexcept {
63691
  if (error()) { return error(); }
63692
  return first.get_number();
63693
}
63694
63695
63696
#if SIMDJSON_EXCEPTIONS
63697
template <class T, typename std::enable_if<std::is_same<T, icelake::ondemand::document>::value == false>::type>
63698
simdjson_inline simdjson_result<icelake::ondemand::document>::operator T() noexcept(false) {
63699
  if (error()) { throw simdjson_error(error()); }
63700
  return first;
63701
}
63702
simdjson_inline simdjson_result<icelake::ondemand::document>::operator icelake::ondemand::array() & noexcept(false) {
63703
  if (error()) { throw simdjson_error(error()); }
63704
  return first;
63705
}
63706
simdjson_inline simdjson_result<icelake::ondemand::document>::operator icelake::ondemand::object() & noexcept(false) {
63707
  if (error()) { throw simdjson_error(error()); }
63708
  return first;
63709
}
63710
simdjson_inline simdjson_result<icelake::ondemand::document>::operator uint64_t() noexcept(false) {
63711
  if (error()) { throw simdjson_error(error()); }
63712
  return first;
63713
}
63714
simdjson_inline simdjson_result<icelake::ondemand::document>::operator int64_t() noexcept(false) {
63715
  if (error()) { throw simdjson_error(error()); }
63716
  return first;
63717
}
63718
simdjson_inline simdjson_result<icelake::ondemand::document>::operator double() noexcept(false) {
63719
  if (error()) { throw simdjson_error(error()); }
63720
  return first;
63721
}
63722
simdjson_inline simdjson_result<icelake::ondemand::document>::operator std::string_view() noexcept(false) {
63723
  if (error()) { throw simdjson_error(error()); }
63724
  return first;
63725
}
63726
simdjson_inline simdjson_result<icelake::ondemand::document>::operator icelake::ondemand::raw_json_string() noexcept(false) {
63727
  if (error()) { throw simdjson_error(error()); }
63728
  return first;
63729
}
63730
simdjson_inline simdjson_result<icelake::ondemand::document>::operator bool() noexcept(false) {
63731
  if (error()) { throw simdjson_error(error()); }
63732
  return first;
63733
}
63734
simdjson_inline simdjson_result<icelake::ondemand::document>::operator icelake::ondemand::value() noexcept(false) {
63735
  if (error()) { throw simdjson_error(error()); }
63736
  return first;
63737
}
63738
#endif
63739
63740
63741
simdjson_inline simdjson_result<const char *> simdjson_result<icelake::ondemand::document>::current_location() noexcept {
63742
  if (error()) { return error(); }
63743
  return first.current_location();
63744
}
63745
63746
simdjson_inline bool simdjson_result<icelake::ondemand::document>::at_end() const noexcept {
63747
  if (error()) { return error(); }
63748
  return first.at_end();
63749
}
63750
63751
63752
simdjson_inline int32_t simdjson_result<icelake::ondemand::document>::current_depth() const noexcept {
63753
  if (error()) { return error(); }
63754
  return first.current_depth();
63755
}
63756
63757
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::document>::raw_json_token() noexcept {
63758
  if (error()) { return error(); }
63759
  return first.raw_json_token();
63760
}
63761
63762
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::at_pointer(std::string_view json_pointer) noexcept {
63763
  if (error()) { return error(); }
63764
  return first.at_pointer(json_pointer);
63765
}
63766
63767
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document>::at_path(std::string_view json_path) noexcept {
63768
  if (error()) { return error(); }
63769
  return first.at_path(json_path);
63770
}
63771
63772
} // namespace simdjson
63773
63774
63775
namespace simdjson {
63776
namespace icelake {
63777
namespace ondemand {
63778
63779
simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {}
63780
simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
63781
simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
63782
simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
63783
simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
63784
/**
63785
 * The document_reference instances are used primarily/solely for streams of JSON
63786
 * documents.
63787
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
63788
 * give an error, so we check for trailing content.
63789
 *
63790
 * However, for streams of JSON documents, we want to be able to start from
63791
 * "321" "321" "321"
63792
 * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
63793
 * successfully each time.
63794
 *
63795
 * To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
63796
 * this indicates that we allow trailing content.
63797
 */
63798
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
63799
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
63800
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
63801
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
63802
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
63803
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
63804
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
63805
template <typename string_type>
63806
simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
63807
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
63808
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
63809
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
63810
simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
63811
simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
63812
template<> simdjson_inline simdjson_result<array> document_reference::get() & noexcept { return get_array(); }
63813
template<> simdjson_inline simdjson_result<object> document_reference::get() & noexcept { return get_object(); }
63814
template<> simdjson_inline simdjson_result<raw_json_string> document_reference::get() & noexcept { return get_raw_json_string(); }
63815
template<> simdjson_inline simdjson_result<std::string_view> document_reference::get() & noexcept { return get_string(false); }
63816
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
63817
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
63818
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
63819
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
63820
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
63821
#if SIMDJSON_EXCEPTIONS
63822
template <class T>
63823
simdjson_inline document_reference::operator T() noexcept(false) { return get<T>(); }
63824
simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
63825
simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
63826
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
63827
simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
63828
simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
63829
simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
63830
simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
63831
simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
63832
simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
63833
#endif
63834
simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
63835
simdjson_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
63836
simdjson_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
63837
simdjson_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
63838
simdjson_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
63839
simdjson_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
63840
simdjson_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
63841
simdjson_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
63842
simdjson_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
63843
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
63844
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
63845
simdjson_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
63846
simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
63847
simdjson_inline simdjson_result<bool> document_reference::is_string() noexcept { return doc->is_string(); }
63848
simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
63849
simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
63850
simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
63851
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
63852
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
63853
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
63854
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
63855
simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
63856
simdjson_inline simdjson_result<value> document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); }
63857
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
63858
simdjson_inline document_reference::operator document&() const noexcept { return *doc; }
63859
63860
} // namespace ondemand
63861
} // namespace icelake
63862
} // namespace simdjson
63863
63864
63865
63866
namespace simdjson {
63867
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::simdjson_result(icelake::ondemand::document_reference value, error_code error)
63868
  noexcept : implementation_simdjson_result_base<icelake::ondemand::document_reference>(std::forward<icelake::ondemand::document_reference>(value), error) {}
63869
63870
63871
simdjson_inline simdjson_result<size_t> simdjson_result<icelake::ondemand::document_reference>::count_elements() & noexcept {
63872
  if (error()) { return error(); }
63873
  return first.count_elements();
63874
}
63875
simdjson_inline simdjson_result<size_t> simdjson_result<icelake::ondemand::document_reference>::count_fields() & noexcept {
63876
  if (error()) { return error(); }
63877
  return first.count_fields();
63878
}
63879
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::at(size_t index) & noexcept {
63880
  if (error()) { return error(); }
63881
  return first.at(index);
63882
}
63883
simdjson_inline error_code simdjson_result<icelake::ondemand::document_reference>::rewind() noexcept {
63884
  if (error()) { return error(); }
63885
  first.rewind();
63886
  return SUCCESS;
63887
}
63888
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::document_reference>::begin() & noexcept {
63889
  if (error()) { return error(); }
63890
  return first.begin();
63891
}
63892
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::document_reference>::end() & noexcept {
63893
  return {};
63894
}
63895
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
63896
  if (error()) { return error(); }
63897
  return first.find_field_unordered(key);
63898
}
63899
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
63900
  if (error()) { return error(); }
63901
  return first.find_field_unordered(key);
63902
}
63903
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
63904
  if (error()) { return error(); }
63905
  return first[key];
63906
}
63907
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::operator[](const char *key) & noexcept {
63908
  if (error()) { return error(); }
63909
  return first[key];
63910
}
63911
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
63912
  if (error()) { return error(); }
63913
  return first.find_field(key);
63914
}
63915
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::find_field(const char *key) & noexcept {
63916
  if (error()) { return error(); }
63917
  return first.find_field(key);
63918
}
63919
simdjson_inline simdjson_result<icelake::ondemand::array> simdjson_result<icelake::ondemand::document_reference>::get_array() & noexcept {
63920
  if (error()) { return error(); }
63921
  return first.get_array();
63922
}
63923
simdjson_inline simdjson_result<icelake::ondemand::object> simdjson_result<icelake::ondemand::document_reference>::get_object() & noexcept {
63924
  if (error()) { return error(); }
63925
  return first.get_object();
63926
}
63927
simdjson_inline simdjson_result<uint64_t> simdjson_result<icelake::ondemand::document_reference>::get_uint64() noexcept {
63928
  if (error()) { return error(); }
63929
  return first.get_uint64();
63930
}
63931
simdjson_inline simdjson_result<uint64_t> simdjson_result<icelake::ondemand::document_reference>::get_uint64_in_string() noexcept {
63932
  if (error()) { return error(); }
63933
  return first.get_uint64_in_string();
63934
}
63935
simdjson_inline simdjson_result<int64_t> simdjson_result<icelake::ondemand::document_reference>::get_int64() noexcept {
63936
  if (error()) { return error(); }
63937
  return first.get_int64();
63938
}
63939
simdjson_inline simdjson_result<int64_t> simdjson_result<icelake::ondemand::document_reference>::get_int64_in_string() noexcept {
63940
  if (error()) { return error(); }
63941
  return first.get_int64_in_string();
63942
}
63943
simdjson_inline simdjson_result<double> simdjson_result<icelake::ondemand::document_reference>::get_double() noexcept {
63944
  if (error()) { return error(); }
63945
  return first.get_double();
63946
}
63947
simdjson_inline simdjson_result<double> simdjson_result<icelake::ondemand::document_reference>::get_double_in_string() noexcept {
63948
  if (error()) { return error(); }
63949
  return first.get_double_in_string();
63950
}
63951
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::document_reference>::get_string(bool allow_replacement) noexcept {
63952
  if (error()) { return error(); }
63953
  return first.get_string(allow_replacement);
63954
}
63955
template <typename string_type>
63956
simdjson_inline error_code simdjson_result<icelake::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
63957
  if (error()) { return error(); }
63958
  return first.get_string(receiver, allow_replacement);
63959
}
63960
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::document_reference>::get_wobbly_string() noexcept {
63961
  if (error()) { return error(); }
63962
  return first.get_wobbly_string();
63963
}
63964
simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> simdjson_result<icelake::ondemand::document_reference>::get_raw_json_string() noexcept {
63965
  if (error()) { return error(); }
63966
  return first.get_raw_json_string();
63967
}
63968
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document_reference>::get_bool() noexcept {
63969
  if (error()) { return error(); }
63970
  return first.get_bool();
63971
}
63972
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::get_value() noexcept {
63973
  if (error()) { return error(); }
63974
  return first.get_value();
63975
}
63976
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document_reference>::is_null() noexcept {
63977
  if (error()) { return error(); }
63978
  return first.is_null();
63979
}
63980
simdjson_inline simdjson_result<icelake::ondemand::json_type> simdjson_result<icelake::ondemand::document_reference>::type() noexcept {
63981
  if (error()) { return error(); }
63982
  return first.type();
63983
}
63984
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document_reference>::is_scalar() noexcept {
63985
  if (error()) { return error(); }
63986
  return first.is_scalar();
63987
}
63988
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document_reference>::is_string() noexcept {
63989
  if (error()) { return error(); }
63990
  return first.is_string();
63991
}
63992
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document_reference>::is_negative() noexcept {
63993
  if (error()) { return error(); }
63994
  return first.is_negative();
63995
}
63996
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::document_reference>::is_integer() noexcept {
63997
  if (error()) { return error(); }
63998
  return first.is_integer();
63999
}
64000
simdjson_inline simdjson_result<icelake::number_type> simdjson_result<icelake::ondemand::document_reference>::get_number_type() noexcept {
64001
  if (error()) { return error(); }
64002
  return first.get_number_type();
64003
}
64004
simdjson_inline simdjson_result<icelake::ondemand::number> simdjson_result<icelake::ondemand::document_reference>::get_number() noexcept {
64005
  if (error()) { return error(); }
64006
  return first.get_number();
64007
}
64008
#if SIMDJSON_EXCEPTIONS
64009
template <class T, typename std::enable_if<std::is_same<T, icelake::ondemand::document_reference>::value == false>::type>
64010
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator T() noexcept(false) {
64011
  if (error()) { throw simdjson_error(error()); }
64012
  return first;
64013
}
64014
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator icelake::ondemand::array() & noexcept(false) {
64015
  if (error()) { throw simdjson_error(error()); }
64016
  return first;
64017
}
64018
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator icelake::ondemand::object() & noexcept(false) {
64019
  if (error()) { throw simdjson_error(error()); }
64020
  return first;
64021
}
64022
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator uint64_t() noexcept(false) {
64023
  if (error()) { throw simdjson_error(error()); }
64024
  return first;
64025
}
64026
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator int64_t() noexcept(false) {
64027
  if (error()) { throw simdjson_error(error()); }
64028
  return first;
64029
}
64030
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator double() noexcept(false) {
64031
  if (error()) { throw simdjson_error(error()); }
64032
  return first;
64033
}
64034
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator std::string_view() noexcept(false) {
64035
  if (error()) { throw simdjson_error(error()); }
64036
  return first;
64037
}
64038
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator icelake::ondemand::raw_json_string() noexcept(false) {
64039
  if (error()) { throw simdjson_error(error()); }
64040
  return first;
64041
}
64042
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator bool() noexcept(false) {
64043
  if (error()) { throw simdjson_error(error()); }
64044
  return first;
64045
}
64046
simdjson_inline simdjson_result<icelake::ondemand::document_reference>::operator icelake::ondemand::value() noexcept(false) {
64047
  if (error()) { throw simdjson_error(error()); }
64048
  return first;
64049
}
64050
#endif
64051
64052
simdjson_inline simdjson_result<const char *> simdjson_result<icelake::ondemand::document_reference>::current_location() noexcept {
64053
  if (error()) { return error(); }
64054
  return first.current_location();
64055
}
64056
64057
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::document_reference>::raw_json_token() noexcept {
64058
  if (error()) { return error(); }
64059
  return first.raw_json_token();
64060
}
64061
64062
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
64063
  if (error()) { return error(); }
64064
  return first.at_pointer(json_pointer);
64065
}
64066
64067
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::document_reference>::at_path(std::string_view json_path) noexcept {
64068
  if (error()) {
64069
      return error();
64070
  }
64071
  return first.at_path(json_path);
64072
}
64073
64074
} // namespace simdjson
64075
64076
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
64077
/* end file simdjson/generic/ondemand/document-inl.h for icelake */
64078
/* including simdjson/generic/ondemand/document_stream-inl.h for icelake: #include "simdjson/generic/ondemand/document_stream-inl.h" */
64079
/* begin file simdjson/generic/ondemand/document_stream-inl.h for icelake */
64080
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
64081
64082
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
64083
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */
64084
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
64085
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
64086
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
64087
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
64088
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
64089
64090
#include <algorithm>
64091
#include <stdexcept>
64092
64093
namespace simdjson {
64094
namespace icelake {
64095
namespace ondemand {
64096
64097
#ifdef SIMDJSON_THREADS_ENABLED
64098
64099
inline void stage1_worker::finish() {
64100
  // After calling "run" someone would call finish() to wait
64101
  // for the end of the processing.
64102
  // This function will wait until either the thread has done
64103
  // the processing or, else, the destructor has been called.
64104
  std::unique_lock<std::mutex> lock(locking_mutex);
64105
  cond_var.wait(lock, [this]{return has_work == false;});
64106
}
64107
64108
inline stage1_worker::~stage1_worker() {
64109
  // The thread may never outlive the stage1_worker instance
64110
  // and will always be stopped/joined before the stage1_worker
64111
  // instance is gone.
64112
  stop_thread();
64113
}
64114
64115
inline void stage1_worker::start_thread() {
64116
  std::unique_lock<std::mutex> lock(locking_mutex);
64117
  if(thread.joinable()) {
64118
    return; // This should never happen but we never want to create more than one thread.
64119
  }
64120
  thread = std::thread([this]{
64121
      while(true) {
64122
        std::unique_lock<std::mutex> thread_lock(locking_mutex);
64123
        // We wait for either "run" or "stop_thread" to be called.
64124
        cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
64125
        // If, for some reason, the stop_thread() method was called (i.e., the
64126
        // destructor of stage1_worker is called, then we want to immediately destroy
64127
        // the thread (and not do any more processing).
64128
        if(!can_work) {
64129
          break;
64130
        }
64131
        this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
64132
              this->_next_batch_start);
64133
        this->has_work = false;
64134
        // The condition variable call should be moved after thread_lock.unlock() for performance
64135
        // reasons but thread sanitizers may report it as a data race if we do.
64136
        // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
64137
        cond_var.notify_one(); // will notify "finish"
64138
        thread_lock.unlock();
64139
      }
64140
    }
64141
  );
64142
}
64143
64144
64145
inline void stage1_worker::stop_thread() {
64146
  std::unique_lock<std::mutex> lock(locking_mutex);
64147
  // We have to make sure that all locks can be released.
64148
  can_work = false;
64149
  has_work = false;
64150
  cond_var.notify_all();
64151
  lock.unlock();
64152
  if(thread.joinable()) {
64153
    thread.join();
64154
  }
64155
}
64156
64157
inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) {
64158
  std::unique_lock<std::mutex> lock(locking_mutex);
64159
  owner = ds;
64160
  _next_batch_start = next_batch_start;
64161
  stage1_thread_parser = stage1;
64162
  has_work = true;
64163
  // The condition variable call should be moved after thread_lock.unlock() for performance
64164
  // reasons but thread sanitizers may report it as a data race if we do.
64165
  // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
64166
  cond_var.notify_one(); // will notify the thread lock that we have work
64167
  lock.unlock();
64168
}
64169
64170
#endif  // SIMDJSON_THREADS_ENABLED
64171
64172
simdjson_inline document_stream::document_stream(
64173
  ondemand::parser &_parser,
64174
  const uint8_t *_buf,
64175
  size_t _len,
64176
  size_t _batch_size,
64177
  bool _allow_comma_separated
64178
) noexcept
64179
  : parser{&_parser},
64180
    buf{_buf},
64181
    len{_len},
64182
    batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
64183
    allow_comma_separated{_allow_comma_separated},
64184
    error{SUCCESS}
64185
    #ifdef SIMDJSON_THREADS_ENABLED
64186
    , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
64187
    #endif
64188
{
64189
#ifdef SIMDJSON_THREADS_ENABLED
64190
  if(worker.get() == nullptr) {
64191
    error = MEMALLOC;
64192
  }
64193
#endif
64194
}
64195
64196
simdjson_inline document_stream::document_stream() noexcept
64197
  : parser{nullptr},
64198
    buf{nullptr},
64199
    len{0},
64200
    batch_size{0},
64201
    allow_comma_separated{false},
64202
    error{UNINITIALIZED}
64203
    #ifdef SIMDJSON_THREADS_ENABLED
64204
    , use_thread(false)
64205
    #endif
64206
{
64207
}
64208
64209
simdjson_inline document_stream::~document_stream() noexcept
64210
{
64211
  #ifdef SIMDJSON_THREADS_ENABLED
64212
  worker.reset();
64213
  #endif
64214
}
64215
64216
inline size_t document_stream::size_in_bytes() const noexcept {
64217
  return len;
64218
}
64219
64220
inline size_t document_stream::truncated_bytes() const noexcept {
64221
  if(error == CAPACITY) { return len - batch_start; }
64222
  return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
64223
}
64224
64225
simdjson_inline document_stream::iterator::iterator() noexcept
64226
  : stream{nullptr}, finished{true} {
64227
}
64228
64229
simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
64230
  : stream{_stream}, finished{is_end} {
64231
}
64232
64233
simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
64234
  //if(stream->error) { return stream->error; }
64235
  return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
64236
}
64237
64238
simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
64239
  // If there is an error, then we want the iterator
64240
  // to be finished, no matter what. (E.g., we do not
64241
  // keep generating documents with errors, or go beyond
64242
  // a document with errors.)
64243
  //
64244
  // Users do not have to call "operator*()" when they use operator++,
64245
  // so we need to end the stream in the operator++ function.
64246
  //
64247
  // Note that setting finished = true is essential otherwise
64248
  // we would enter an infinite loop.
64249
  if (stream->error) { finished = true; }
64250
  // Note that stream->error() is guarded against error conditions
64251
  // (it will immediately return if stream->error casts to false).
64252
  // In effect, this next function does nothing when (stream->error)
64253
  // is true (hence the risk of an infinite loop).
64254
  stream->next();
64255
  // If that was the last document, we're finished.
64256
  // It is the only type of error we do not want to appear
64257
  // in operator*.
64258
  if (stream->error == EMPTY) { finished = true; }
64259
  // If we had any other kind of error (not EMPTY) then we want
64260
  // to pass it along to the operator* and we cannot mark the result
64261
  // as "finished" just yet.
64262
  return *this;
64263
}
64264
64265
simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
64266
  return finished != other.finished;
64267
}
64268
64269
simdjson_inline document_stream::iterator document_stream::begin() noexcept {
64270
  start();
64271
  // If there are no documents, we're finished.
64272
  return iterator(this, error == EMPTY);
64273
}
64274
64275
simdjson_inline document_stream::iterator document_stream::end() noexcept {
64276
  return iterator(this, true);
64277
}
64278
64279
inline void document_stream::start() noexcept {
64280
  if (error) { return; }
64281
  error = parser->allocate(batch_size);
64282
  if (error) { return; }
64283
  // Always run the first stage 1 parse immediately
64284
  batch_start = 0;
64285
  error = run_stage1(*parser, batch_start);
64286
  while(error == EMPTY) {
64287
    // In exceptional cases, we may start with an empty block
64288
    batch_start = next_batch_start();
64289
    if (batch_start >= len) { return; }
64290
    error = run_stage1(*parser, batch_start);
64291
  }
64292
  if (error) { return; }
64293
  doc_index = batch_start;
64294
  doc = document(json_iterator(&buf[batch_start], parser));
64295
  doc.iter._streaming = true;
64296
64297
  #ifdef SIMDJSON_THREADS_ENABLED
64298
  if (use_thread && next_batch_start() < len) {
64299
    // Kick off the first thread on next batch if needed
64300
    error = stage1_thread_parser.allocate(batch_size);
64301
    if (error) { return; }
64302
    worker->start_thread();
64303
    start_stage1_thread();
64304
    if (error) { return; }
64305
  }
64306
  #endif // SIMDJSON_THREADS_ENABLED
64307
}
64308
64309
inline void document_stream::next() noexcept {
64310
  // We always enter at once once in an error condition.
64311
  if (error) { return; }
64312
  next_document();
64313
  if (error) { return; }
64314
  auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get();
64315
  doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index];
64316
64317
  // Check if at end of structural indexes (i.e. at end of batch)
64318
  if(cur_struct_index >= static_cast<int64_t>(parser->implementation->n_structural_indexes)) {
64319
    error = EMPTY;
64320
    // Load another batch (if available)
64321
    while (error == EMPTY) {
64322
      batch_start = next_batch_start();
64323
      if (batch_start >= len) { break; }
64324
      #ifdef SIMDJSON_THREADS_ENABLED
64325
      if(use_thread) {
64326
        load_from_stage1_thread();
64327
      } else {
64328
        error = run_stage1(*parser, batch_start);
64329
      }
64330
      #else
64331
      error = run_stage1(*parser, batch_start);
64332
      #endif
64333
      /**
64334
       * Whenever we move to another window, we need to update all pointers to make
64335
       * it appear as if the input buffer started at the beginning of the window.
64336
       *
64337
       * Take this input:
64338
       *
64339
       * {"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]  [15,  11,   12, 13]  [154,  110,   112, 1311]
64340
       *
64341
       * Say you process the following window...
64342
       *
64343
       * '{"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]'
64344
       *
64345
       * When you do so, the json_iterator has a pointer at the beginning of the memory region
64346
       * (pointing at the beginning of '{"z"...'.
64347
       *
64348
       * When you move to the window that starts at...
64349
       *
64350
       * '[7,  10,   9]  [15,  11,   12, 13] ...
64351
       *
64352
       * then it is not sufficient to just run stage 1. You also need to re-anchor the
64353
       * json_iterator so that it believes we are starting at '[7,  10,   9]...'.
64354
       *
64355
       * Under the DOM front-end, this gets done automatically because the parser owns
64356
       * the pointer the data, and when you call stage1 and then stage2 on the same
64357
       * parser, then stage2 will run on the pointer acquired by stage1.
64358
       *
64359
       * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that
64360
       * we used. But json_iterator has no callback when stage1 is called on the parser.
64361
       * In fact, I think that the parser is unaware of json_iterator.
64362
       *
64363
       *
64364
       * So we need to re-anchor the json_iterator after each call to stage 1 so that
64365
       * all of the pointers are in sync.
64366
       */
64367
      doc.iter = json_iterator(&buf[batch_start], parser);
64368
      doc.iter._streaming = true;
64369
      /**
64370
       * End of resync.
64371
       */
64372
64373
      if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
64374
      doc_index = batch_start;
64375
    }
64376
  }
64377
}
64378
64379
inline void document_stream::next_document() noexcept {
64380
  // Go to next place where depth=0 (document depth)
64381
  error = doc.iter.skip_child(0);
64382
  if (error) { return; }
64383
  // Always set depth=1 at the start of document
64384
  doc.iter._depth = 1;
64385
  // consume comma if comma separated is allowed
64386
  if (allow_comma_separated) { doc.iter.consume_character(','); }
64387
  // Resets the string buffer at the beginning, thus invalidating the strings.
64388
  doc.iter._string_buf_loc = parser->string_buf.get();
64389
  doc.iter._root = doc.iter.position();
64390
}
64391
64392
inline size_t document_stream::next_batch_start() const noexcept {
64393
  return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
64394
}
64395
64396
inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept {
64397
  // This code only updates the structural index in the parser, it does not update any json_iterator
64398
  // instance.
64399
  size_t remaining = len - _batch_start;
64400
  if (remaining <= batch_size) {
64401
    return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
64402
  } else {
64403
    return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
64404
  }
64405
}
64406
64407
simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
64408
  return stream->doc_index;
64409
}
64410
64411
simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
64412
  auto depth = stream->doc.iter.depth();
64413
  auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get();
64414
64415
  // If at root, process the first token to determine if scalar value
64416
  if (stream->doc.iter.at_root()) {
64417
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
64418
      case '{': case '[':   // Depth=1 already at start of document
64419
        break;
64420
      case '}': case ']':
64421
        depth--;
64422
        break;
64423
      default:    // Scalar value document
64424
        // TODO: Remove any trailing whitespaces
64425
        // This returns a string spanning from start of value to the beginning of the next document (excluded)
64426
        return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[++cur_struct_index] - current_index() - 1);
64427
    }
64428
    cur_struct_index++;
64429
  }
64430
64431
  while (cur_struct_index <= static_cast<int64_t>(stream->parser->implementation->n_structural_indexes)) {
64432
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
64433
      case '{': case '[':
64434
        depth++;
64435
        break;
64436
      case '}': case ']':
64437
        depth--;
64438
        break;
64439
    }
64440
    if (depth == 0) { break; }
64441
    cur_struct_index++;
64442
  }
64443
64444
  return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);;
64445
}
64446
64447
inline error_code document_stream::iterator::error() const noexcept {
64448
  return stream->error;
64449
}
64450
64451
#ifdef SIMDJSON_THREADS_ENABLED
64452
64453
inline void document_stream::load_from_stage1_thread() noexcept {
64454
  worker->finish();
64455
  // Swap to the parser that was loaded up in the thread. Make sure the parser has
64456
  // enough memory to swap to, as well.
64457
  std::swap(stage1_thread_parser,*parser);
64458
  error = stage1_thread_error;
64459
  if (error) { return; }
64460
64461
  // If there's anything left, start the stage 1 thread!
64462
  if (next_batch_start() < len) {
64463
    start_stage1_thread();
64464
  }
64465
}
64466
64467
inline void document_stream::start_stage1_thread() noexcept {
64468
  // we call the thread on a lambda that will update
64469
  // this->stage1_thread_error
64470
  // there is only one thread that may write to this value
64471
  // TODO this is NOT exception-safe.
64472
  this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
64473
  size_t _next_batch_start = this->next_batch_start();
64474
64475
  worker->run(this, & this->stage1_thread_parser, _next_batch_start);
64476
}
64477
64478
#endif // SIMDJSON_THREADS_ENABLED
64479
64480
} // namespace ondemand
64481
} // namespace icelake
64482
} // namespace simdjson
64483
64484
namespace simdjson {
64485
64486
simdjson_inline simdjson_result<icelake::ondemand::document_stream>::simdjson_result(
64487
  error_code error
64488
) noexcept :
64489
    implementation_simdjson_result_base<icelake::ondemand::document_stream>(error)
64490
{
64491
}
64492
simdjson_inline simdjson_result<icelake::ondemand::document_stream>::simdjson_result(
64493
  icelake::ondemand::document_stream &&value
64494
) noexcept :
64495
    implementation_simdjson_result_base<icelake::ondemand::document_stream>(
64496
      std::forward<icelake::ondemand::document_stream>(value)
64497
    )
64498
{
64499
}
64500
64501
}
64502
64503
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
64504
/* end file simdjson/generic/ondemand/document_stream-inl.h for icelake */
64505
/* including simdjson/generic/ondemand/field-inl.h for icelake: #include "simdjson/generic/ondemand/field-inl.h" */
64506
/* begin file simdjson/generic/ondemand/field-inl.h for icelake */
64507
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
64508
64509
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
64510
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */
64511
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
64512
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
64513
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
64514
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
64515
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
64516
64517
namespace simdjson {
64518
namespace icelake {
64519
namespace ondemand {
64520
64521
// clang 6 does not think the default constructor can be noexcept, so we make it explicit
64522
simdjson_inline field::field() noexcept : std::pair<raw_json_string, ondemand::value>() {}
64523
64524
simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept
64525
  : std::pair<raw_json_string, ondemand::value>(key, std::forward<ondemand::value>(value))
64526
{
64527
}
64528
64529
simdjson_inline simdjson_result<field> field::start(value_iterator &parent_iter) noexcept {
64530
  raw_json_string key;
64531
  SIMDJSON_TRY( parent_iter.field_key().get(key) );
64532
  SIMDJSON_TRY( parent_iter.field_value() );
64533
  return field::start(parent_iter, key);
64534
}
64535
64536
simdjson_inline simdjson_result<field> field::start(const value_iterator &parent_iter, raw_json_string key) noexcept {
64537
    return field(key, parent_iter.child());
64538
}
64539
64540
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> field::unescaped_key(bool allow_replacement) noexcept {
64541
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us.
64542
  simdjson_result<std::string_view> answer = first.unescape(second.iter.json_iter(), allow_replacement);
64543
  first.consume();
64544
  return answer;
64545
}
64546
64547
simdjson_inline raw_json_string field::key() const noexcept {
64548
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
64549
  return first;
64550
}
64551
64552
64553
simdjson_inline std::string_view field::key_raw_json_token() const noexcept {
64554
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
64555
  return std::string_view(reinterpret_cast<const char*>(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1);
64556
}
64557
64558
simdjson_inline value &field::value() & noexcept {
64559
  return second;
64560
}
64561
64562
simdjson_inline value field::value() && noexcept {
64563
  return std::forward<field>(*this).second;
64564
}
64565
64566
} // namespace ondemand
64567
} // namespace icelake
64568
} // namespace simdjson
64569
64570
namespace simdjson {
64571
64572
simdjson_inline simdjson_result<icelake::ondemand::field>::simdjson_result(
64573
  icelake::ondemand::field &&value
64574
) noexcept :
64575
    implementation_simdjson_result_base<icelake::ondemand::field>(
64576
      std::forward<icelake::ondemand::field>(value)
64577
    )
64578
{
64579
}
64580
simdjson_inline simdjson_result<icelake::ondemand::field>::simdjson_result(
64581
  error_code error
64582
) noexcept :
64583
    implementation_simdjson_result_base<icelake::ondemand::field>(error)
64584
{
64585
}
64586
64587
simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> simdjson_result<icelake::ondemand::field>::key() noexcept {
64588
  if (error()) { return error(); }
64589
  return first.key();
64590
}
64591
64592
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::field>::key_raw_json_token() noexcept {
64593
  if (error()) { return error(); }
64594
  return first.key_raw_json_token();
64595
}
64596
64597
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::field>::unescaped_key(bool allow_replacement) noexcept {
64598
  if (error()) { return error(); }
64599
  return first.unescaped_key(allow_replacement);
64600
}
64601
64602
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::field>::value() noexcept {
64603
  if (error()) { return error(); }
64604
  return std::move(first.value());
64605
}
64606
64607
} // namespace simdjson
64608
64609
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
64610
/* end file simdjson/generic/ondemand/field-inl.h for icelake */
64611
/* including simdjson/generic/ondemand/json_iterator-inl.h for icelake: #include "simdjson/generic/ondemand/json_iterator-inl.h" */
64612
/* begin file simdjson/generic/ondemand/json_iterator-inl.h for icelake */
64613
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
64614
64615
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
64616
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */
64617
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
64618
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
64619
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
64620
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
64621
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
64622
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */
64623
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */
64624
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */
64625
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
64626
64627
namespace simdjson {
64628
namespace icelake {
64629
namespace ondemand {
64630
64631
simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
64632
  : token(std::forward<token_iterator>(other.token)),
64633
    parser{other.parser},
64634
    _string_buf_loc{other._string_buf_loc},
64635
    error{other.error},
64636
    _depth{other._depth},
64637
    _root{other._root},
64638
    _streaming{other._streaming}
64639
{
64640
  other.parser = nullptr;
64641
}
64642
simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept {
64643
  token = other.token;
64644
  parser = other.parser;
64645
  _string_buf_loc = other._string_buf_loc;
64646
  error = other.error;
64647
  _depth = other._depth;
64648
  _root = other._root;
64649
  _streaming = other._streaming;
64650
  other.parser = nullptr;
64651
  return *this;
64652
}
64653
64654
simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept
64655
  : token(buf, &_parser->implementation->structural_indexes[0]),
64656
    parser{_parser},
64657
    _string_buf_loc{parser->string_buf.get()},
64658
    _depth{1},
64659
    _root{parser->implementation->structural_indexes.get()},
64660
    _streaming{false}
64661
64662
{
64663
  logger::log_headers();
64664
#if SIMDJSON_CHECK_EOF
64665
  assert_more_tokens();
64666
#endif
64667
}
64668
64669
inline void json_iterator::rewind() noexcept {
64670
  token.set_position( root_position() );
64671
  logger::log_headers(); // We start again
64672
  _string_buf_loc = parser->string_buf.get();
64673
  _depth = 1;
64674
}
64675
64676
inline bool json_iterator::balanced() const noexcept {
64677
  token_iterator ti(token);
64678
  int32_t count{0};
64679
  ti.set_position( root_position() );
64680
  while(ti.peek() <= peek_last()) {
64681
    switch (*ti.return_current_and_advance())
64682
    {
64683
    case '[': case '{':
64684
      count++;
64685
      break;
64686
    case ']': case '}':
64687
      count--;
64688
      break;
64689
    default:
64690
      break;
64691
    }
64692
  }
64693
  return count == 0;
64694
}
64695
64696
64697
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
64698
// relating depth and parent_depth, which is a desired effect. The warning does not show up if the
64699
// skip_child() function is not marked inline).
64700
SIMDJSON_PUSH_DISABLE_WARNINGS
64701
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
64702
simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
64703
  if (depth() <= parent_depth) { return SUCCESS; }
64704
  switch (*return_current_and_advance()) {
64705
    // TODO consider whether matching braces is a requirement: if non-matching braces indicates
64706
    // *missing* braces, then future lookups are not in the object/arrays they think they are,
64707
    // violating the rule "validate enough structure that the user can be confident they are
64708
    // looking at the right values."
64709
    // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
64710
64711
    // For the first open array/object in a value, we've already incremented depth, so keep it the same
64712
    // We never stop at colon, but if we did, it wouldn't affect depth
64713
    case '[': case '{': case ':':
64714
      logger::log_start_value(*this, "skip");
64715
      break;
64716
    // If there is a comma, we have just finished a value in an array/object, and need to get back in
64717
    case ',':
64718
      logger::log_value(*this, "skip");
64719
      break;
64720
    // ] or } means we just finished a value and need to jump out of the array/object
64721
    case ']': case '}':
64722
      logger::log_end_value(*this, "skip");
64723
      _depth--;
64724
      if (depth() <= parent_depth) { return SUCCESS; }
64725
#if SIMDJSON_CHECK_EOF
64726
      // If there are no more tokens, the parent is incomplete.
64727
      if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
64728
#endif // SIMDJSON_CHECK_EOF
64729
      break;
64730
    case '"':
64731
      if(*peek() == ':') {
64732
        // We are at a key!!!
64733
        // This might happen if you just started an object and you skip it immediately.
64734
        // Performance note: it would be nice to get rid of this check as it is somewhat
64735
        // expensive.
64736
        // https://github.com/simdjson/simdjson/issues/1742
64737
        logger::log_value(*this, "key");
64738
        return_current_and_advance(); // eat up the ':'
64739
        break; // important!!!
64740
      }
64741
      simdjson_fallthrough;
64742
    // Anything else must be a scalar value
64743
    default:
64744
      // For the first scalar, we will have incremented depth already, so we decrement it here.
64745
      logger::log_value(*this, "skip");
64746
      _depth--;
64747
      if (depth() <= parent_depth) { return SUCCESS; }
64748
      break;
64749
  }
64750
64751
  // Now that we've considered the first value, we only increment/decrement for arrays/objects
64752
  while (position() < end_position()) {
64753
    switch (*return_current_and_advance()) {
64754
      case '[': case '{':
64755
        logger::log_start_value(*this, "skip");
64756
        _depth++;
64757
        break;
64758
      // TODO consider whether matching braces is a requirement: if non-matching braces indicates
64759
      // *missing* braces, then future lookups are not in the object/arrays they think they are,
64760
      // violating the rule "validate enough structure that the user can be confident they are
64761
      // looking at the right values."
64762
      // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
64763
      case ']': case '}':
64764
        logger::log_end_value(*this, "skip");
64765
        _depth--;
64766
        if (depth() <= parent_depth) { return SUCCESS; }
64767
        break;
64768
      default:
64769
        logger::log_value(*this, "skip", "");
64770
        break;
64771
    }
64772
  }
64773
64774
  return report_error(TAPE_ERROR, "not enough close braces");
64775
}
64776
64777
SIMDJSON_POP_DISABLE_WARNINGS
64778
64779
simdjson_inline bool json_iterator::at_root() const noexcept {
64780
  return position() == root_position();
64781
}
64782
64783
simdjson_inline bool json_iterator::is_single_token() const noexcept {
64784
  return parser->implementation->n_structural_indexes == 1;
64785
}
64786
64787
simdjson_inline bool json_iterator::streaming() const noexcept {
64788
  return _streaming;
64789
}
64790
64791
simdjson_inline token_position json_iterator::root_position() const noexcept {
64792
  return _root;
64793
}
64794
64795
simdjson_inline void json_iterator::assert_at_document_depth() const noexcept {
64796
  SIMDJSON_ASSUME( _depth == 1 );
64797
}
64798
64799
simdjson_inline void json_iterator::assert_at_root() const noexcept {
64800
  SIMDJSON_ASSUME( _depth == 1 );
64801
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
64802
  // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument
64803
  // has side effects that will be discarded.
64804
  SIMDJSON_ASSUME( token.position() == _root );
64805
#endif
64806
}
64807
64808
simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
64809
  assert_valid_position(token._position + required_tokens - 1);
64810
}
64811
64812
simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
64813
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
64814
  SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
64815
  SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
64816
#endif
64817
}
64818
64819
simdjson_inline bool json_iterator::at_end() const noexcept {
64820
  return position() == end_position();
64821
}
64822
simdjson_inline token_position json_iterator::end_position() const noexcept {
64823
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
64824
  return &parser->implementation->structural_indexes[n_structural_indexes];
64825
}
64826
64827
inline std::string json_iterator::to_string() const noexcept {
64828
  if( !is_alive() ) { return "dead json_iterator instance"; }
64829
  const char * current_structural = reinterpret_cast<const char *>(token.peek());
64830
  return std::string("json_iterator [ depth : ") + std::to_string(_depth)
64831
          + std::string(", structural : '") + std::string(current_structural,1)
64832
          + std::string("', offset : ") + std::to_string(token.current_offset())
64833
          + std::string("', error : ") + error_message(error)
64834
          + std::string(" ]");
64835
}
64836
64837
inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
64838
  if (!is_alive()) {    // Unrecoverable error
64839
    if (!at_root()) {
64840
      return reinterpret_cast<const char *>(token.peek(-1));
64841
    } else {
64842
      return reinterpret_cast<const char *>(token.peek());
64843
    }
64844
  }
64845
  if (at_end()) {
64846
    return OUT_OF_BOUNDS;
64847
  }
64848
  return reinterpret_cast<const char *>(token.peek());
64849
}
64850
64851
simdjson_inline bool json_iterator::is_alive() const noexcept {
64852
  return parser;
64853
}
64854
64855
simdjson_inline void json_iterator::abandon() noexcept {
64856
  parser = nullptr;
64857
  _depth = 0;
64858
}
64859
64860
simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
64861
#if SIMDJSON_CHECK_EOF
64862
  assert_more_tokens();
64863
#endif // SIMDJSON_CHECK_EOF
64864
  return token.return_current_and_advance();
64865
}
64866
64867
simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
64868
  // deliberately done without safety guard:
64869
  return token.peek();
64870
}
64871
64872
simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
64873
#if SIMDJSON_CHECK_EOF
64874
  assert_more_tokens(delta+1);
64875
#endif // SIMDJSON_CHECK_EOF
64876
  return token.peek(delta);
64877
}
64878
64879
simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
64880
#if SIMDJSON_CHECK_EOF
64881
  assert_more_tokens(delta+1);
64882
#endif // #if SIMDJSON_CHECK_EOF
64883
  return token.peek_length(delta);
64884
}
64885
64886
simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
64887
  // todo: currently we require end-of-string buffering, but the following
64888
  // assert_valid_position should be turned on if/when we lift that condition.
64889
  // assert_valid_position(position);
64890
  // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
64891
  // is ON by default, we have no choice but to disable it for real with a comment.
64892
  return token.peek(position);
64893
}
64894
64895
simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
64896
#if SIMDJSON_CHECK_EOF
64897
  assert_valid_position(position);
64898
#endif // SIMDJSON_CHECK_EOF
64899
  return token.peek_length(position);
64900
}
64901
simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept {
64902
#if SIMDJSON_CHECK_EOF
64903
  assert_valid_position(position);
64904
#endif // SIMDJSON_CHECK_EOF
64905
  return token.peek_root_length(position);
64906
}
64907
64908
simdjson_inline token_position json_iterator::last_position() const noexcept {
64909
  // The following line fails under some compilers...
64910
  // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0);
64911
  // since it has side-effects.
64912
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
64913
  SIMDJSON_ASSUME(n_structural_indexes > 0);
64914
  return &parser->implementation->structural_indexes[n_structural_indexes - 1];
64915
}
64916
simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept {
64917
  return token.peek(last_position());
64918
}
64919
64920
simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
64921
  SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
64922
  SIMDJSON_ASSUME(_depth == parent_depth + 1);
64923
  _depth = parent_depth;
64924
}
64925
64926
simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
64927
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
64928
  SIMDJSON_ASSUME(_depth == child_depth - 1);
64929
  _depth = child_depth;
64930
}
64931
64932
simdjson_inline depth_t json_iterator::depth() const noexcept {
64933
  return _depth;
64934
}
64935
64936
simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
64937
  return _string_buf_loc;
64938
}
64939
64940
simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept {
64941
  SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD);
64942
  logger::log_error(*this, message);
64943
  error = _error;
64944
  return error;
64945
}
64946
64947
simdjson_inline token_position json_iterator::position() const noexcept {
64948
  return token.position();
64949
}
64950
64951
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept {
64952
  return parser->unescape(in, _string_buf_loc, allow_replacement);
64953
}
64954
64955
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in) noexcept {
64956
  return parser->unescape_wobbly(in, _string_buf_loc);
64957
}
64958
64959
simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
64960
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
64961
  SIMDJSON_ASSUME(_depth == child_depth - 1);
64962
#if SIMDJSON_DEVELOPMENT_CHECKS
64963
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
64964
  SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
64965
  SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
64966
#endif
64967
#endif
64968
  token.set_position(position);
64969
  _depth = child_depth;
64970
}
64971
64972
simdjson_inline error_code json_iterator::consume_character(char c) noexcept {
64973
  if (*peek() == c) {
64974
    return_current_and_advance();
64975
    return SUCCESS;
64976
  }
64977
  return TAPE_ERROR;
64978
}
64979
64980
#if SIMDJSON_DEVELOPMENT_CHECKS
64981
64982
simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
64983
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
64984
  return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
64985
}
64986
64987
simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
64988
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
64989
  if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
64990
}
64991
64992
#endif
64993
64994
64995
simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept {
64996
  SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD);
64997
  logger::log_error(*this, message);
64998
  return _error;
64999
}
65000
65001
65002
simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept {
65003
  // This function is not expected to be called in performance-sensitive settings.
65004
  // Let us guard against silly cases:
65005
  if((N < max_len) || (N == 0)) { return false; }
65006
  // Copy to the buffer.
65007
  std::memcpy(tmpbuf, json, max_len);
65008
  if(N > max_len) { // We pad whatever remains with ' '.
65009
    std::memset(tmpbuf + max_len, ' ', N - max_len);
65010
  }
65011
  return true;
65012
}
65013
65014
} // namespace ondemand
65015
} // namespace icelake
65016
} // namespace simdjson
65017
65018
namespace simdjson {
65019
65020
simdjson_inline simdjson_result<icelake::ondemand::json_iterator>::simdjson_result(icelake::ondemand::json_iterator &&value) noexcept
65021
    : implementation_simdjson_result_base<icelake::ondemand::json_iterator>(std::forward<icelake::ondemand::json_iterator>(value)) {}
65022
simdjson_inline simdjson_result<icelake::ondemand::json_iterator>::simdjson_result(error_code error) noexcept
65023
    : implementation_simdjson_result_base<icelake::ondemand::json_iterator>(error) {}
65024
65025
} // namespace simdjson
65026
65027
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
65028
/* end file simdjson/generic/ondemand/json_iterator-inl.h for icelake */
65029
/* including simdjson/generic/ondemand/json_type-inl.h for icelake: #include "simdjson/generic/ondemand/json_type-inl.h" */
65030
/* begin file simdjson/generic/ondemand/json_type-inl.h for icelake */
65031
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
65032
65033
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
65034
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */
65035
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
65036
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
65037
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
65038
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
65039
65040
namespace simdjson {
65041
namespace icelake {
65042
namespace ondemand {
65043
65044
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
65045
    switch (type) {
65046
        case json_type::array: out << "array"; break;
65047
        case json_type::object: out << "object"; break;
65048
        case json_type::number: out << "number"; break;
65049
        case json_type::string: out << "string"; break;
65050
        case json_type::boolean: out << "boolean"; break;
65051
        case json_type::null: out << "null"; break;
65052
        default: SIMDJSON_UNREACHABLE();
65053
    }
65054
    return out;
65055
}
65056
65057
#if SIMDJSON_EXCEPTIONS
65058
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
65059
    return out << type.value();
65060
}
65061
#endif
65062
65063
65064
65065
simdjson_inline number_type number::get_number_type() const noexcept {
65066
  return type;
65067
}
65068
65069
simdjson_inline bool number::is_uint64() const noexcept {
65070
  return get_number_type() == number_type::unsigned_integer;
65071
}
65072
65073
simdjson_inline uint64_t number::get_uint64() const noexcept {
65074
  return payload.unsigned_integer;
65075
}
65076
65077
simdjson_inline number::operator uint64_t() const noexcept {
65078
  return get_uint64();
65079
}
65080
65081
simdjson_inline bool number::is_int64() const noexcept {
65082
  return get_number_type() == number_type::signed_integer;
65083
}
65084
65085
simdjson_inline int64_t number::get_int64() const noexcept {
65086
  return payload.signed_integer;
65087
}
65088
65089
simdjson_inline number::operator int64_t() const noexcept {
65090
  return get_int64();
65091
}
65092
65093
simdjson_inline bool number::is_double() const noexcept {
65094
    return get_number_type() == number_type::floating_point_number;
65095
}
65096
65097
simdjson_inline double number::get_double() const noexcept {
65098
  return payload.floating_point_number;
65099
}
65100
65101
simdjson_inline number::operator double() const noexcept {
65102
  return get_double();
65103
}
65104
65105
simdjson_inline double number::as_double() const noexcept {
65106
  if(is_double()) {
65107
    return payload.floating_point_number;
65108
  }
65109
  if(is_int64()) {
65110
    return double(payload.signed_integer);
65111
  }
65112
  return double(payload.unsigned_integer);
65113
}
65114
65115
simdjson_inline void number::append_s64(int64_t value) noexcept {
65116
  payload.signed_integer = value;
65117
  type = number_type::signed_integer;
65118
}
65119
65120
simdjson_inline void number::append_u64(uint64_t value) noexcept {
65121
  payload.unsigned_integer = value;
65122
  type = number_type::unsigned_integer;
65123
}
65124
65125
simdjson_inline void number::append_double(double value) noexcept {
65126
  payload.floating_point_number = value;
65127
  type = number_type::floating_point_number;
65128
}
65129
65130
simdjson_inline void number::skip_double() noexcept {
65131
  type = number_type::floating_point_number;
65132
}
65133
65134
} // namespace ondemand
65135
} // namespace icelake
65136
} // namespace simdjson
65137
65138
namespace simdjson {
65139
65140
simdjson_inline simdjson_result<icelake::ondemand::json_type>::simdjson_result(icelake::ondemand::json_type &&value) noexcept
65141
    : implementation_simdjson_result_base<icelake::ondemand::json_type>(std::forward<icelake::ondemand::json_type>(value)) {}
65142
simdjson_inline simdjson_result<icelake::ondemand::json_type>::simdjson_result(error_code error) noexcept
65143
    : implementation_simdjson_result_base<icelake::ondemand::json_type>(error) {}
65144
65145
} // namespace simdjson
65146
65147
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
65148
/* end file simdjson/generic/ondemand/json_type-inl.h for icelake */
65149
/* including simdjson/generic/ondemand/logger-inl.h for icelake: #include "simdjson/generic/ondemand/logger-inl.h" */
65150
/* begin file simdjson/generic/ondemand/logger-inl.h for icelake */
65151
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
65152
65153
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
65154
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */
65155
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
65156
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
65157
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
65158
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
65159
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
65160
65161
#include <memory>
65162
#include <cstring>
65163
65164
namespace simdjson {
65165
namespace icelake {
65166
namespace ondemand {
65167
namespace logger {
65168
65169
static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
65170
static constexpr const int LOG_EVENT_LEN = 20;
65171
static constexpr const int LOG_BUFFER_LEN = 30;
65172
static constexpr const int LOG_SMALL_BUFFER_LEN = 10;
65173
static int log_depth = 0; // Not threadsafe. Log only.
65174
65175
// Helper to turn unprintable or newline characters into spaces
65176
static inline char printable_char(char c) {
65177
  if (c >= 0x20) {
65178
    return c;
65179
  } else {
65180
    return ' ';
65181
  }
65182
}
65183
65184
template<typename... Args>
65185
static inline std::string string_format(const std::string& format, const Args&... args)
65186
{
65187
  SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
65188
  int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
65189
  auto size = static_cast<size_t>(size_s);
65190
  if (size <= 0) return std::string();
65191
  std::unique_ptr<char[]> buf(new char[size]);
65192
  std::snprintf(buf.get(), size, format.c_str(), args...);
65193
  SIMDJSON_POP_DISABLE_WARNINGS
65194
  return std::string(buf.get(), buf.get() + size - 1);
65195
}
65196
65197
static inline log_level get_log_level_from_env()
65198
{
65199
  SIMDJSON_PUSH_DISABLE_WARNINGS
65200
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
65201
      char *lvl = getenv("SIMDJSON_LOG_LEVEL");
65202
  SIMDJSON_POP_DISABLE_WARNINGS
65203
  if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; }
65204
  return log_level::info;
65205
}
65206
65207
static inline log_level log_threshold()
65208
{
65209
  static log_level threshold = get_log_level_from_env();
65210
  return threshold;
65211
}
65212
65213
static inline bool should_log(log_level level)
65214
{
65215
  return level >= log_threshold();
65216
}
65217
65218
inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
65219
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
65220
}
65221
65222
inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
65223
  log_line(iter, index, depth, "", type, detail, log_level::info);
65224
}
65225
inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
65226
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
65227
}
65228
65229
inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
65230
  log_line(iter, index, depth, "+", type, detail, log_level::info);
65231
  if (LOG_ENABLED) { log_depth++; }
65232
}
65233
inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
65234
  log_line(iter, "+", type, "", delta, depth_delta, log_level::info);
65235
  if (LOG_ENABLED) { log_depth++; }
65236
}
65237
65238
inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
65239
  if (LOG_ENABLED) { log_depth--; }
65240
  log_line(iter, "-", type, "", delta, depth_delta, log_level::info);
65241
}
65242
65243
inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
65244
  log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error);
65245
}
65246
inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept {
65247
  log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error);
65248
}
65249
65250
inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
65251
  log_event(iter.json_iter(), type, detail, delta, depth_delta);
65252
}
65253
65254
inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
65255
  log_value(iter.json_iter(), type, detail, delta, depth_delta);
65256
}
65257
65258
inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
65259
  log_start_value(iter.json_iter(), type, delta, depth_delta);
65260
}
65261
65262
inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
65263
  log_end_value(iter.json_iter(), type, delta, depth_delta);
65264
}
65265
65266
inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
65267
  log_error(iter.json_iter(), error, detail, delta, depth_delta);
65268
}
65269
65270
inline void log_headers() noexcept {
65271
  if (LOG_ENABLED) {
65272
    if (simdjson_unlikely(should_log(log_level::info))) {
65273
      // Technically a static variable is not thread-safe, but if you are using threads and logging... well...
65274
      static bool displayed_hint{false};
65275
      log_depth = 0;
65276
      printf("\n");
65277
      if (!displayed_hint) {
65278
        // We only print this helpful header once.
65279
        printf("# Logging provides the depth and position of the iterator user-visible steps:\n");
65280
        printf("# +array says 'this is where we were when we discovered the start array'\n");
65281
        printf(
65282
            "# -array says 'this is where we were when we ended the array'\n");
65283
        printf("# skip says 'this is a structural or value I am skipping'\n");
65284
        printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
65285
        printf("#\n");
65286
        printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
65287
        printf("# in addition to the depth being displayed.\n");
65288
        printf("#\n");
65289
        printf("# Every token in the document has a single depth determined by the tokens before it,\n");
65290
        printf("# and is not affected by what the token actually is.\n");
65291
        printf("#\n");
65292
        printf("# Not all structural elements are presented as tokens in the logs.\n");
65293
        printf("#\n");
65294
        printf("# We never give control to the user within an empty array or an empty object.\n");
65295
        printf("#\n");
65296
        printf("# Inside an array, having a depth greater than the array's depth means that\n");
65297
        printf("# we are pointing inside a value.\n");
65298
        printf("# Having a depth equal to the array means that we are pointing right before a value.\n");
65299
        printf("# Having a depth smaller than the array means that we have moved beyond the array.\n");
65300
        displayed_hint = true;
65301
      }
65302
      printf("\n");
65303
      printf("| %-*s ", LOG_EVENT_LEN, "Event");
65304
      printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
65305
      printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next");
65306
      // printf("| %-*s ", 5,                    "Next#");
65307
      printf("| %-*s ", 5, "Depth");
65308
      printf("| Detail ");
65309
      printf("|\n");
65310
65311
      printf("|%.*s", LOG_EVENT_LEN + 2, DASHES);
65312
      printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES);
65313
      printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
65314
      // printf("|%.*s", 5+2, DASHES);
65315
      printf("|%.*s", 5 + 2, DASHES);
65316
      printf("|--------");
65317
      printf("|\n");
65318
      fflush(stdout);
65319
    }
65320
  }
65321
}
65322
65323
template <typename... Args>
65324
inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept {
65325
  log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
65326
}
65327
65328
template <typename... Args>
65329
inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
65330
  if (LOG_ENABLED) {
65331
    if (simdjson_unlikely(should_log(level))) {
65332
      const int indent = depth * 2;
65333
      const auto buf = iter.token.buf;
65334
      auto msg = string_format(title, std::forward<Args>(args)...);
65335
      printf("| %*s%s%-*s ", indent, "", title_prefix,
65336
             LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str());
65337
      {
65338
        // Print the current structural.
65339
        printf("| ");
65340
        // Before we begin, the index might point right before the document.
65341
        // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
65342
        if (index < iter._root) {
65343
          printf("%*s", LOG_BUFFER_LEN, "");
65344
        } else {
65345
          auto current_structural = &buf[*index];
65346
          for (int i = 0; i < LOG_BUFFER_LEN; i++) {
65347
            printf("%c", printable_char(current_structural[i]));
65348
          }
65349
        }
65350
        printf(" ");
65351
      }
65352
      {
65353
        // Print the next structural.
65354
        printf("| ");
65355
        auto next_structural = &buf[*(index + 1)];
65356
        for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
65357
          printf("%c", printable_char(next_structural[i]));
65358
        }
65359
        printf(" ");
65360
      }
65361
      // printf("| %5u ", *(index+1));
65362
      printf("| %5i ", depth);
65363
      printf("| %6.*s ", int(detail.size()), detail.data());
65364
      printf("|\n");
65365
      fflush(stdout);
65366
    }
65367
  }
65368
}
65369
65370
} // namespace logger
65371
} // namespace ondemand
65372
} // namespace icelake
65373
} // namespace simdjson
65374
65375
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
65376
/* end file simdjson/generic/ondemand/logger-inl.h for icelake */
65377
/* including simdjson/generic/ondemand/object-inl.h for icelake: #include "simdjson/generic/ondemand/object-inl.h" */
65378
/* begin file simdjson/generic/ondemand/object-inl.h for icelake */
65379
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
65380
65381
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
65382
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */
65383
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
65384
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
65385
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
65386
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
65387
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
65388
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
65389
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
65390
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
65391
65392
namespace simdjson {
65393
namespace icelake {
65394
namespace ondemand {
65395
65396
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
65397
  bool has_value;
65398
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
65399
  if (!has_value) {
65400
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
65401
    return NO_SUCH_FIELD;
65402
  }
65403
  return value(iter.child());
65404
}
65405
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
65406
  bool has_value;
65407
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
65408
  if (!has_value) {
65409
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
65410
    return NO_SUCH_FIELD;
65411
  }
65412
  return value(iter.child());
65413
}
65414
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
65415
  return find_field_unordered(key);
65416
}
65417
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
65418
  return std::forward<object>(*this).find_field_unordered(key);
65419
}
65420
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
65421
  bool has_value;
65422
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
65423
  if (!has_value) {
65424
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
65425
    return NO_SUCH_FIELD;
65426
  }
65427
  return value(iter.child());
65428
}
65429
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
65430
  bool has_value;
65431
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
65432
  if (!has_value) {
65433
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
65434
    return NO_SUCH_FIELD;
65435
  }
65436
  return value(iter.child());
65437
}
65438
65439
simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
65440
  SIMDJSON_TRY( iter.start_object().error() );
65441
  return object(iter);
65442
}
65443
simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
65444
  SIMDJSON_TRY( iter.start_root_object().error() );
65445
  return object(iter);
65446
}
65447
simdjson_inline error_code object::consume() noexcept {
65448
  if(iter.is_at_key()) {
65449
    /**
65450
     * whenever you are pointing at a key, calling skip_child() is
65451
     * unsafe because you will hit a string and you will assume that
65452
     * it is string value, and this mistake will lead you to make bad
65453
     * depth computation.
65454
     */
65455
    /**
65456
     * We want to 'consume' the key. We could really
65457
     * just do _json_iter->return_current_and_advance(); at this
65458
     * point, but, for clarity, we will use the high-level API to
65459
     * eat the key. We assume that the compiler optimizes away
65460
     * most of the work.
65461
     */
65462
    simdjson_unused raw_json_string actual_key;
65463
    auto error = iter.field_key().get(actual_key);
65464
    if (error) { iter.abandon(); return error; };
65465
    // Let us move to the value while we are at it.
65466
    if ((error = iter.field_value())) { iter.abandon(); return error; }
65467
  }
65468
  auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
65469
  if(error_skip) { iter.abandon(); }
65470
  return error_skip;
65471
}
65472
65473
simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
65474
  const uint8_t * starting_point{iter.peek_start()};
65475
  auto error = consume();
65476
  if(error) { return error; }
65477
  const uint8_t * final_point{iter._json_iter->peek()};
65478
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
65479
}
65480
65481
simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
65482
  SIMDJSON_TRY( iter.started_object().error() );
65483
  return object(iter);
65484
}
65485
65486
simdjson_inline object object::resume(const value_iterator &iter) noexcept {
65487
  return iter;
65488
}
65489
65490
simdjson_inline object::object(const value_iterator &_iter) noexcept
65491
  : iter{_iter}
65492
{
65493
}
65494
65495
simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
65496
#if SIMDJSON_DEVELOPMENT_CHECKS
65497
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
65498
#endif
65499
  return object_iterator(iter);
65500
}
65501
simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
65502
  return object_iterator(iter);
65503
}
65504
65505
inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
65506
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
65507
  json_pointer = json_pointer.substr(1);
65508
  size_t slash = json_pointer.find('/');
65509
  std::string_view key = json_pointer.substr(0, slash);
65510
  // Grab the child with the given key
65511
  simdjson_result<value> child;
65512
65513
  // If there is an escape character in the key, unescape it and then get the child.
65514
  size_t escape = key.find('~');
65515
  if (escape != std::string_view::npos) {
65516
    // Unescape the key
65517
    std::string unescaped(key);
65518
    do {
65519
      switch (unescaped[escape+1]) {
65520
        case '0':
65521
          unescaped.replace(escape, 2, "~");
65522
          break;
65523
        case '1':
65524
          unescaped.replace(escape, 2, "/");
65525
          break;
65526
        default:
65527
          return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
65528
      }
65529
      escape = unescaped.find('~', escape+1);
65530
    } while (escape != std::string::npos);
65531
    child = find_field(unescaped);  // Take note find_field does not unescape keys when matching
65532
  } else {
65533
    child = find_field(key);
65534
  }
65535
  if(child.error()) {
65536
    return child; // we do not continue if there was an error
65537
  }
65538
  // If there is a /, we have to recurse and look up more of the path
65539
  if (slash != std::string_view::npos) {
65540
    child = child.at_pointer(json_pointer.substr(slash));
65541
  }
65542
  return child;
65543
}
65544
65545
inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
65546
  auto json_pointer = json_path_to_pointer_conversion(json_path);
65547
  if (json_pointer == "-1") {
65548
    return INVALID_JSON_POINTER;
65549
  }
65550
  return at_pointer(json_pointer);
65551
}
65552
65553
simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
65554
  size_t count{0};
65555
  // Important: we do not consume any of the values.
65556
  for(simdjson_unused auto v : *this) { count++; }
65557
  // The above loop will always succeed, but we want to report errors.
65558
  if(iter.error()) { return iter.error(); }
65559
  // We need to move back at the start because we expect users to iterate through
65560
  // the object after counting the number of elements.
65561
  iter.reset_object();
65562
  return count;
65563
}
65564
65565
simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
65566
  bool is_not_empty;
65567
  auto error = iter.reset_object().get(is_not_empty);
65568
  if(error) { return error; }
65569
  return !is_not_empty;
65570
}
65571
65572
simdjson_inline simdjson_result<bool> object::reset() & noexcept {
65573
  return iter.reset_object();
65574
}
65575
65576
} // namespace ondemand
65577
} // namespace icelake
65578
} // namespace simdjson
65579
65580
namespace simdjson {
65581
65582
simdjson_inline simdjson_result<icelake::ondemand::object>::simdjson_result(icelake::ondemand::object &&value) noexcept
65583
    : implementation_simdjson_result_base<icelake::ondemand::object>(std::forward<icelake::ondemand::object>(value)) {}
65584
simdjson_inline simdjson_result<icelake::ondemand::object>::simdjson_result(error_code error) noexcept
65585
    : implementation_simdjson_result_base<icelake::ondemand::object>(error) {}
65586
65587
simdjson_inline simdjson_result<icelake::ondemand::object_iterator> simdjson_result<icelake::ondemand::object>::begin() noexcept {
65588
  if (error()) { return error(); }
65589
  return first.begin();
65590
}
65591
simdjson_inline simdjson_result<icelake::ondemand::object_iterator> simdjson_result<icelake::ondemand::object>::end() noexcept {
65592
  if (error()) { return error(); }
65593
  return first.end();
65594
}
65595
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
65596
  if (error()) { return error(); }
65597
  return first.find_field_unordered(key);
65598
}
65599
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
65600
  if (error()) { return error(); }
65601
  return std::forward<icelake::ondemand::object>(first).find_field_unordered(key);
65602
}
65603
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::operator[](std::string_view key) & noexcept {
65604
  if (error()) { return error(); }
65605
  return first[key];
65606
}
65607
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::operator[](std::string_view key) && noexcept {
65608
  if (error()) { return error(); }
65609
  return std::forward<icelake::ondemand::object>(first)[key];
65610
}
65611
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::find_field(std::string_view key) & noexcept {
65612
  if (error()) { return error(); }
65613
  return first.find_field(key);
65614
}
65615
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::find_field(std::string_view key) && noexcept {
65616
  if (error()) { return error(); }
65617
  return std::forward<icelake::ondemand::object>(first).find_field(key);
65618
}
65619
65620
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
65621
  if (error()) { return error(); }
65622
  return first.at_pointer(json_pointer);
65623
}
65624
65625
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::object>::at_path(
65626
    std::string_view json_path) noexcept {
65627
  if (error()) {
65628
    return error();
65629
  }
65630
  return first.at_path(json_path);
65631
}
65632
65633
inline simdjson_result<bool> simdjson_result<icelake::ondemand::object>::reset() noexcept {
65634
  if (error()) { return error(); }
65635
  return first.reset();
65636
}
65637
65638
inline simdjson_result<bool> simdjson_result<icelake::ondemand::object>::is_empty() noexcept {
65639
  if (error()) { return error(); }
65640
  return first.is_empty();
65641
}
65642
65643
simdjson_inline  simdjson_result<size_t> simdjson_result<icelake::ondemand::object>::count_fields() & noexcept {
65644
  if (error()) { return error(); }
65645
  return first.count_fields();
65646
}
65647
65648
simdjson_inline  simdjson_result<std::string_view> simdjson_result<icelake::ondemand::object>::raw_json() noexcept {
65649
  if (error()) { return error(); }
65650
  return first.raw_json();
65651
}
65652
} // namespace simdjson
65653
65654
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
65655
/* end file simdjson/generic/ondemand/object-inl.h for icelake */
65656
/* including simdjson/generic/ondemand/object_iterator-inl.h for icelake: #include "simdjson/generic/ondemand/object_iterator-inl.h" */
65657
/* begin file simdjson/generic/ondemand/object_iterator-inl.h for icelake */
65658
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
65659
65660
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
65661
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */
65662
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
65663
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
65664
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */
65665
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
65666
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
65667
65668
namespace simdjson {
65669
namespace icelake {
65670
namespace ondemand {
65671
65672
//
65673
// object_iterator
65674
//
65675
65676
simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
65677
  : iter{_iter}
65678
{}
65679
65680
simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
65681
  error_code error = iter.error();
65682
  if (error) { iter.abandon(); return error; }
65683
  auto result = field::start(iter);
65684
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
65685
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
65686
  if (result.error()) { iter.abandon(); }
65687
  return result;
65688
}
65689
simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
65690
  return !(*this != other);
65691
}
65692
simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
65693
  return iter.is_open();
65694
}
65695
65696
SIMDJSON_PUSH_DISABLE_WARNINGS
65697
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
65698
simdjson_inline object_iterator &object_iterator::operator++() noexcept {
65699
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
65700
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
65701
  if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
65702
65703
  simdjson_unused error_code error;
65704
  if ((error = iter.skip_child() )) { return *this; }
65705
65706
  simdjson_unused bool has_value;
65707
  if ((error = iter.has_next_field().get(has_value) )) { return *this; };
65708
  return *this;
65709
}
65710
SIMDJSON_POP_DISABLE_WARNINGS
65711
65712
//
65713
// ### Live States
65714
//
65715
// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
65716
// always SUCCESS:
65717
//
65718
// - Start: This is the state when the object is first found and the iterator is just past the {.
65719
//   In this state, at_start == true.
65720
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
65721
//   iterate over, the iterator is at the , or } before the next value. In this state,
65722
//   depth == iter.depth, at_start == false, and error == SUCCESS.
65723
// - Unfinished Business: When we hand an array/object to the user which they do not fully
65724
//   iterate over, we need to finish that iteration by skipping child values until we reach the
65725
//   Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
65726
//
65727
// ## Error States
65728
//
65729
// In error states, we will yield exactly one more value before stopping. iter.depth == depth
65730
// and at_start is always false. We decrement after yielding the error, moving to the Finished
65731
// state.
65732
//
65733
// - Chained Error: When the object iterator is part of an error chain--for example, in
65734
//   `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
65735
//   object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
65736
//   iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
65737
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
65738
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
65739
//   error == TAPE_ERROR, iter.depth == depth, and at_start == false.
65740
//
65741
// Errors that occur while reading a field to give to the user (such as when the key is not a
65742
// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
65743
// moving to the Finished state without transitioning through an Error state at all.
65744
//
65745
// ## Terminal State
65746
//
65747
// The terminal state has iter.depth < depth. at_start is always false.
65748
//
65749
// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
65750
//   In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
65751
//
65752
65753
} // namespace ondemand
65754
} // namespace icelake
65755
} // namespace simdjson
65756
65757
namespace simdjson {
65758
65759
simdjson_inline simdjson_result<icelake::ondemand::object_iterator>::simdjson_result(
65760
  icelake::ondemand::object_iterator &&value
65761
) noexcept
65762
  : implementation_simdjson_result_base<icelake::ondemand::object_iterator>(std::forward<icelake::ondemand::object_iterator>(value))
65763
{
65764
  first.iter.assert_is_valid();
65765
}
65766
simdjson_inline simdjson_result<icelake::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
65767
  : implementation_simdjson_result_base<icelake::ondemand::object_iterator>({}, error)
65768
{
65769
}
65770
65771
simdjson_inline simdjson_result<icelake::ondemand::field> simdjson_result<icelake::ondemand::object_iterator>::operator*() noexcept {
65772
  if (error()) { return error(); }
65773
  return *first;
65774
}
65775
// If we're iterating and there is an error, return the error once.
65776
simdjson_inline bool simdjson_result<icelake::ondemand::object_iterator>::operator==(const simdjson_result<icelake::ondemand::object_iterator> &other) const noexcept {
65777
  if (!first.iter.is_valid()) { return !error(); }
65778
  return first == other.first;
65779
}
65780
// If we're iterating and there is an error, return the error once.
65781
simdjson_inline bool simdjson_result<icelake::ondemand::object_iterator>::operator!=(const simdjson_result<icelake::ondemand::object_iterator> &other) const noexcept {
65782
  if (!first.iter.is_valid()) { return error(); }
65783
  return first != other.first;
65784
}
65785
// Checks for ']' and ','
65786
simdjson_inline simdjson_result<icelake::ondemand::object_iterator> &simdjson_result<icelake::ondemand::object_iterator>::operator++() noexcept {
65787
  // Clear the error if there is one, so we don't yield it twice
65788
  if (error()) { second = SUCCESS; return *this; }
65789
  ++first;
65790
  return *this;
65791
}
65792
65793
} // namespace simdjson
65794
65795
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
65796
/* end file simdjson/generic/ondemand/object_iterator-inl.h for icelake */
65797
/* including simdjson/generic/ondemand/parser-inl.h for icelake: #include "simdjson/generic/ondemand/parser-inl.h" */
65798
/* begin file simdjson/generic/ondemand/parser-inl.h for icelake */
65799
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
65800
65801
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
65802
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */
65803
/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */
65804
/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */
65805
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
65806
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
65807
/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */
65808
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
65809
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
65810
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
65811
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
65812
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
65813
65814
namespace simdjson {
65815
namespace icelake {
65816
namespace ondemand {
65817
65818
simdjson_inline parser::parser(size_t max_capacity) noexcept
65819
  : _max_capacity{max_capacity} {
65820
}
65821
65822
simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept {
65823
  if (new_capacity > max_capacity()) { return CAPACITY; }
65824
  if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; }
65825
65826
  // string_capacity copied from document::allocate
65827
  _capacity = 0;
65828
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64);
65829
  string_buf.reset(new (std::nothrow) uint8_t[string_capacity]);
65830
#if SIMDJSON_DEVELOPMENT_CHECKS
65831
  start_positions.reset(new (std::nothrow) token_position[new_max_depth]);
65832
#endif
65833
  if (implementation) {
65834
    SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
65835
    SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
65836
  } else {
65837
    SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
65838
  }
65839
  _capacity = new_capacity;
65840
  _max_depth = new_max_depth;
65841
  return SUCCESS;
65842
}
65843
65844
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(padded_string_view json) & noexcept {
65845
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
65846
65847
  json.remove_utf8_bom();
65848
65849
  // Allocate if needed
65850
  if (capacity() < json.length() || !string_buf) {
65851
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
65852
  }
65853
65854
  // Run stage 1.
65855
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
65856
  return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this });
65857
}
65858
65859
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const char *json, size_t len, size_t allocated) & noexcept {
65860
  return iterate(padded_string_view(json, len, allocated));
65861
}
65862
65863
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept {
65864
  return iterate(padded_string_view(json, len, allocated));
65865
}
65866
65867
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string_view json, size_t allocated) & noexcept {
65868
  return iterate(padded_string_view(json, allocated));
65869
}
65870
65871
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
65872
  if(json.capacity() - json.size() < SIMDJSON_PADDING) {
65873
    json.reserve(json.size() + SIMDJSON_PADDING);
65874
  }
65875
  return iterate(padded_string_view(json));
65876
}
65877
65878
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
65879
  return iterate(padded_string_view(json));
65880
}
65881
65882
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string_view> &result) & noexcept {
65883
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
65884
  SIMDJSON_TRY( result.error() );
65885
  padded_string_view json = result.value_unsafe();
65886
  return iterate(json);
65887
}
65888
65889
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
65890
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
65891
  SIMDJSON_TRY( result.error() );
65892
  const padded_string &json = result.value_unsafe();
65893
  return iterate(json);
65894
}
65895
65896
simdjson_warn_unused simdjson_inline simdjson_result<json_iterator> parser::iterate_raw(padded_string_view json) & noexcept {
65897
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
65898
65899
  json.remove_utf8_bom();
65900
65901
  // Allocate if needed
65902
  if (capacity() < json.length()) {
65903
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
65904
  }
65905
65906
  // Run stage 1.
65907
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
65908
  return json_iterator(reinterpret_cast<const uint8_t *>(json.data()), this);
65909
}
65910
65911
inline simdjson_result<document_stream> parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
65912
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
65913
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
65914
    buf += 3;
65915
    len -= 3;
65916
  }
65917
  if(allow_comma_separated && batch_size < len) { batch_size = len; }
65918
  return document_stream(*this, buf, len, batch_size, allow_comma_separated);
65919
}
65920
inline simdjson_result<document_stream> parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
65921
  return iterate_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size, allow_comma_separated);
65922
}
65923
inline simdjson_result<document_stream> parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept {
65924
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
65925
}
65926
inline simdjson_result<document_stream> parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept {
65927
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
65928
}
65929
65930
simdjson_inline size_t parser::capacity() const noexcept {
65931
  return _capacity;
65932
}
65933
simdjson_inline size_t parser::max_capacity() const noexcept {
65934
  return _max_capacity;
65935
}
65936
simdjson_inline size_t parser::max_depth() const noexcept {
65937
  return _max_depth;
65938
}
65939
65940
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
65941
  if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
65942
    _max_capacity = max_capacity;
65943
  } else {
65944
    _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
65945
  }
65946
}
65947
65948
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept {
65949
  uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement);
65950
  if (!end) { return STRING_ERROR; }
65951
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
65952
  dst = end;
65953
  return result;
65954
}
65955
65956
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept {
65957
  uint8_t *end = implementation->parse_wobbly_string(in.buf, dst);
65958
  if (!end) { return STRING_ERROR; }
65959
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
65960
  dst = end;
65961
  return result;
65962
}
65963
65964
} // namespace ondemand
65965
} // namespace icelake
65966
} // namespace simdjson
65967
65968
namespace simdjson {
65969
65970
simdjson_inline simdjson_result<icelake::ondemand::parser>::simdjson_result(icelake::ondemand::parser &&value) noexcept
65971
    : implementation_simdjson_result_base<icelake::ondemand::parser>(std::forward<icelake::ondemand::parser>(value)) {}
65972
simdjson_inline simdjson_result<icelake::ondemand::parser>::simdjson_result(error_code error) noexcept
65973
    : implementation_simdjson_result_base<icelake::ondemand::parser>(error) {}
65974
65975
} // namespace simdjson
65976
65977
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
65978
/* end file simdjson/generic/ondemand/parser-inl.h for icelake */
65979
/* including simdjson/generic/ondemand/raw_json_string-inl.h for icelake: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
65980
/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for icelake */
65981
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
65982
65983
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
65984
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */
65985
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
65986
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
65987
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
65988
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
65989
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
65990
65991
namespace simdjson {
65992
65993
namespace icelake {
65994
namespace ondemand {
65995
65996
simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
65997
65998
simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
65999
66000
66001
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
66002
  size_t pos{0};
66003
  // if the content has no escape character, just scan through it quickly!
66004
  for(;pos < target.size() && target[pos] != '\\';pos++) {}
66005
  // slow path may begin.
66006
  bool escaping{false};
66007
  for(;pos < target.size();pos++) {
66008
    if((target[pos] == '"') && !escaping) {
66009
      return false;
66010
    } else if(target[pos] == '\\') {
66011
      escaping = !escaping;
66012
    } else {
66013
      escaping = false;
66014
    }
66015
  }
66016
  return true;
66017
}
66018
66019
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
66020
  size_t pos{0};
66021
  // if the content has no escape character, just scan through it quickly!
66022
  for(;target[pos] && target[pos] != '\\';pos++) {}
66023
  // slow path may begin.
66024
  bool escaping{false};
66025
  for(;target[pos];pos++) {
66026
    if((target[pos] == '"') && !escaping) {
66027
      return false;
66028
    } else if(target[pos] == '\\') {
66029
      escaping = !escaping;
66030
    } else {
66031
      escaping = false;
66032
    }
66033
  }
66034
  return true;
66035
}
66036
66037
66038
simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
66039
  // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
66040
  return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
66041
}
66042
66043
simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
66044
  // Assumptions: does not contain unescaped quote characters, and
66045
  // the raw content is quote terminated within a valid JSON string.
66046
  if(target.size() <= SIMDJSON_PADDING) {
66047
    return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
66048
  }
66049
  const char * r{raw()};
66050
  size_t pos{0};
66051
  for(;pos < target.size();pos++) {
66052
    if(r[pos] != target[pos]) { return false; }
66053
  }
66054
  if(r[pos] != '"') { return false; }
66055
  return true;
66056
}
66057
66058
simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
66059
  const char * r{raw()};
66060
  size_t pos{0};
66061
  bool escaping{false};
66062
  for(;pos < target.size();pos++) {
66063
    if(r[pos] != target[pos]) { return false; }
66064
    // if target is a compile-time constant and it is free from
66065
    // quotes, then the next part could get optimized away through
66066
    // inlining.
66067
    if((target[pos] == '"') && !escaping) {
66068
      // We have reached the end of the raw_json_string but
66069
      // the target is not done.
66070
      return false;
66071
    } else if(target[pos] == '\\') {
66072
      escaping = !escaping;
66073
    } else {
66074
      escaping = false;
66075
    }
66076
  }
66077
  if(r[pos] != '"') { return false; }
66078
  return true;
66079
}
66080
66081
66082
simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
66083
  // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
66084
  // the raw content is quote terminated within a valid JSON string.
66085
  const char * r{raw()};
66086
  size_t pos{0};
66087
  for(;target[pos];pos++) {
66088
    if(r[pos] != target[pos]) { return false; }
66089
  }
66090
  if(r[pos] != '"') { return false; }
66091
  return true;
66092
}
66093
66094
simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
66095
  // Assumptions: does not contain unescaped quote characters, and
66096
  // the raw content is quote terminated within a valid JSON string.
66097
  const char * r{raw()};
66098
  size_t pos{0};
66099
  bool escaping{false};
66100
  for(;target[pos];pos++) {
66101
    if(r[pos] != target[pos]) { return false; }
66102
    // if target is a compile-time constant and it is free from
66103
    // quotes, then the next part could get optimized away through
66104
    // inlining.
66105
    if((target[pos] == '"') && !escaping) {
66106
      // We have reached the end of the raw_json_string but
66107
      // the target is not done.
66108
      return false;
66109
    } else if(target[pos] == '\\') {
66110
      escaping = !escaping;
66111
    } else {
66112
      escaping = false;
66113
    }
66114
  }
66115
  if(r[pos] != '"') { return false; }
66116
  return true;
66117
}
66118
66119
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
66120
  return a.unsafe_is_equal(c);
66121
}
66122
66123
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
66124
  return a == c;
66125
}
66126
66127
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
66128
  return !(a == c);
66129
}
66130
66131
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
66132
  return !(a == c);
66133
}
66134
66135
66136
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
66137
  return iter.unescape(*this, allow_replacement);
66138
}
66139
66140
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
66141
  return iter.unescape_wobbly(*this);
66142
}
66143
66144
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
66145
  bool in_escape = false;
66146
  const char *s = str.raw();
66147
  while (true) {
66148
    switch (*s) {
66149
      case '\\': in_escape = !in_escape; break;
66150
      case '"': if (in_escape) { in_escape = false; } else { return out; } break;
66151
      default: if (in_escape) { in_escape = false; }
66152
    }
66153
    out << *s;
66154
    s++;
66155
  }
66156
}
66157
66158
} // namespace ondemand
66159
} // namespace icelake
66160
} // namespace simdjson
66161
66162
namespace simdjson {
66163
66164
simdjson_inline simdjson_result<icelake::ondemand::raw_json_string>::simdjson_result(icelake::ondemand::raw_json_string &&value) noexcept
66165
    : implementation_simdjson_result_base<icelake::ondemand::raw_json_string>(std::forward<icelake::ondemand::raw_json_string>(value)) {}
66166
simdjson_inline simdjson_result<icelake::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
66167
    : implementation_simdjson_result_base<icelake::ondemand::raw_json_string>(error) {}
66168
66169
simdjson_inline simdjson_result<const char *> simdjson_result<icelake::ondemand::raw_json_string>::raw() const noexcept {
66170
  if (error()) { return error(); }
66171
  return first.raw();
66172
}
66173
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<icelake::ondemand::raw_json_string>::unescape(icelake::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
66174
  if (error()) { return error(); }
66175
  return first.unescape(iter, allow_replacement);
66176
}
66177
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<icelake::ondemand::raw_json_string>::unescape_wobbly(icelake::ondemand::json_iterator &iter) const noexcept {
66178
  if (error()) { return error(); }
66179
  return first.unescape_wobbly(iter);
66180
}
66181
} // namespace simdjson
66182
66183
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
66184
/* end file simdjson/generic/ondemand/raw_json_string-inl.h for icelake */
66185
/* including simdjson/generic/ondemand/serialization-inl.h for icelake: #include "simdjson/generic/ondemand/serialization-inl.h" */
66186
/* begin file simdjson/generic/ondemand/serialization-inl.h for icelake */
66187
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
66188
66189
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
66190
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */
66191
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
66192
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
66193
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
66194
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
66195
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
66196
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */
66197
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
66198
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
66199
66200
namespace simdjson {
66201
66202
inline std::string_view trim(const std::string_view str) noexcept {
66203
  // We can almost surely do better by rolling our own find_first_not_of function.
66204
  size_t first = str.find_first_not_of(" \t\n\r");
66205
  // If we have the empty string (just white space), then no trimming is possible, and
66206
  // we return the empty string_view.
66207
  if (std::string_view::npos == first) { return std::string_view(); }
66208
  size_t last = str.find_last_not_of(" \t\n\r");
66209
  return str.substr(first, (last - first + 1));
66210
}
66211
66212
66213
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::document& x) noexcept {
66214
  std::string_view v;
66215
  auto error = x.raw_json().get(v);
66216
  if(error) {return error; }
66217
  return trim(v);
66218
}
66219
66220
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::document_reference& x) noexcept {
66221
  std::string_view v;
66222
  auto error = x.raw_json().get(v);
66223
  if(error) {return error; }
66224
  return trim(v);
66225
}
66226
66227
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::value& x) noexcept {
66228
  /**
66229
   * If we somehow receive a value that has already been consumed,
66230
   * then the following code could be in trouble. E.g., we create
66231
   * an array as needed, but if an array was already created, then
66232
   * it could be bad.
66233
   */
66234
  using namespace icelake::ondemand;
66235
  icelake::ondemand::json_type t;
66236
  auto error = x.type().get(t);
66237
  if(error != SUCCESS) { return error; }
66238
  switch (t)
66239
  {
66240
    case json_type::array:
66241
    {
66242
      icelake::ondemand::array array;
66243
      error = x.get_array().get(array);
66244
      if(error) { return error; }
66245
      return to_json_string(array);
66246
    }
66247
    case json_type::object:
66248
    {
66249
      icelake::ondemand::object object;
66250
      error = x.get_object().get(object);
66251
      if(error) { return error; }
66252
      return to_json_string(object);
66253
    }
66254
    default:
66255
      return trim(x.raw_json_token());
66256
  }
66257
}
66258
66259
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::object& x) noexcept {
66260
  std::string_view v;
66261
  auto error = x.raw_json().get(v);
66262
  if(error) {return error; }
66263
  return trim(v);
66264
}
66265
66266
inline simdjson_result<std::string_view> to_json_string(icelake::ondemand::array& x) noexcept {
66267
  std::string_view v;
66268
  auto error = x.raw_json().get(v);
66269
  if(error) {return error; }
66270
  return trim(v);
66271
}
66272
66273
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::document> x) {
66274
  if (x.error()) { return x.error(); }
66275
  return to_json_string(x.value_unsafe());
66276
}
66277
66278
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::document_reference> x) {
66279
  if (x.error()) { return x.error(); }
66280
  return to_json_string(x.value_unsafe());
66281
}
66282
66283
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::value> x) {
66284
  if (x.error()) { return x.error(); }
66285
  return to_json_string(x.value_unsafe());
66286
}
66287
66288
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::object> x) {
66289
  if (x.error()) { return x.error(); }
66290
  return to_json_string(x.value_unsafe());
66291
}
66292
66293
inline simdjson_result<std::string_view> to_json_string(simdjson_result<icelake::ondemand::array> x) {
66294
  if (x.error()) { return x.error(); }
66295
  return to_json_string(x.value_unsafe());
66296
}
66297
} // namespace simdjson
66298
66299
namespace simdjson { namespace icelake { namespace ondemand {
66300
66301
#if SIMDJSON_EXCEPTIONS
66302
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::value x) {
66303
  std::string_view v;
66304
  auto error = simdjson::to_json_string(x).get(v);
66305
  if(error == simdjson::SUCCESS) {
66306
    return (out << v);
66307
  } else {
66308
    throw simdjson::simdjson_error(error);
66309
  }
66310
}
66311
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::value> x) {
66312
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
66313
  return (out << x.value());
66314
}
66315
#else
66316
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::value x) {
66317
  std::string_view v;
66318
  auto error = simdjson::to_json_string(x).get(v);
66319
  if(error == simdjson::SUCCESS) {
66320
    return (out << v);
66321
  } else {
66322
    return (out << error);
66323
  }
66324
}
66325
#endif
66326
66327
#if SIMDJSON_EXCEPTIONS
66328
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::array value) {
66329
  std::string_view v;
66330
  auto error = simdjson::to_json_string(value).get(v);
66331
  if(error == simdjson::SUCCESS) {
66332
    return (out << v);
66333
  } else {
66334
    throw simdjson::simdjson_error(error);
66335
  }
66336
}
66337
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::array> x) {
66338
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
66339
  return (out << x.value());
66340
}
66341
#else
66342
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::array value) {
66343
  std::string_view v;
66344
  auto error = simdjson::to_json_string(value).get(v);
66345
  if(error == simdjson::SUCCESS) {
66346
    return (out << v);
66347
  } else {
66348
    return (out << error);
66349
  }
66350
}
66351
#endif
66352
66353
#if SIMDJSON_EXCEPTIONS
66354
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::document& value)  {
66355
  std::string_view v;
66356
  auto error = simdjson::to_json_string(value).get(v);
66357
  if(error == simdjson::SUCCESS) {
66358
    return (out << v);
66359
  } else {
66360
    throw simdjson::simdjson_error(error);
66361
  }
66362
}
66363
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::document_reference& value)  {
66364
  std::string_view v;
66365
  auto error = simdjson::to_json_string(value).get(v);
66366
  if(error == simdjson::SUCCESS) {
66367
    return (out << v);
66368
  } else {
66369
    throw simdjson::simdjson_error(error);
66370
  }
66371
}
66372
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::document>&& x) {
66373
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
66374
  return (out << x.value());
66375
}
66376
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::icelake::ondemand::document_reference>&& x) {
66377
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
66378
  return (out << x.value());
66379
}
66380
#else
66381
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::document& value)  {
66382
  std::string_view v;
66383
  auto error = simdjson::to_json_string(value).get(v);
66384
  if(error == simdjson::SUCCESS) {
66385
    return (out << v);
66386
  } else {
66387
    return (out << error);
66388
  }
66389
}
66390
#endif
66391
66392
#if SIMDJSON_EXCEPTIONS
66393
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::object value) {
66394
  std::string_view v;
66395
  auto error = simdjson::to_json_string(value).get(v);
66396
  if(error == simdjson::SUCCESS) {
66397
    return (out << v);
66398
  } else {
66399
    throw simdjson::simdjson_error(error);
66400
  }
66401
}
66402
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::icelake::ondemand::object> x) {
66403
  if (x.error()) { throw  simdjson::simdjson_error(x.error()); }
66404
  return (out << x.value());
66405
}
66406
#else
66407
inline std::ostream& operator<<(std::ostream& out, simdjson::icelake::ondemand::object value) {
66408
  std::string_view v;
66409
  auto error = simdjson::to_json_string(value).get(v);
66410
  if(error == simdjson::SUCCESS) {
66411
    return (out << v);
66412
  } else {
66413
    return (out << error);
66414
  }
66415
}
66416
#endif
66417
}}} // namespace simdjson::icelake::ondemand
66418
66419
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
66420
/* end file simdjson/generic/ondemand/serialization-inl.h for icelake */
66421
/* including simdjson/generic/ondemand/token_iterator-inl.h for icelake: #include "simdjson/generic/ondemand/token_iterator-inl.h" */
66422
/* begin file simdjson/generic/ondemand/token_iterator-inl.h for icelake */
66423
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
66424
66425
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
66426
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */
66427
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
66428
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
66429
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
66430
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
66431
66432
namespace simdjson {
66433
namespace icelake {
66434
namespace ondemand {
66435
66436
simdjson_inline token_iterator::token_iterator(
66437
  const uint8_t *_buf,
66438
  token_position position
66439
) noexcept : buf{_buf}, _position{position}
66440
{
66441
}
66442
66443
simdjson_inline uint32_t token_iterator::current_offset() const noexcept {
66444
  return *(_position);
66445
}
66446
66447
66448
simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept {
66449
  return &buf[*(_position++)];
66450
}
66451
66452
simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept {
66453
  return &buf[*position];
66454
}
66455
simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept {
66456
  return *position;
66457
}
66458
simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept {
66459
  return *(position+1) - *position;
66460
}
66461
66462
simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept {
66463
  return *(position+2) - *(position) > *(position+1) - *(position) ?
66464
      *(position+1) - *(position)
66465
      : *(position+2) - *(position);
66466
}
66467
simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept {
66468
  return &buf[*(_position+delta)];
66469
}
66470
simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept {
66471
  return *(_position+delta);
66472
}
66473
simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept {
66474
  return *(_position+delta+1) - *(_position+delta);
66475
}
66476
66477
simdjson_inline token_position token_iterator::position() const noexcept {
66478
  return _position;
66479
}
66480
simdjson_inline void token_iterator::set_position(token_position target_position) noexcept {
66481
  _position = target_position;
66482
}
66483
66484
simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept {
66485
  return _position == other._position;
66486
}
66487
simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept {
66488
  return _position != other._position;
66489
}
66490
simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept {
66491
  return _position > other._position;
66492
}
66493
simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept {
66494
  return _position >= other._position;
66495
}
66496
simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept {
66497
  return _position < other._position;
66498
}
66499
simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept {
66500
  return _position <= other._position;
66501
}
66502
66503
} // namespace ondemand
66504
} // namespace icelake
66505
} // namespace simdjson
66506
66507
namespace simdjson {
66508
66509
simdjson_inline simdjson_result<icelake::ondemand::token_iterator>::simdjson_result(icelake::ondemand::token_iterator &&value) noexcept
66510
    : implementation_simdjson_result_base<icelake::ondemand::token_iterator>(std::forward<icelake::ondemand::token_iterator>(value)) {}
66511
simdjson_inline simdjson_result<icelake::ondemand::token_iterator>::simdjson_result(error_code error) noexcept
66512
    : implementation_simdjson_result_base<icelake::ondemand::token_iterator>(error) {}
66513
66514
} // namespace simdjson
66515
66516
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
66517
/* end file simdjson/generic/ondemand/token_iterator-inl.h for icelake */
66518
/* including simdjson/generic/ondemand/value-inl.h for icelake: #include "simdjson/generic/ondemand/value-inl.h" */
66519
/* begin file simdjson/generic/ondemand/value-inl.h for icelake */
66520
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
66521
66522
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
66523
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */
66524
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
66525
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
66526
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
66527
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
66528
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
66529
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
66530
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
66531
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
66532
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
66533
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
66534
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
66535
66536
namespace simdjson {
66537
namespace icelake {
66538
namespace ondemand {
66539
66540
simdjson_inline value::value(const value_iterator &_iter) noexcept
66541
  : iter{_iter}
66542
{
66543
}
66544
simdjson_inline value value::start(const value_iterator &iter) noexcept {
66545
  return iter;
66546
}
66547
simdjson_inline value value::resume(const value_iterator &iter) noexcept {
66548
  return iter;
66549
}
66550
66551
simdjson_inline simdjson_result<array> value::get_array() noexcept {
66552
  return array::start(iter);
66553
}
66554
simdjson_inline simdjson_result<object> value::get_object() noexcept {
66555
  return object::start(iter);
66556
}
66557
simdjson_inline simdjson_result<object> value::start_or_resume_object() noexcept {
66558
  if (iter.at_start()) {
66559
    return get_object();
66560
  } else {
66561
    return object::resume(iter);
66562
  }
66563
}
66564
66565
simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
66566
  return iter.get_raw_json_string();
66567
}
66568
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
66569
  return iter.get_string(allow_replacement);
66570
}
66571
template <typename string_type>
66572
simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
66573
  return iter.get_string(receiver, allow_replacement);
66574
}
66575
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
66576
  return iter.get_wobbly_string();
66577
}
66578
simdjson_inline simdjson_result<double> value::get_double() noexcept {
66579
  return iter.get_double();
66580
}
66581
simdjson_inline simdjson_result<double> value::get_double_in_string() noexcept {
66582
  return iter.get_double_in_string();
66583
}
66584
simdjson_inline simdjson_result<uint64_t> value::get_uint64() noexcept {
66585
  return iter.get_uint64();
66586
}
66587
simdjson_inline simdjson_result<uint64_t> value::get_uint64_in_string() noexcept {
66588
  return iter.get_uint64_in_string();
66589
}
66590
simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
66591
  return iter.get_int64();
66592
}
66593
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
66594
  return iter.get_int64_in_string();
66595
}
66596
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
66597
  return iter.get_bool();
66598
}
66599
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
66600
  return iter.is_null();
66601
}
66602
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
66603
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
66604
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
66605
template<> simdjson_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(false); }
66606
template<> simdjson_inline simdjson_result<number> value::get() noexcept { return get_number(); }
66607
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
66608
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
66609
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
66610
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
66611
66612
template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
66613
  return get<T>().get(out);
66614
}
66615
66616
#if SIMDJSON_EXCEPTIONS
66617
template <class T>
66618
simdjson_inline value::operator T() noexcept(false) {
66619
  return get<T>();
66620
}
66621
simdjson_inline value::operator array() noexcept(false) {
66622
  return get_array();
66623
}
66624
simdjson_inline value::operator object() noexcept(false) {
66625
  return get_object();
66626
}
66627
simdjson_inline value::operator uint64_t() noexcept(false) {
66628
  return get_uint64();
66629
}
66630
simdjson_inline value::operator int64_t() noexcept(false) {
66631
  return get_int64();
66632
}
66633
simdjson_inline value::operator double() noexcept(false) {
66634
  return get_double();
66635
}
66636
simdjson_inline value::operator std::string_view() noexcept(false) {
66637
  return get_string(false);
66638
}
66639
simdjson_inline value::operator raw_json_string() noexcept(false) {
66640
  return get_raw_json_string();
66641
}
66642
simdjson_inline value::operator bool() noexcept(false) {
66643
  return get_bool();
66644
}
66645
#endif
66646
66647
simdjson_inline simdjson_result<array_iterator> value::begin() & noexcept {
66648
  return get_array().begin();
66649
}
66650
simdjson_inline simdjson_result<array_iterator> value::end() & noexcept {
66651
  return {};
66652
}
66653
simdjson_inline simdjson_result<size_t> value::count_elements() & noexcept {
66654
  simdjson_result<size_t> answer;
66655
  auto a = get_array();
66656
  answer = a.count_elements();
66657
  // count_elements leaves you pointing inside the array, at the first element.
66658
  // We need to move back so that the user can create a new array (which requires that
66659
  // we point at '[').
66660
  iter.move_at_start();
66661
  return answer;
66662
}
66663
simdjson_inline simdjson_result<size_t> value::count_fields() & noexcept {
66664
  simdjson_result<size_t> answer;
66665
  auto a = get_object();
66666
  answer = a.count_fields();
66667
  iter.move_at_start();
66668
  return answer;
66669
}
66670
simdjson_inline simdjson_result<value> value::at(size_t index) noexcept {
66671
  auto a = get_array();
66672
  return a.at(index);
66673
}
66674
66675
simdjson_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
66676
  return start_or_resume_object().find_field(key);
66677
}
66678
simdjson_inline simdjson_result<value> value::find_field(const char *key) noexcept {
66679
  return start_or_resume_object().find_field(key);
66680
}
66681
66682
simdjson_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
66683
  return start_or_resume_object().find_field_unordered(key);
66684
}
66685
simdjson_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
66686
  return start_or_resume_object().find_field_unordered(key);
66687
}
66688
66689
simdjson_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
66690
  return start_or_resume_object()[key];
66691
}
66692
simdjson_inline simdjson_result<value> value::operator[](const char *key) noexcept {
66693
  return start_or_resume_object()[key];
66694
}
66695
66696
simdjson_inline simdjson_result<json_type> value::type() noexcept {
66697
  return iter.type();
66698
}
66699
66700
simdjson_inline simdjson_result<bool> value::is_scalar() noexcept {
66701
  json_type this_type;
66702
  auto error = type().get(this_type);
66703
  if(error) { return error; }
66704
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
66705
}
66706
66707
simdjson_inline simdjson_result<bool> value::is_string() noexcept {
66708
  json_type this_type;
66709
  auto error = type().get(this_type);
66710
  if(error) { return error; }
66711
  return (this_type == json_type::string);
66712
}
66713
66714
66715
simdjson_inline bool value::is_negative() noexcept {
66716
  return iter.is_negative();
66717
}
66718
66719
simdjson_inline simdjson_result<bool> value::is_integer() noexcept {
66720
  return iter.is_integer();
66721
}
66722
simdjson_warn_unused simdjson_inline simdjson_result<number_type> value::get_number_type() noexcept {
66723
  return iter.get_number_type();
66724
}
66725
simdjson_warn_unused simdjson_inline simdjson_result<number> value::get_number() noexcept {
66726
  return iter.get_number();
66727
}
66728
66729
simdjson_inline std::string_view value::raw_json_token() noexcept {
66730
  return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
66731
}
66732
66733
simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
66734
  json_type t;
66735
  SIMDJSON_TRY(type().get(t));
66736
  switch (t)
66737
  {
66738
    case json_type::array: {
66739
      ondemand::array array;
66740
      SIMDJSON_TRY(get_array().get(array));
66741
      return array.raw_json();
66742
    }
66743
    case json_type::object: {
66744
      ondemand::object object;
66745
      SIMDJSON_TRY(get_object().get(object));
66746
      return object.raw_json();
66747
    }
66748
    default:
66749
      return raw_json_token();
66750
  }
66751
}
66752
66753
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
66754
  return iter.json_iter().current_location();
66755
}
66756
66757
simdjson_inline int32_t value::current_depth() const noexcept{
66758
  return iter.json_iter().depth();
66759
}
66760
66761
simdjson_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
66762
  json_type t;
66763
  SIMDJSON_TRY(type().get(t));
66764
  switch (t)
66765
  {
66766
    case json_type::array:
66767
      return (*this).get_array().at_pointer(json_pointer);
66768
    case json_type::object:
66769
      return (*this).get_object().at_pointer(json_pointer);
66770
    default:
66771
      return INVALID_JSON_POINTER;
66772
  }
66773
}
66774
66775
simdjson_inline simdjson_result<value> value::at_path(std::string_view json_path) noexcept {
66776
  json_type t;
66777
  SIMDJSON_TRY(type().get(t));
66778
  switch (t) {
66779
  case json_type::array:
66780
      return (*this).get_array().at_path(json_path);
66781
  case json_type::object:
66782
      return (*this).get_object().at_path(json_path);
66783
  default:
66784
      return INVALID_JSON_POINTER;
66785
  }
66786
}
66787
66788
} // namespace ondemand
66789
} // namespace icelake
66790
} // namespace simdjson
66791
66792
namespace simdjson {
66793
66794
simdjson_inline simdjson_result<icelake::ondemand::value>::simdjson_result(
66795
  icelake::ondemand::value &&value
66796
) noexcept :
66797
    implementation_simdjson_result_base<icelake::ondemand::value>(
66798
      std::forward<icelake::ondemand::value>(value)
66799
    )
66800
{
66801
}
66802
simdjson_inline simdjson_result<icelake::ondemand::value>::simdjson_result(
66803
  error_code error
66804
) noexcept :
66805
    implementation_simdjson_result_base<icelake::ondemand::value>(error)
66806
{
66807
}
66808
simdjson_inline simdjson_result<size_t> simdjson_result<icelake::ondemand::value>::count_elements() & noexcept {
66809
  if (error()) { return error(); }
66810
  return first.count_elements();
66811
}
66812
simdjson_inline simdjson_result<size_t> simdjson_result<icelake::ondemand::value>::count_fields() & noexcept {
66813
  if (error()) { return error(); }
66814
  return first.count_fields();
66815
}
66816
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::at(size_t index) noexcept {
66817
  if (error()) { return error(); }
66818
  return first.at(index);
66819
}
66820
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::value>::begin() & noexcept {
66821
  if (error()) { return error(); }
66822
  return first.begin();
66823
}
66824
simdjson_inline simdjson_result<icelake::ondemand::array_iterator> simdjson_result<icelake::ondemand::value>::end() & noexcept {
66825
  if (error()) { return error(); }
66826
  return {};
66827
}
66828
66829
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::find_field(std::string_view key) noexcept {
66830
  if (error()) { return error(); }
66831
  return first.find_field(key);
66832
}
66833
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::find_field(const char *key) noexcept {
66834
  if (error()) { return error(); }
66835
  return first.find_field(key);
66836
}
66837
66838
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
66839
  if (error()) { return error(); }
66840
  return first.find_field_unordered(key);
66841
}
66842
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::find_field_unordered(const char *key) noexcept {
66843
  if (error()) { return error(); }
66844
  return first.find_field_unordered(key);
66845
}
66846
66847
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::operator[](std::string_view key) noexcept {
66848
  if (error()) { return error(); }
66849
  return first[key];
66850
}
66851
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::operator[](const char *key) noexcept {
66852
  if (error()) { return error(); }
66853
  return first[key];
66854
}
66855
66856
simdjson_inline simdjson_result<icelake::ondemand::array> simdjson_result<icelake::ondemand::value>::get_array() noexcept {
66857
  if (error()) { return error(); }
66858
  return first.get_array();
66859
}
66860
simdjson_inline simdjson_result<icelake::ondemand::object> simdjson_result<icelake::ondemand::value>::get_object() noexcept {
66861
  if (error()) { return error(); }
66862
  return first.get_object();
66863
}
66864
simdjson_inline simdjson_result<uint64_t> simdjson_result<icelake::ondemand::value>::get_uint64() noexcept {
66865
  if (error()) { return error(); }
66866
  return first.get_uint64();
66867
}
66868
simdjson_inline simdjson_result<uint64_t> simdjson_result<icelake::ondemand::value>::get_uint64_in_string() noexcept {
66869
  if (error()) { return error(); }
66870
  return first.get_uint64_in_string();
66871
}
66872
simdjson_inline simdjson_result<int64_t> simdjson_result<icelake::ondemand::value>::get_int64() noexcept {
66873
  if (error()) { return error(); }
66874
  return first.get_int64();
66875
}
66876
simdjson_inline simdjson_result<int64_t> simdjson_result<icelake::ondemand::value>::get_int64_in_string() noexcept {
66877
  if (error()) { return error(); }
66878
  return first.get_int64_in_string();
66879
}
66880
simdjson_inline simdjson_result<double> simdjson_result<icelake::ondemand::value>::get_double() noexcept {
66881
  if (error()) { return error(); }
66882
  return first.get_double();
66883
}
66884
simdjson_inline simdjson_result<double> simdjson_result<icelake::ondemand::value>::get_double_in_string() noexcept {
66885
  if (error()) { return error(); }
66886
  return first.get_double_in_string();
66887
}
66888
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::value>::get_string(bool allow_replacement) noexcept {
66889
  if (error()) { return error(); }
66890
  return first.get_string(allow_replacement);
66891
}
66892
template <typename string_type>
66893
simdjson_inline error_code simdjson_result<icelake::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
66894
  if (error()) { return error(); }
66895
  return first.get_string(receiver, allow_replacement);
66896
}
66897
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::value>::get_wobbly_string() noexcept {
66898
  if (error()) { return error(); }
66899
  return first.get_wobbly_string();
66900
}
66901
simdjson_inline simdjson_result<icelake::ondemand::raw_json_string> simdjson_result<icelake::ondemand::value>::get_raw_json_string() noexcept {
66902
  if (error()) { return error(); }
66903
  return first.get_raw_json_string();
66904
}
66905
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::value>::get_bool() noexcept {
66906
  if (error()) { return error(); }
66907
  return first.get_bool();
66908
}
66909
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::value>::is_null() noexcept {
66910
  if (error()) { return error(); }
66911
  return first.is_null();
66912
}
66913
66914
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<icelake::ondemand::value>::get() noexcept {
66915
  if (error()) { return error(); }
66916
  return first.get<T>();
66917
}
66918
template<typename T> simdjson_inline error_code simdjson_result<icelake::ondemand::value>::get(T &out) noexcept {
66919
  if (error()) { return error(); }
66920
  return first.get<T>(out);
66921
}
66922
66923
template<> simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::get<icelake::ondemand::value>() noexcept  {
66924
  if (error()) { return error(); }
66925
  return std::move(first);
66926
}
66927
template<> simdjson_inline error_code simdjson_result<icelake::ondemand::value>::get<icelake::ondemand::value>(icelake::ondemand::value &out) noexcept {
66928
  if (error()) { return error(); }
66929
  out = first;
66930
  return SUCCESS;
66931
}
66932
66933
simdjson_inline simdjson_result<icelake::ondemand::json_type> simdjson_result<icelake::ondemand::value>::type() noexcept {
66934
  if (error()) { return error(); }
66935
  return first.type();
66936
}
66937
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::value>::is_scalar() noexcept {
66938
  if (error()) { return error(); }
66939
  return first.is_scalar();
66940
}
66941
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::value>::is_string() noexcept {
66942
  if (error()) { return error(); }
66943
  return first.is_string();
66944
}
66945
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::value>::is_negative() noexcept {
66946
  if (error()) { return error(); }
66947
  return first.is_negative();
66948
}
66949
simdjson_inline simdjson_result<bool> simdjson_result<icelake::ondemand::value>::is_integer() noexcept {
66950
  if (error()) { return error(); }
66951
  return first.is_integer();
66952
}
66953
simdjson_inline simdjson_result<icelake::number_type> simdjson_result<icelake::ondemand::value>::get_number_type() noexcept {
66954
  if (error()) { return error(); }
66955
  return first.get_number_type();
66956
}
66957
simdjson_inline simdjson_result<icelake::ondemand::number> simdjson_result<icelake::ondemand::value>::get_number() noexcept {
66958
  if (error()) { return error(); }
66959
  return first.get_number();
66960
}
66961
#if SIMDJSON_EXCEPTIONS
66962
template <class T>
66963
simdjson_inline simdjson_result<icelake::ondemand::value>::operator T() noexcept(false) {
66964
  if (error()) { throw simdjson_error(error()); }
66965
  return static_cast<T>(first);
66966
}
66967
simdjson_inline simdjson_result<icelake::ondemand::value>::operator icelake::ondemand::array() noexcept(false) {
66968
  if (error()) { throw simdjson_error(error()); }
66969
  return first;
66970
}
66971
simdjson_inline simdjson_result<icelake::ondemand::value>::operator icelake::ondemand::object() noexcept(false) {
66972
  if (error()) { throw simdjson_error(error()); }
66973
  return first;
66974
}
66975
simdjson_inline simdjson_result<icelake::ondemand::value>::operator uint64_t() noexcept(false) {
66976
  if (error()) { throw simdjson_error(error()); }
66977
  return first;
66978
}
66979
simdjson_inline simdjson_result<icelake::ondemand::value>::operator int64_t() noexcept(false) {
66980
  if (error()) { throw simdjson_error(error()); }
66981
  return first;
66982
}
66983
simdjson_inline simdjson_result<icelake::ondemand::value>::operator double() noexcept(false) {
66984
  if (error()) { throw simdjson_error(error()); }
66985
  return first;
66986
}
66987
simdjson_inline simdjson_result<icelake::ondemand::value>::operator std::string_view() noexcept(false) {
66988
  if (error()) { throw simdjson_error(error()); }
66989
  return first;
66990
}
66991
simdjson_inline simdjson_result<icelake::ondemand::value>::operator icelake::ondemand::raw_json_string() noexcept(false) {
66992
  if (error()) { throw simdjson_error(error()); }
66993
  return first;
66994
}
66995
simdjson_inline simdjson_result<icelake::ondemand::value>::operator bool() noexcept(false) {
66996
  if (error()) { throw simdjson_error(error()); }
66997
  return first;
66998
}
66999
#endif
67000
67001
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::value>::raw_json_token() noexcept {
67002
  if (error()) { return error(); }
67003
  return first.raw_json_token();
67004
}
67005
67006
simdjson_inline simdjson_result<std::string_view> simdjson_result<icelake::ondemand::value>::raw_json() noexcept {
67007
  if (error()) { return error(); }
67008
  return first.raw_json();
67009
}
67010
67011
simdjson_inline simdjson_result<const char *> simdjson_result<icelake::ondemand::value>::current_location() noexcept {
67012
  if (error()) { return error(); }
67013
  return first.current_location();
67014
}
67015
67016
simdjson_inline simdjson_result<int32_t> simdjson_result<icelake::ondemand::value>::current_depth() const noexcept {
67017
  if (error()) { return error(); }
67018
  return first.current_depth();
67019
}
67020
67021
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::at_pointer(
67022
    std::string_view json_pointer) noexcept {
67023
  if (error()) {
67024
      return error();
67025
  }
67026
  return first.at_pointer(json_pointer);
67027
}
67028
67029
simdjson_inline simdjson_result<icelake::ondemand::value> simdjson_result<icelake::ondemand::value>::at_path(
67030
      std::string_view json_path) noexcept {
67031
  if (error()) {
67032
    return error();
67033
  }
67034
  return first.at_path(json_path);
67035
}
67036
67037
} // namespace simdjson
67038
67039
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
67040
/* end file simdjson/generic/ondemand/value-inl.h for icelake */
67041
/* including simdjson/generic/ondemand/value_iterator-inl.h for icelake: #include "simdjson/generic/ondemand/value_iterator-inl.h" */
67042
/* begin file simdjson/generic/ondemand/value_iterator-inl.h for icelake */
67043
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
67044
67045
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
67046
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */
67047
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
67048
/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */
67049
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
67050
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
67051
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */
67052
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
67053
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
67054
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
67055
67056
namespace simdjson {
67057
namespace icelake {
67058
namespace ondemand {
67059
67060
simdjson_inline value_iterator::value_iterator(
67061
  json_iterator *json_iter,
67062
  depth_t depth,
67063
  token_position start_position
67064
) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
67065
{
67066
}
67067
67068
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
67069
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
67070
  return started_object();
67071
}
67072
67073
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
67074
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
67075
  return started_root_object();
67076
}
67077
67078
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
67079
  assert_at_container_start();
67080
#if SIMDJSON_DEVELOPMENT_CHECKS
67081
  _json_iter->set_start_position(_depth, start_position());
67082
#endif
67083
  if (*_json_iter->peek() == '}') {
67084
    logger::log_value(*_json_iter, "empty object");
67085
    _json_iter->return_current_and_advance();
67086
    end_container();
67087
    return false;
67088
  }
67089
  return true;
67090
}
67091
67092
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
67093
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
67094
  // current document. It only works in the normal mode where we have indexed a single document.
67095
  // Note that adding a check for 'streaming' is not expensive since we only have at most
67096
  // one root element.
67097
  if ( ! _json_iter->streaming() ) {
67098
    // The following lines do not fully protect against garbage content within the
67099
    // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
67100
    // call `at_end()` on the document instance at the end of the processing to
67101
    // ensure that the processing has finished at the end.
67102
    //
67103
    if (*_json_iter->peek_last() != '}') {
67104
      _json_iter->abandon();
67105
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
67106
    }
67107
    // If the last character is } *and* the first gibberish character is also '}'
67108
    // then on-demand could accidentally go over. So we need additional checks.
67109
    // https://github.com/simdjson/simdjson/issues/1834
67110
    // Checking that the document is balanced requires a full scan which is potentially
67111
    // expensive, but it only happens in edge cases where the first padding character is
67112
    // a closing bracket.
67113
    if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
67114
      _json_iter->abandon();
67115
      // The exact error would require more work. It will typically be an unclosed object.
67116
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
67117
    }
67118
  }
67119
  return SUCCESS;
67120
}
67121
67122
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
67123
  auto error = check_root_object();
67124
  if(error) { return error; }
67125
  return started_object();
67126
}
67127
67128
simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
67129
#if SIMDJSON_CHECK_EOF
67130
    if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
67131
    // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
67132
#endif // SIMDJSON_CHECK_EOF
67133
    _json_iter->ascend_to(depth()-1);
67134
    return SUCCESS;
67135
}
67136
67137
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
67138
  assert_at_next();
67139
67140
  // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
67141
  // obligated to verify there are more tokens if they are not the top level.
67142
  switch (*_json_iter->return_current_and_advance()) {
67143
    case '}':
67144
      logger::log_end_value(*_json_iter, "object");
67145
      SIMDJSON_TRY( end_container() );
67146
      return false;
67147
    case ',':
67148
      return true;
67149
    default:
67150
      return report_error(TAPE_ERROR, "Missing comma between object fields");
67151
  }
67152
}
67153
67154
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
67155
  error_code error;
67156
  bool has_value;
67157
  //
67158
  // Initially, the object can be in one of a few different places:
67159
  //
67160
  // 1. The start of the object, at the first field:
67161
  //
67162
  //    ```
67163
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67164
  //      ^ (depth 2, index 1)
67165
  //    ```
67166
  if (at_first_field()) {
67167
    has_value = true;
67168
67169
  //
67170
  // 2. When a previous search did not yield a value or the object is empty:
67171
  //
67172
  //    ```
67173
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67174
  //                                     ^ (depth 0)
67175
  //    { }
67176
  //        ^ (depth 0, index 2)
67177
  //    ```
67178
  //
67179
  } else if (!is_open()) {
67180
#if SIMDJSON_DEVELOPMENT_CHECKS
67181
    // If we're past the end of the object, we're being iterated out of order.
67182
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
67183
    // this object iterator will blithely scan that object for fields.
67184
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
67185
#endif
67186
    return false;
67187
67188
  // 3. When a previous search found a field or an iterator yielded a value:
67189
  //
67190
  //    ```
67191
  //    // When a field was not fully consumed (or not even touched at all)
67192
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67193
  //           ^ (depth 2)
67194
  //    // When a field was fully consumed
67195
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67196
  //                   ^ (depth 1)
67197
  //    // When the last field was fully consumed
67198
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67199
  //                                   ^ (depth 1)
67200
  //    ```
67201
  //
67202
  } else {
67203
    if ((error = skip_child() )) { abandon(); return error; }
67204
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
67205
#if SIMDJSON_DEVELOPMENT_CHECKS
67206
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
67207
#endif
67208
  }
67209
  while (has_value) {
67210
    // Get the key and colon, stopping at the value.
67211
    raw_json_string actual_key;
67212
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
67213
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
67214
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
67215
    // The depth is left unchanged by field_key().
67216
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
67217
    // field_value() will advance and check that we find a ':' separating the
67218
    // key and the value. It will also increment the depth by one.
67219
    if ((error = field_value() )) { abandon(); return error; }
67220
    // If it matches, stop and return
67221
    // We could do it this way if we wanted to allow arbitrary
67222
    // key content (including escaped quotes).
67223
    //if (actual_key.unsafe_is_equal(max_key_length, key)) {
67224
    // Instead we do the following which may trigger buffer overruns if the
67225
    // user provides an adversarial key (containing a well placed unescaped quote
67226
    // character and being longer than the number of bytes remaining in the JSON
67227
    // input).
67228
    if (actual_key.unsafe_is_equal(key)) {
67229
      logger::log_event(*this, "match", key, -2);
67230
      // If we return here, then we return while pointing at the ':' that we just checked.
67231
      return true;
67232
    }
67233
67234
    // No match: skip the value and see if , or } is next
67235
    logger::log_event(*this, "no match", key, -2);
67236
    // The call to skip_child is meant to skip over the value corresponding to the key.
67237
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
67238
    SIMDJSON_TRY( skip_child() ); // Skip the value entirely
67239
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
67240
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
67241
    // then we are in error and we abort.
67242
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
67243
  }
67244
67245
  // If the loop ended, we're out of fields to look at.
67246
  return false;
67247
}
67248
67249
SIMDJSON_PUSH_DISABLE_WARNINGS
67250
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
67251
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
67252
  /**
67253
   * When find_field_unordered_raw is called, we can either be pointing at the
67254
   * first key, pointing outside (at the closing brace) or if a key was matched
67255
   * we can be either pointing right afterthe ':' right before the value (that we need skip),
67256
   * or we may have consumed the value and we might be at a comma or at the
67257
   * final brace (ready for a call to has_next_field()).
67258
   */
67259
  error_code error;
67260
  bool has_value;
67261
67262
  // First, we scan from that point to the end.
67263
  // If we don't find a match, we may loop back around, and scan from the beginning to that point.
67264
  token_position search_start = _json_iter->position();
67265
67266
  // We want to know whether we need to go back to the beginning.
67267
  bool at_first = at_first_field();
67268
  ///////////////
67269
  // Initially, the object can be in one of a few different places:
67270
  //
67271
  // 1. At the first key:
67272
  //
67273
  //    ```
67274
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67275
  //      ^ (depth 2, index 1)
67276
  //    ```
67277
  //
67278
  if (at_first) {
67279
    has_value = true;
67280
67281
  // 2. When a previous search did not yield a value or the object is empty:
67282
  //
67283
  //    ```
67284
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67285
  //                                     ^ (depth 0)
67286
  //    { }
67287
  //        ^ (depth 0, index 2)
67288
  //    ```
67289
  //
67290
  } else if (!is_open()) {
67291
67292
#if SIMDJSON_DEVELOPMENT_CHECKS
67293
    // If we're past the end of the object, we're being iterated out of order.
67294
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
67295
    // this object iterator will blithely scan that object for fields.
67296
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
67297
#endif
67298
    SIMDJSON_TRY(reset_object().get(has_value));
67299
    at_first = true;
67300
  // 3. When a previous search found a field or an iterator yielded a value:
67301
  //
67302
  //    ```
67303
  //    // When a field was not fully consumed (or not even touched at all)
67304
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67305
  //           ^ (depth 2)
67306
  //    // When a field was fully consumed
67307
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67308
  //                   ^ (depth 1)
67309
  //    // When the last field was fully consumed
67310
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67311
  //                                   ^ (depth 1)
67312
  //    ```
67313
  //
67314
  } else {
67315
    // If someone queried a key but they not did access the value, then we are left pointing
67316
    // at the ':' and we need to move forward through the value... If the value was
67317
    // processed then skip_child() does not move the iterator (but may adjust the depth).
67318
    if ((error = skip_child() )) { abandon(); return error; }
67319
    search_start = _json_iter->position();
67320
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
67321
#if SIMDJSON_DEVELOPMENT_CHECKS
67322
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
67323
#endif
67324
  }
67325
67326
  // After initial processing, we will be in one of two states:
67327
  //
67328
  // ```
67329
  // // At the beginning of a field
67330
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67331
  //   ^ (depth 1)
67332
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67333
  //                  ^ (depth 1)
67334
  // // At the end of the object
67335
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
67336
  //                                  ^ (depth 0)
67337
  // ```
67338
  //
67339
  // Next, we find a match starting from the current position.
67340
  while (has_value) {
67341
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
67342
67343
    // Get the key and colon, stopping at the value.
67344
    raw_json_string actual_key;
67345
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
67346
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
67347
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
67348
    // The depth is left unchanged by field_key().
67349
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
67350
    // field_value() will advance and check that we find a ':' separating the
67351
    // key and the value. It will also increment the depth by one.
67352
    if ((error = field_value() )) { abandon(); return error; }
67353
67354
    // If it matches, stop and return
67355
    // We could do it this way if we wanted to allow arbitrary
67356
    // key content (including escaped quotes).
67357
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
67358
    // Instead we do the following which may trigger buffer overruns if the
67359
    // user provides an adversarial key (containing a well placed unescaped quote
67360
    // character and being longer than the number of bytes remaining in the JSON
67361
    // input).
67362
    if (actual_key.unsafe_is_equal(key)) {
67363
      logger::log_event(*this, "match", key, -2);
67364
      // If we return here, then we return while pointing at the ':' that we just checked.
67365
      return true;
67366
    }
67367
67368
    // No match: skip the value and see if , or } is next
67369
    logger::log_event(*this, "no match", key, -2);
67370
    // The call to skip_child is meant to skip over the value corresponding to the key.
67371
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
67372
    SIMDJSON_TRY( skip_child() );
67373
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
67374
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
67375
    // then we are in error and we abort.
67376
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
67377
  }
67378
  // Performance note: it maybe wasteful to rewind to the beginning when there might be
67379
  // no other query following. Indeed, it would require reskipping the whole object.
67380
  // Instead, you can just stay where you are. If there is a new query, there is always time
67381
  // to rewind.
67382
  if(at_first) { return false; }
67383
67384
  // If we reach the end without finding a match, search the rest of the fields starting at the
67385
  // beginning of the object.
67386
  // (We have already run through the object before, so we've already validated its structure. We
67387
  // don't check errors in this bit.)
67388
  SIMDJSON_TRY(reset_object().get(has_value));
67389
  while (true) {
67390
    SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
67391
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
67392
67393
    // Get the key and colon, stopping at the value.
67394
    raw_json_string actual_key;
67395
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
67396
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
67397
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
67398
    // The depth is left unchanged by field_key().
67399
    error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
67400
    // field_value() will advance and check that we find a ':' separating the
67401
    // key and the value.  It will also increment the depth by one.
67402
    error = field_value(); SIMDJSON_ASSUME(!error);
67403
67404
    // If it matches, stop and return
67405
    // We could do it this way if we wanted to allow arbitrary
67406
    // key content (including escaped quotes).
67407
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
67408
    // Instead we do the following which may trigger buffer overruns if the
67409
    // user provides an adversarial key (containing a well placed unescaped quote
67410
    // character and being longer than the number of bytes remaining in the JSON
67411
    // input).
67412
    if (actual_key.unsafe_is_equal(key)) {
67413
      logger::log_event(*this, "match", key, -2);
67414
      // If we return here, then we return while pointing at the ':' that we just checked.
67415
      return true;
67416
    }
67417
67418
    // No match: skip the value and see if , or } is next
67419
    logger::log_event(*this, "no match", key, -2);
67420
    // The call to skip_child is meant to skip over the value corresponding to the key.
67421
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
67422
    SIMDJSON_TRY( skip_child() );
67423
    // If we reached the end of the key-value pair we started from, then we know
67424
    // that the key is not there so we return false. We are either right before
67425
    // the next comma or the final brace.
67426
    if(_json_iter->position() == search_start) { return false; }
67427
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
67428
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
67429
    // then we are in error and we abort.
67430
    error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
67431
    // If we make the mistake of exiting here, then we could be left pointing at a key
67432
    // in the middle of an object. That's not an allowable state.
67433
  }
67434
  // If the loop ended, we're out of fields to look at. The program should
67435
  // never reach this point.
67436
  return false;
67437
}
67438
SIMDJSON_POP_DISABLE_WARNINGS
67439
67440
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
67441
  assert_at_next();
67442
67443
  const uint8_t *key = _json_iter->return_current_and_advance();
67444
  if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
67445
  return raw_json_string(key);
67446
}
67447
67448
simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
67449
  assert_at_next();
67450
67451
  if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
67452
  _json_iter->descend_to(depth()+1);
67453
  return SUCCESS;
67454
}
67455
67456
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
67457
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
67458
  return started_array();
67459
}
67460
67461
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
67462
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
67463
  return started_root_array();
67464
}
67465
67466
inline std::string value_iterator::to_string() const noexcept {
67467
  auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
67468
  if(_json_iter != nullptr) { answer +=  _json_iter->to_string(); }
67469
  answer += std::string(" ]");
67470
  return answer;
67471
}
67472
67473
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
67474
  assert_at_container_start();
67475
  if (*_json_iter->peek() == ']') {
67476
    logger::log_value(*_json_iter, "empty array");
67477
    _json_iter->return_current_and_advance();
67478
    SIMDJSON_TRY( end_container() );
67479
    return false;
67480
  }
67481
  _json_iter->descend_to(depth()+1);
67482
#if SIMDJSON_DEVELOPMENT_CHECKS
67483
  _json_iter->set_start_position(_depth, start_position());
67484
#endif
67485
  return true;
67486
}
67487
67488
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
67489
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
67490
  // current document. It only works in the normal mode where we have indexed a single document.
67491
  // Note that adding a check for 'streaming' is not expensive since we only have at most
67492
  // one root element.
67493
  if ( ! _json_iter->streaming() ) {
67494
    // The following lines do not fully protect against garbage content within the
67495
    // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
67496
    // also call `at_end()` on the document instance at the end of the processing to
67497
    // ensure that the processing has finished at the end.
67498
    //
67499
    if (*_json_iter->peek_last() != ']') {
67500
      _json_iter->abandon();
67501
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
67502
    }
67503
    // If the last character is ] *and* the first gibberish character is also ']'
67504
    // then on-demand could accidentally go over. So we need additional checks.
67505
    // https://github.com/simdjson/simdjson/issues/1834
67506
    // Checking that the document is balanced requires a full scan which is potentially
67507
    // expensive, but it only happens in edge cases where the first padding character is
67508
    // a closing bracket.
67509
    if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
67510
      _json_iter->abandon();
67511
      // The exact error would require more work. It will typically be an unclosed array.
67512
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
67513
    }
67514
  }
67515
  return SUCCESS;
67516
}
67517
67518
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
67519
  auto error = check_root_array();
67520
  if (error) { return error; }
67521
  return started_array();
67522
}
67523
67524
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
67525
  assert_at_next();
67526
67527
  logger::log_event(*this, "has_next_element");
67528
  switch (*_json_iter->return_current_and_advance()) {
67529
    case ']':
67530
      logger::log_end_value(*_json_iter, "array");
67531
      SIMDJSON_TRY( end_container() );
67532
      return false;
67533
    case ',':
67534
      _json_iter->descend_to(depth()+1);
67535
      return true;
67536
    default:
67537
      return report_error(TAPE_ERROR, "Missing comma between array elements");
67538
  }
67539
}
67540
67541
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
67542
  auto not_true = atomparsing::str4ncmp(json, "true");
67543
  auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
67544
  bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
67545
  if (error) { return incorrect_type_error("Not a boolean"); }
67546
  return simdjson_result<bool>(!not_true);
67547
}
67548
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
67549
  bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
67550
  // if we start with 'n', we must be a null
67551
  if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
67552
  return is_null_string;
67553
}
67554
67555
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
67556
  return get_raw_json_string().unescape(json_iter(), allow_replacement);
67557
}
67558
template <typename string_type>
67559
simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
67560
  std::string_view content;
67561
  auto err = get_string(allow_replacement).get(content);
67562
  if (err) { return err; }
67563
  receiver = content;
67564
  return SUCCESS;
67565
}
67566
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
67567
  return get_raw_json_string().unescape_wobbly(json_iter());
67568
}
67569
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
67570
  auto json = peek_scalar("string");
67571
  if (*json != '"') { return incorrect_type_error("Not a string"); }
67572
  advance_scalar("string");
67573
  return raw_json_string(json+1);
67574
}
67575
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
67576
  auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
67577
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
67578
  return result;
67579
}
67580
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
67581
  auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
67582
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
67583
  return result;
67584
}
67585
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
67586
  auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
67587
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
67588
  return result;
67589
}
67590
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
67591
  auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
67592
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
67593
  return result;
67594
}
67595
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
67596
  auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
67597
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
67598
  return result;
67599
}
67600
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
67601
  auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
67602
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
67603
  return result;
67604
}
67605
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
67606
  auto result = parse_bool(peek_non_root_scalar("bool"));
67607
  if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
67608
  return result;
67609
}
67610
simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
67611
  bool is_null_value;
67612
  SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
67613
  if(is_null_value) { advance_non_root_scalar("null"); }
67614
  return is_null_value;
67615
}
67616
simdjson_inline bool value_iterator::is_negative() noexcept {
67617
  return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
67618
}
67619
simdjson_inline bool value_iterator::is_root_negative() noexcept {
67620
  return numberparsing::is_negative(peek_root_scalar("numbersign"));
67621
}
67622
simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
67623
  return numberparsing::is_integer(peek_non_root_scalar("integer"));
67624
}
67625
simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
67626
  return numberparsing::get_number_type(peek_non_root_scalar("integer"));
67627
}
67628
simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
67629
  number num;
67630
  error_code error =  numberparsing::parse_number(peek_non_root_scalar("number"), num);
67631
  if(error) { return error; }
67632
  return num;
67633
}
67634
67635
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
67636
  auto max_len = peek_root_length();
67637
  auto json = peek_root_scalar("is_root_integer");
67638
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
67639
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
67640
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
67641
    return false; // if there are more than 20 characters, it cannot be represented as an integer.
67642
  }
67643
  auto answer = numberparsing::is_integer(tmpbuf);
67644
  // If the parsing was a success, we must still check that it is
67645
  // a single scalar. Note that we parse first because of cases like '[]' where
67646
  // getting TRAILING_CONTENT is wrong.
67647
  if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
67648
  return answer;
67649
}
67650
67651
simdjson_inline simdjson_result<icelake::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
67652
  auto max_len = peek_root_length();
67653
  auto json = peek_root_scalar("number");
67654
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
67655
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
67656
  // number: -0.<fraction>e-308.
67657
  uint8_t tmpbuf[1074+8+1+1];
67658
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
67659
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
67660
    if(numberparsing::check_if_integer(json, max_len)) {
67661
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67662
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
67663
      return number_type::big_integer;
67664
    }
67665
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
67666
    return NUMBER_ERROR;
67667
  }
67668
  auto answer = numberparsing::get_number_type(tmpbuf);
67669
  if (check_trailing && (answer.error() == SUCCESS)  && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67670
  return answer;
67671
}
67672
simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
67673
  auto max_len = peek_root_length();
67674
  auto json = peek_root_scalar("number");
67675
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
67676
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
67677
  // number: -0.<fraction>e-308.
67678
  // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
67679
  uint8_t tmpbuf[1074+8+1+1];
67680
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
67681
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
67682
    if(numberparsing::check_if_integer(json, max_len)) {
67683
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67684
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
67685
      return BIGINT_ERROR;
67686
    }
67687
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
67688
    return NUMBER_ERROR;
67689
  }
67690
  number num;
67691
  error_code error =  numberparsing::parse_number(tmpbuf, num);
67692
  if(error) { return error; }
67693
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67694
  advance_root_scalar("number");
67695
  return num;
67696
}
67697
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
67698
  return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
67699
}
67700
template <typename string_type>
67701
simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
67702
  std::string_view content;
67703
  auto err = get_root_string(check_trailing, allow_replacement).get(content);
67704
  if (err) { return err; }
67705
  receiver = content;
67706
  return SUCCESS;
67707
}
67708
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
67709
  return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
67710
}
67711
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
67712
  auto json = peek_scalar("string");
67713
  if (*json != '"') { return incorrect_type_error("Not a string"); }
67714
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67715
  advance_scalar("string");
67716
  return raw_json_string(json+1);
67717
}
67718
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
67719
  auto max_len = peek_root_length();
67720
  auto json = peek_root_scalar("uint64");
67721
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
67722
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
67723
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
67724
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
67725
    return NUMBER_ERROR;
67726
  }
67727
  auto result = numberparsing::parse_unsigned(tmpbuf);
67728
  if(result.error() == SUCCESS) {
67729
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67730
    advance_root_scalar("uint64");
67731
  }
67732
  return result;
67733
}
67734
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
67735
  auto max_len = peek_root_length();
67736
  auto json = peek_root_scalar("uint64");
67737
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
67738
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
67739
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
67740
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
67741
    return NUMBER_ERROR;
67742
  }
67743
  auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
67744
  if(result.error() == SUCCESS) {
67745
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67746
    advance_root_scalar("uint64");
67747
  }
67748
  return result;
67749
}
67750
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
67751
  auto max_len = peek_root_length();
67752
  auto json = peek_root_scalar("int64");
67753
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
67754
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
67755
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
67756
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
67757
    return NUMBER_ERROR;
67758
  }
67759
67760
  auto result = numberparsing::parse_integer(tmpbuf);
67761
  if(result.error() == SUCCESS) {
67762
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67763
    advance_root_scalar("int64");
67764
  }
67765
  return result;
67766
}
67767
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
67768
  auto max_len = peek_root_length();
67769
  auto json = peek_root_scalar("int64");
67770
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
67771
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
67772
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
67773
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
67774
    return NUMBER_ERROR;
67775
  }
67776
67777
  auto result = numberparsing::parse_integer_in_string(tmpbuf);
67778
  if(result.error() == SUCCESS) {
67779
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67780
    advance_root_scalar("int64");
67781
  }
67782
  return result;
67783
}
67784
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
67785
  auto max_len = peek_root_length();
67786
  auto json = peek_root_scalar("double");
67787
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
67788
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
67789
  // number: -0.<fraction>e-308.
67790
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
67791
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
67792
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
67793
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
67794
    return NUMBER_ERROR;
67795
  }
67796
  auto result = numberparsing::parse_double(tmpbuf);
67797
  if(result.error() == SUCCESS) {
67798
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67799
    advance_root_scalar("double");
67800
  }
67801
  return result;
67802
}
67803
67804
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
67805
  auto max_len = peek_root_length();
67806
  auto json = peek_root_scalar("double");
67807
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
67808
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
67809
  // number: -0.<fraction>e-308.
67810
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
67811
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
67812
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
67813
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
67814
    return NUMBER_ERROR;
67815
  }
67816
  auto result = numberparsing::parse_double_in_string(tmpbuf);
67817
  if(result.error() == SUCCESS) {
67818
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67819
    advance_root_scalar("double");
67820
  }
67821
  return result;
67822
}
67823
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
67824
  auto max_len = peek_root_length();
67825
  auto json = peek_root_scalar("bool");
67826
  uint8_t tmpbuf[5+1+1]; // +1 for null termination
67827
  tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
67828
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
67829
  auto result = parse_bool(tmpbuf);
67830
  if(result.error() == SUCCESS) {
67831
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67832
    advance_root_scalar("bool");
67833
  }
67834
  return result;
67835
}
67836
simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
67837
  auto max_len = peek_root_length();
67838
  auto json = peek_root_scalar("null");
67839
  bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
67840
         (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
67841
  if(result) { // we have something that looks like a null.
67842
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
67843
    advance_root_scalar("null");
67844
  }
67845
  return result;
67846
}
67847
67848
simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
67849
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
67850
  SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
67851
67852
  return _json_iter->skip_child(depth());
67853
}
67854
67855
simdjson_inline value_iterator value_iterator::child() const noexcept {
67856
  assert_at_child();
67857
  return { _json_iter, depth()+1, _json_iter->token.position() };
67858
}
67859
67860
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
67861
// relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
67862
// marked non-inline.
67863
SIMDJSON_PUSH_DISABLE_WARNINGS
67864
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
67865
simdjson_inline bool value_iterator::is_open() const noexcept {
67866
  return _json_iter->depth() >= depth();
67867
}
67868
SIMDJSON_POP_DISABLE_WARNINGS
67869
67870
simdjson_inline bool value_iterator::at_end() const noexcept {
67871
  return _json_iter->at_end();
67872
}
67873
67874
simdjson_inline bool value_iterator::at_start() const noexcept {
67875
  return _json_iter->token.position() == start_position();
67876
}
67877
67878
simdjson_inline bool value_iterator::at_first_field() const noexcept {
67879
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
67880
  return _json_iter->token.position() == start_position() + 1;
67881
}
67882
67883
simdjson_inline void value_iterator::abandon() noexcept {
67884
  _json_iter->abandon();
67885
}
67886
67887
simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
67888
  return _depth;
67889
}
67890
simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
67891
  return _json_iter->error;
67892
}
67893
simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
67894
  return _json_iter->string_buf_loc();
67895
}
67896
simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
67897
  return *_json_iter;
67898
}
67899
simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
67900
  return *_json_iter;
67901
}
67902
67903
simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
67904
  return _json_iter->peek(start_position());
67905
}
67906
simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
67907
  return _json_iter->peek_length(start_position());
67908
}
67909
simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
67910
  return _json_iter->peek_root_length(start_position());
67911
}
67912
67913
simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
67914
  logger::log_value(*_json_iter, start_position(), depth(), type);
67915
  // If we're not at the position anymore, we don't want to advance the cursor.
67916
  if (!is_at_start()) { return peek_start(); }
67917
67918
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
67919
  assert_at_start();
67920
  return _json_iter->peek();
67921
}
67922
67923
simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
67924
  logger::log_value(*_json_iter, start_position(), depth(), type);
67925
  // If we're not at the position anymore, we don't want to advance the cursor.
67926
  if (!is_at_start()) { return; }
67927
67928
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
67929
  assert_at_start();
67930
  _json_iter->return_current_and_advance();
67931
  _json_iter->ascend_to(depth()-1);
67932
}
67933
67934
simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
67935
  logger::log_start_value(*_json_iter, start_position(), depth(), type);
67936
  // If we're not at the position anymore, we don't want to advance the cursor.
67937
  const uint8_t *json;
67938
  if (!is_at_start()) {
67939
#if SIMDJSON_DEVELOPMENT_CHECKS
67940
    if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
67941
#endif
67942
    json = peek_start();
67943
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
67944
  } else {
67945
    assert_at_start();
67946
    /**
67947
     * We should be prudent. Let us peek. If it is not the right type, we
67948
     * return an error. Only once we have determined that we have the right
67949
     * type are we allowed to advance!
67950
     */
67951
    json = _json_iter->peek();
67952
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
67953
    _json_iter->return_current_and_advance();
67954
  }
67955
67956
67957
  return SUCCESS;
67958
}
67959
67960
67961
simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
67962
  logger::log_value(*_json_iter, start_position(), depth(), type);
67963
  if (!is_at_start()) { return peek_start(); }
67964
67965
  assert_at_root();
67966
  return _json_iter->peek();
67967
}
67968
simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
67969
  logger::log_value(*_json_iter, start_position(), depth(), type);
67970
  if (!is_at_start()) { return peek_start(); }
67971
67972
  assert_at_non_root_start();
67973
  return _json_iter->peek();
67974
}
67975
67976
simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
67977
  logger::log_value(*_json_iter, start_position(), depth(), type);
67978
  if (!is_at_start()) { return; }
67979
67980
  assert_at_root();
67981
  _json_iter->return_current_and_advance();
67982
  _json_iter->ascend_to(depth()-1);
67983
}
67984
simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
67985
  logger::log_value(*_json_iter, start_position(), depth(), type);
67986
  if (!is_at_start()) { return; }
67987
67988
  assert_at_non_root_start();
67989
  _json_iter->return_current_and_advance();
67990
  _json_iter->ascend_to(depth()-1);
67991
}
67992
67993
simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
67994
  logger::log_error(*_json_iter, start_position(), depth(), message);
67995
  return INCORRECT_TYPE;
67996
}
67997
67998
simdjson_inline bool value_iterator::is_at_start() const noexcept {
67999
  return position() == start_position();
68000
}
68001
68002
simdjson_inline bool value_iterator::is_at_key() const noexcept {
68003
  // Keys are at the same depth as the object.
68004
  // Note here that we could be safer and check that we are within an object,
68005
  // but we do not.
68006
  return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
68007
}
68008
68009
simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
68010
  // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
68011
  auto delta = position() - start_position();
68012
  return delta == 1 || delta == 2;
68013
}
68014
68015
inline void value_iterator::assert_at_start() const noexcept {
68016
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
68017
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
68018
  SIMDJSON_ASSUME( _depth > 0 );
68019
}
68020
68021
inline void value_iterator::assert_at_container_start() const noexcept {
68022
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
68023
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
68024
  SIMDJSON_ASSUME( _depth > 0 );
68025
}
68026
68027
inline void value_iterator::assert_at_next() const noexcept {
68028
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
68029
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
68030
  SIMDJSON_ASSUME( _depth > 0 );
68031
}
68032
68033
simdjson_inline void value_iterator::move_at_start() noexcept {
68034
  _json_iter->_depth = _depth;
68035
  _json_iter->token.set_position(_start_position);
68036
}
68037
68038
simdjson_inline void value_iterator::move_at_container_start() noexcept {
68039
  _json_iter->_depth = _depth;
68040
  _json_iter->token.set_position(_start_position + 1);
68041
}
68042
68043
simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
68044
  if(error()) { return error(); }
68045
  move_at_container_start();
68046
  return started_array();
68047
}
68048
68049
simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
68050
  if(error()) { return error(); }
68051
  move_at_container_start();
68052
  return started_object();
68053
}
68054
68055
inline void value_iterator::assert_at_child() const noexcept {
68056
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
68057
  SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
68058
  SIMDJSON_ASSUME( _depth > 0 );
68059
}
68060
68061
inline void value_iterator::assert_at_root() const noexcept {
68062
  assert_at_start();
68063
  SIMDJSON_ASSUME( _depth == 1 );
68064
}
68065
68066
inline void value_iterator::assert_at_non_root_start() const noexcept {
68067
  assert_at_start();
68068
  SIMDJSON_ASSUME( _depth > 1 );
68069
}
68070
68071
inline void value_iterator::assert_is_valid() const noexcept {
68072
  SIMDJSON_ASSUME( _json_iter != nullptr );
68073
}
68074
68075
simdjson_inline bool value_iterator::is_valid() const noexcept {
68076
  return _json_iter != nullptr;
68077
}
68078
68079
simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
68080
  switch (*peek_start()) {
68081
    case '{':
68082
      return json_type::object;
68083
    case '[':
68084
      return json_type::array;
68085
    case '"':
68086
      return json_type::string;
68087
    case 'n':
68088
      return json_type::null;
68089
    case 't': case 'f':
68090
      return json_type::boolean;
68091
    case '-':
68092
    case '0': case '1': case '2': case '3': case '4':
68093
    case '5': case '6': case '7': case '8': case '9':
68094
      return json_type::number;
68095
    default:
68096
      return TAPE_ERROR;
68097
  }
68098
}
68099
68100
simdjson_inline token_position value_iterator::start_position() const noexcept {
68101
  return _start_position;
68102
}
68103
68104
simdjson_inline token_position value_iterator::position() const noexcept {
68105
  return _json_iter->position();
68106
}
68107
68108
simdjson_inline token_position value_iterator::end_position() const noexcept {
68109
  return _json_iter->end_position();
68110
}
68111
68112
simdjson_inline token_position value_iterator::last_position() const noexcept {
68113
  return _json_iter->last_position();
68114
}
68115
68116
simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
68117
  return _json_iter->report_error(error, message);
68118
}
68119
68120
} // namespace ondemand
68121
} // namespace icelake
68122
} // namespace simdjson
68123
68124
namespace simdjson {
68125
68126
simdjson_inline simdjson_result<icelake::ondemand::value_iterator>::simdjson_result(icelake::ondemand::value_iterator &&value) noexcept
68127
    : implementation_simdjson_result_base<icelake::ondemand::value_iterator>(std::forward<icelake::ondemand::value_iterator>(value)) {}
68128
simdjson_inline simdjson_result<icelake::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
68129
    : implementation_simdjson_result_base<icelake::ondemand::value_iterator>(error) {}
68130
68131
} // namespace simdjson
68132
68133
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
68134
/* end file simdjson/generic/ondemand/value_iterator-inl.h for icelake */
68135
/* end file simdjson/generic/ondemand/amalgamated.h for icelake */
68136
/* including simdjson/icelake/end.h: #include "simdjson/icelake/end.h" */
68137
/* begin file simdjson/icelake/end.h */
68138
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68139
/* amalgamation skipped (editor-only): #include "simdjson/icelake/base.h" */
68140
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68141
68142
#if !SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
68143
SIMDJSON_UNTARGET_REGION
68144
#endif
68145
68146
/* undefining SIMDJSON_IMPLEMENTATION from "icelake" */
68147
#undef SIMDJSON_IMPLEMENTATION
68148
/* end file simdjson/icelake/end.h */
68149
68150
#endif // SIMDJSON_ICELAKE_ONDEMAND_H
68151
/* end file simdjson/icelake/ondemand.h */
68152
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
68153
/* including simdjson/ppc64/ondemand.h: #include "simdjson/ppc64/ondemand.h" */
68154
/* begin file simdjson/ppc64/ondemand.h */
68155
#ifndef SIMDJSON_PPC64_ONDEMAND_H
68156
#define SIMDJSON_PPC64_ONDEMAND_H
68157
68158
/* including simdjson/ppc64/begin.h: #include "simdjson/ppc64/begin.h" */
68159
/* begin file simdjson/ppc64/begin.h */
68160
/* defining SIMDJSON_IMPLEMENTATION to "ppc64" */
68161
#define SIMDJSON_IMPLEMENTATION ppc64
68162
/* including simdjson/ppc64/base.h: #include "simdjson/ppc64/base.h" */
68163
/* begin file simdjson/ppc64/base.h */
68164
#ifndef SIMDJSON_PPC64_BASE_H
68165
#define SIMDJSON_PPC64_BASE_H
68166
68167
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68168
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
68169
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68170
68171
namespace simdjson {
68172
/**
68173
 * Implementation for ALTIVEC (PPC64).
68174
 */
68175
namespace ppc64 {
68176
68177
class implementation;
68178
68179
namespace {
68180
namespace simd {
68181
template <typename T> struct simd8;
68182
template <typename T> struct simd8x64;
68183
} // namespace simd
68184
} // unnamed namespace
68185
68186
} // namespace ppc64
68187
} // namespace simdjson
68188
68189
#endif // SIMDJSON_PPC64_BASE_H
68190
/* end file simdjson/ppc64/base.h */
68191
/* including simdjson/ppc64/intrinsics.h: #include "simdjson/ppc64/intrinsics.h" */
68192
/* begin file simdjson/ppc64/intrinsics.h */
68193
#ifndef SIMDJSON_PPC64_INTRINSICS_H
68194
#define SIMDJSON_PPC64_INTRINSICS_H
68195
68196
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68197
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
68198
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68199
68200
// This should be the correct header whether
68201
// you use visual studio or other compilers.
68202
#include <altivec.h>
68203
68204
// These are defined by altivec.h in GCC toolchain, it is safe to undef them.
68205
#ifdef bool
68206
#undef bool
68207
#endif
68208
68209
#ifdef vector
68210
#undef vector
68211
#endif
68212
68213
static_assert(sizeof(__vector unsigned char) <= simdjson::SIMDJSON_PADDING, "insufficient padding for ppc64");
68214
68215
#endif //  SIMDJSON_PPC64_INTRINSICS_H
68216
/* end file simdjson/ppc64/intrinsics.h */
68217
/* including simdjson/ppc64/bitmanipulation.h: #include "simdjson/ppc64/bitmanipulation.h" */
68218
/* begin file simdjson/ppc64/bitmanipulation.h */
68219
#ifndef SIMDJSON_PPC64_BITMANIPULATION_H
68220
#define SIMDJSON_PPC64_BITMANIPULATION_H
68221
68222
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68223
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
68224
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68225
68226
namespace simdjson {
68227
namespace ppc64 {
68228
namespace {
68229
68230
// We sometimes call trailing_zero on inputs that are zero,
68231
// but the algorithms do not end up using the returned value.
68232
// Sadly, sanitizers are not smart enough to figure it out.
68233
SIMDJSON_NO_SANITIZE_UNDEFINED
68234
// This function can be used safely even if not all bytes have been
68235
// initialized.
68236
// See issue https://github.com/simdjson/simdjson/issues/1965
68237
SIMDJSON_NO_SANITIZE_MEMORY
68238
simdjson_inline int trailing_zeroes(uint64_t input_num) {
68239
#if SIMDJSON_REGULAR_VISUAL_STUDIO
68240
  unsigned long ret;
68241
  // Search the mask data from least significant bit (LSB)
68242
  // to the most significant bit (MSB) for a set bit (1).
68243
  _BitScanForward64(&ret, input_num);
68244
  return (int)ret;
68245
#else  // SIMDJSON_REGULAR_VISUAL_STUDIO
68246
  return __builtin_ctzll(input_num);
68247
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
68248
}
68249
68250
/* result might be undefined when input_num is zero */
68251
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
68252
  return input_num & (input_num - 1);
68253
}
68254
68255
/* result might be undefined when input_num is zero */
68256
simdjson_inline int leading_zeroes(uint64_t input_num) {
68257
#if SIMDJSON_REGULAR_VISUAL_STUDIO
68258
  unsigned long leading_zero = 0;
68259
  // Search the mask data from most significant bit (MSB)
68260
  // to least significant bit (LSB) for a set bit (1).
68261
  if (_BitScanReverse64(&leading_zero, input_num))
68262
    return (int)(63 - leading_zero);
68263
  else
68264
    return 64;
68265
#else
68266
  return __builtin_clzll(input_num);
68267
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
68268
}
68269
68270
#if SIMDJSON_REGULAR_VISUAL_STUDIO
68271
simdjson_inline int count_ones(uint64_t input_num) {
68272
  // note: we do not support legacy 32-bit Windows in this kernel
68273
  return __popcnt64(input_num); // Visual Studio wants two underscores
68274
}
68275
#else
68276
simdjson_inline int count_ones(uint64_t input_num) {
68277
  return __builtin_popcountll(input_num);
68278
}
68279
#endif
68280
68281
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
68282
                                         uint64_t *result) {
68283
#if SIMDJSON_REGULAR_VISUAL_STUDIO
68284
  *result = value1 + value2;
68285
  return *result < value1;
68286
#else
68287
  return __builtin_uaddll_overflow(value1, value2,
68288
                                   reinterpret_cast<unsigned long long *>(result));
68289
#endif
68290
}
68291
68292
} // unnamed namespace
68293
} // namespace ppc64
68294
} // namespace simdjson
68295
68296
#endif // SIMDJSON_PPC64_BITMANIPULATION_H
68297
/* end file simdjson/ppc64/bitmanipulation.h */
68298
/* including simdjson/ppc64/bitmask.h: #include "simdjson/ppc64/bitmask.h" */
68299
/* begin file simdjson/ppc64/bitmask.h */
68300
#ifndef SIMDJSON_PPC64_BITMASK_H
68301
#define SIMDJSON_PPC64_BITMASK_H
68302
68303
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68304
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
68305
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68306
68307
namespace simdjson {
68308
namespace ppc64 {
68309
namespace {
68310
68311
//
68312
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is
68313
// encountered.
68314
//
68315
// For example, prefix_xor(00100100) == 00011100
68316
//
68317
simdjson_inline uint64_t prefix_xor(uint64_t bitmask) {
68318
  // You can use the version below, however gcc sometimes miscompiles
68319
  // vec_pmsum_be, it happens somewhere around between 8 and 9th version.
68320
  // The performance boost was not noticeable, falling back to a usual
68321
  // implementation.
68322
  //   __vector unsigned long long all_ones = {~0ull, ~0ull};
68323
  //   __vector unsigned long long mask = {bitmask, 0};
68324
  //   // Clang and GCC return different values for pmsum for ull so cast it to one.
68325
  //   // Generally it is not specified by ALTIVEC ISA what is returned by
68326
  //   // vec_pmsum_be.
68327
  // #if defined(__LITTLE_ENDIAN__)
68328
  //   return (uint64_t)(((__vector unsigned long long)vec_pmsum_be(all_ones, mask))[0]);
68329
  // #else
68330
  //   return (uint64_t)(((__vector unsigned long long)vec_pmsum_be(all_ones, mask))[1]);
68331
  // #endif
68332
  bitmask ^= bitmask << 1;
68333
  bitmask ^= bitmask << 2;
68334
  bitmask ^= bitmask << 4;
68335
  bitmask ^= bitmask << 8;
68336
  bitmask ^= bitmask << 16;
68337
  bitmask ^= bitmask << 32;
68338
  return bitmask;
68339
}
68340
68341
} // unnamed namespace
68342
} // namespace ppc64
68343
} // namespace simdjson
68344
68345
#endif
68346
/* end file simdjson/ppc64/bitmask.h */
68347
/* including simdjson/ppc64/numberparsing_defs.h: #include "simdjson/ppc64/numberparsing_defs.h" */
68348
/* begin file simdjson/ppc64/numberparsing_defs.h */
68349
#ifndef SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
68350
#define SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
68351
68352
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68353
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
68354
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/intrinsics.h" */
68355
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
68356
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68357
68358
#include <cstring>
68359
68360
#if defined(__linux__)
68361
#include <byteswap.h>
68362
#elif defined(__FreeBSD__)
68363
#include <sys/endian.h>
68364
#endif
68365
68366
namespace simdjson {
68367
namespace ppc64 {
68368
namespace numberparsing {
68369
68370
// we don't have appropriate instructions, so let us use a scalar function
68371
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
68372
/** @private */
68373
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
68374
  uint64_t val;
68375
  std::memcpy(&val, chars, sizeof(uint64_t));
68376
#ifdef __BIG_ENDIAN__
68377
#if defined(__linux__)
68378
  val = bswap_64(val);
68379
#elif defined(__FreeBSD__)
68380
  val = bswap64(val);
68381
#endif
68382
#endif
68383
  val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
68384
  val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
68385
  return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
68386
}
68387
68388
/** @private */
68389
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
68390
  internal::value128 answer;
68391
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
68392
#ifdef _M_ARM64
68393
  // ARM64 has native support for 64-bit multiplications, no need to emultate
68394
  answer.high = __umulh(value1, value2);
68395
  answer.low = value1 * value2;
68396
#else
68397
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
68398
#endif // _M_ARM64
68399
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
68400
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
68401
  answer.low = uint64_t(r);
68402
  answer.high = uint64_t(r >> 64);
68403
#endif
68404
  return answer;
68405
}
68406
68407
} // namespace numberparsing
68408
} // namespace ppc64
68409
} // namespace simdjson
68410
68411
#define SIMDJSON_SWAR_NUMBER_PARSING 1
68412
68413
#endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
68414
/* end file simdjson/ppc64/numberparsing_defs.h */
68415
/* including simdjson/ppc64/simd.h: #include "simdjson/ppc64/simd.h" */
68416
/* begin file simdjson/ppc64/simd.h */
68417
#ifndef SIMDJSON_PPC64_SIMD_H
68418
#define SIMDJSON_PPC64_SIMD_H
68419
68420
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68421
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
68422
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/bitmanipulation.h" */
68423
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
68424
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68425
68426
#include <type_traits>
68427
68428
namespace simdjson {
68429
namespace ppc64 {
68430
namespace {
68431
namespace simd {
68432
68433
using __m128i = __vector unsigned char;
68434
68435
template <typename Child> struct base {
68436
  __m128i value;
68437
68438
  // Zero constructor
68439
  simdjson_inline base() : value{__m128i()} {}
68440
68441
  // Conversion from SIMD register
68442
  simdjson_inline base(const __m128i _value) : value(_value) {}
68443
68444
  // Conversion to SIMD register
68445
  simdjson_inline operator const __m128i &() const {
68446
    return this->value;
68447
  }
68448
  simdjson_inline operator __m128i &() { return this->value; }
68449
68450
  // Bit operations
68451
  simdjson_inline Child operator|(const Child other) const {
68452
    return vec_or(this->value, (__m128i)other);
68453
  }
68454
  simdjson_inline Child operator&(const Child other) const {
68455
    return vec_and(this->value, (__m128i)other);
68456
  }
68457
  simdjson_inline Child operator^(const Child other) const {
68458
    return vec_xor(this->value, (__m128i)other);
68459
  }
68460
  simdjson_inline Child bit_andnot(const Child other) const {
68461
    return vec_andc(this->value, (__m128i)other);
68462
  }
68463
  simdjson_inline Child &operator|=(const Child other) {
68464
    auto this_cast = static_cast<Child*>(this);
68465
    *this_cast = *this_cast | other;
68466
    return *this_cast;
68467
  }
68468
  simdjson_inline Child &operator&=(const Child other) {
68469
    auto this_cast = static_cast<Child*>(this);
68470
    *this_cast = *this_cast & other;
68471
    return *this_cast;
68472
  }
68473
  simdjson_inline Child &operator^=(const Child other) {
68474
    auto this_cast = static_cast<Child*>(this);
68475
    *this_cast = *this_cast ^ other;
68476
    return *this_cast;
68477
  }
68478
};
68479
68480
template <typename T, typename Mask = simd8<bool>>
68481
struct base8 : base<simd8<T>> {
68482
  typedef uint16_t bitmask_t;
68483
  typedef uint32_t bitmask2_t;
68484
68485
  simdjson_inline base8() : base<simd8<T>>() {}
68486
  simdjson_inline base8(const __m128i _value) : base<simd8<T>>(_value) {}
68487
68488
  friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) {
68489
    return (__m128i)vec_cmpeq(lhs.value, (__m128i)rhs);
68490
  }
68491
68492
  static const int SIZE = sizeof(base<simd8<T>>::value);
68493
68494
  template <int N = 1>
68495
  simdjson_inline simd8<T> prev(simd8<T> prev_chunk) const {
68496
    __m128i chunk = this->value;
68497
#ifdef __LITTLE_ENDIAN__
68498
    chunk = (__m128i)vec_reve(this->value);
68499
    prev_chunk = (__m128i)vec_reve((__m128i)prev_chunk);
68500
#endif
68501
    chunk = (__m128i)vec_sld((__m128i)prev_chunk, (__m128i)chunk, 16 - N);
68502
#ifdef __LITTLE_ENDIAN__
68503
    chunk = (__m128i)vec_reve((__m128i)chunk);
68504
#endif
68505
    return chunk;
68506
  }
68507
};
68508
68509
// SIMD byte mask type (returned by things like eq and gt)
68510
template <> struct simd8<bool> : base8<bool> {
68511
  static simdjson_inline simd8<bool> splat(bool _value) {
68512
    return (__m128i)vec_splats((unsigned char)(-(!!_value)));
68513
  }
68514
68515
  simdjson_inline simd8<bool>() : base8<bool>() {}
68516
  simdjson_inline simd8<bool>(const __m128i _value)
68517
      : base8<bool>(_value) {}
68518
  // Splat constructor
68519
  simdjson_inline simd8<bool>(bool _value)
68520
      : base8<bool>(splat(_value)) {}
68521
68522
  simdjson_inline int to_bitmask() const {
68523
    __vector unsigned long long result;
68524
    const __m128i perm_mask = {0x78, 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40,
68525
                               0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x00};
68526
68527
    result = ((__vector unsigned long long)vec_vbpermq((__m128i)this->value,
68528
                                                       (__m128i)perm_mask));
68529
#ifdef __LITTLE_ENDIAN__
68530
    return static_cast<int>(result[1]);
68531
#else
68532
    return static_cast<int>(result[0]);
68533
#endif
68534
  }
68535
  simdjson_inline bool any() const {
68536
    return !vec_all_eq(this->value, (__m128i)vec_splats(0));
68537
  }
68538
  simdjson_inline simd8<bool> operator~() const {
68539
    return this->value ^ (__m128i)splat(true);
68540
  }
68541
};
68542
68543
template <typename T> struct base8_numeric : base8<T> {
68544
  static simdjson_inline simd8<T> splat(T value) {
68545
    (void)value;
68546
    return (__m128i)vec_splats(value);
68547
  }
68548
  static simdjson_inline simd8<T> zero() { return splat(0); }
68549
  static simdjson_inline simd8<T> load(const T values[16]) {
68550
    return (__m128i)(vec_vsx_ld(0, reinterpret_cast<const uint8_t *>(values)));
68551
  }
68552
  // Repeat 16 values as many times as necessary (usually for lookup tables)
68553
  static simdjson_inline simd8<T> repeat_16(T v0, T v1, T v2, T v3, T v4,
68554
                                                   T v5, T v6, T v7, T v8, T v9,
68555
                                                   T v10, T v11, T v12, T v13,
68556
                                                   T v14, T v15) {
68557
    return simd8<T>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
68558
                    v14, v15);
68559
  }
68560
68561
  simdjson_inline base8_numeric() : base8<T>() {}
68562
  simdjson_inline base8_numeric(const __m128i _value)
68563
      : base8<T>(_value) {}
68564
68565
  // Store to array
68566
  simdjson_inline void store(T dst[16]) const {
68567
    vec_vsx_st(this->value, 0, reinterpret_cast<__m128i *>(dst));
68568
  }
68569
68570
  // Override to distinguish from bool version
68571
  simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
68572
68573
  // Addition/subtraction are the same for signed and unsigned
68574
  simdjson_inline simd8<T> operator+(const simd8<T> other) const {
68575
    return (__m128i)((__m128i)this->value + (__m128i)other);
68576
  }
68577
  simdjson_inline simd8<T> operator-(const simd8<T> other) const {
68578
    return (__m128i)((__m128i)this->value - (__m128i)other);
68579
  }
68580
  simdjson_inline simd8<T> &operator+=(const simd8<T> other) {
68581
    *this = *this + other;
68582
    return *static_cast<simd8<T> *>(this);
68583
  }
68584
  simdjson_inline simd8<T> &operator-=(const simd8<T> other) {
68585
    *this = *this - other;
68586
    return *static_cast<simd8<T> *>(this);
68587
  }
68588
68589
  // Perform a lookup assuming the value is between 0 and 16 (undefined behavior
68590
  // for out of range values)
68591
  template <typename L>
68592
  simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
68593
    return (__m128i)vec_perm((__m128i)lookup_table, (__m128i)lookup_table, this->value);
68594
  }
68595
68596
  // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted
68597
  // as a bitset). Passing a 0 value for mask would be equivalent to writing out
68598
  // every byte to output. Only the first 16 - count_ones(mask) bytes of the
68599
  // result are significant but 16 bytes get written. Design consideration: it
68600
  // seems like a function with the signature simd8<L> compress(uint32_t mask)
68601
  // would be sensible, but the AVX ISA makes this kind of approach difficult.
68602
  template <typename L>
68603
  simdjson_inline void compress(uint16_t mask, L *output) const {
68604
    using internal::BitsSetTable256mul2;
68605
    using internal::pshufb_combine_table;
68606
    using internal::thintable_epi8;
68607
    // this particular implementation was inspired by work done by @animetosho
68608
    // we do it in two steps, first 8 bytes and then second 8 bytes
68609
    uint8_t mask1 = uint8_t(mask);      // least significant 8 bits
68610
    uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
68611
    // next line just loads the 64-bit values thintable_epi8[mask1] and
68612
    // thintable_epi8[mask2] into a 128-bit register, using only
68613
    // two instructions on most compilers.
68614
#ifdef __LITTLE_ENDIAN__
68615
    __m128i shufmask = (__m128i)(__vector unsigned long long){
68616
        thintable_epi8[mask1], thintable_epi8[mask2]};
68617
#else
68618
    __m128i shufmask = (__m128i)(__vector unsigned long long){
68619
        thintable_epi8[mask2], thintable_epi8[mask1]};
68620
    shufmask = (__m128i)vec_reve((__m128i)shufmask);
68621
#endif
68622
    // we increment by 0x08 the second half of the mask
68623
    shufmask = ((__m128i)shufmask) +
68624
               ((__m128i)(__vector int){0, 0, 0x08080808, 0x08080808});
68625
68626
    // this is the version "nearly pruned"
68627
    __m128i pruned = vec_perm(this->value, this->value, shufmask);
68628
    // we still need to put the two halves together.
68629
    // we compute the popcount of the first half:
68630
    int pop1 = BitsSetTable256mul2[mask1];
68631
    // then load the corresponding mask, what it does is to write
68632
    // only the first pop1 bytes from the first 8 bytes, and then
68633
    // it fills in with the bytes from the second 8 bytes + some filling
68634
    // at the end.
68635
    __m128i compactmask =
68636
        vec_vsx_ld(0, reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
68637
    __m128i answer = vec_perm(pruned, (__m128i)vec_splats(0), compactmask);
68638
    vec_vsx_st(answer, 0, reinterpret_cast<__m128i *>(output));
68639
  }
68640
68641
  template <typename L>
68642
  simdjson_inline simd8<L>
68643
  lookup_16(L replace0, L replace1, L replace2, L replace3, L replace4,
68644
            L replace5, L replace6, L replace7, L replace8, L replace9,
68645
            L replace10, L replace11, L replace12, L replace13, L replace14,
68646
            L replace15) const {
68647
    return lookup_16(simd8<L>::repeat_16(
68648
        replace0, replace1, replace2, replace3, replace4, replace5, replace6,
68649
        replace7, replace8, replace9, replace10, replace11, replace12,
68650
        replace13, replace14, replace15));
68651
  }
68652
};
68653
68654
// Signed bytes
68655
template <> struct simd8<int8_t> : base8_numeric<int8_t> {
68656
  simdjson_inline simd8() : base8_numeric<int8_t>() {}
68657
  simdjson_inline simd8(const __m128i _value)
68658
      : base8_numeric<int8_t>(_value) {}
68659
  // Splat constructor
68660
  simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
68661
  // Array constructor
68662
  simdjson_inline simd8(const int8_t *values) : simd8(load(values)) {}
68663
  // Member-by-member initialization
68664
  simdjson_inline simd8(int8_t v0, int8_t v1, int8_t v2, int8_t v3,
68665
                               int8_t v4, int8_t v5, int8_t v6, int8_t v7,
68666
                               int8_t v8, int8_t v9, int8_t v10, int8_t v11,
68667
                               int8_t v12, int8_t v13, int8_t v14, int8_t v15)
68668
      : simd8((__m128i)(__vector signed char){v0, v1, v2, v3, v4, v5, v6, v7,
68669
                                              v8, v9, v10, v11, v12, v13, v14,
68670
                                              v15}) {}
68671
  // Repeat 16 values as many times as necessary (usually for lookup tables)
68672
  simdjson_inline static simd8<int8_t>
68673
  repeat_16(int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5,
68674
            int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11,
68675
            int8_t v12, int8_t v13, int8_t v14, int8_t v15) {
68676
    return simd8<int8_t>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
68677
                         v13, v14, v15);
68678
  }
68679
68680
  // Order-sensitive comparisons
68681
  simdjson_inline simd8<int8_t>
68682
  max_val(const simd8<int8_t> other) const {
68683
    return (__m128i)vec_max((__vector signed char)this->value,
68684
                            (__vector signed char)(__m128i)other);
68685
  }
68686
  simdjson_inline simd8<int8_t>
68687
  min_val(const simd8<int8_t> other) const {
68688
    return (__m128i)vec_min((__vector signed char)this->value,
68689
                            (__vector signed char)(__m128i)other);
68690
  }
68691
  simdjson_inline simd8<bool>
68692
  operator>(const simd8<int8_t> other) const {
68693
    return (__m128i)vec_cmpgt((__vector signed char)this->value,
68694
                              (__vector signed char)(__m128i)other);
68695
  }
68696
  simdjson_inline simd8<bool>
68697
  operator<(const simd8<int8_t> other) const {
68698
    return (__m128i)vec_cmplt((__vector signed char)this->value,
68699
                              (__vector signed char)(__m128i)other);
68700
  }
68701
};
68702
68703
// Unsigned bytes
68704
template <> struct simd8<uint8_t> : base8_numeric<uint8_t> {
68705
  simdjson_inline simd8() : base8_numeric<uint8_t>() {}
68706
  simdjson_inline simd8(const __m128i _value)
68707
      : base8_numeric<uint8_t>(_value) {}
68708
  // Splat constructor
68709
  simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
68710
  // Array constructor
68711
  simdjson_inline simd8(const uint8_t *values) : simd8(load(values)) {}
68712
  // Member-by-member initialization
68713
  simdjson_inline
68714
  simd8(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5,
68715
        uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10,
68716
        uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15)
68717
      : simd8((__m128i){v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
68718
                        v13, v14, v15}) {}
68719
  // Repeat 16 values as many times as necessary (usually for lookup tables)
68720
  simdjson_inline static simd8<uint8_t>
68721
  repeat_16(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4,
68722
            uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9,
68723
            uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14,
68724
            uint8_t v15) {
68725
    return simd8<uint8_t>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
68726
                          v13, v14, v15);
68727
  }
68728
68729
  // Saturated math
68730
  simdjson_inline simd8<uint8_t>
68731
  saturating_add(const simd8<uint8_t> other) const {
68732
    return (__m128i)vec_adds(this->value, (__m128i)other);
68733
  }
68734
  simdjson_inline simd8<uint8_t>
68735
  saturating_sub(const simd8<uint8_t> other) const {
68736
    return (__m128i)vec_subs(this->value, (__m128i)other);
68737
  }
68738
68739
  // Order-specific operations
68740
  simdjson_inline simd8<uint8_t>
68741
  max_val(const simd8<uint8_t> other) const {
68742
    return (__m128i)vec_max(this->value, (__m128i)other);
68743
  }
68744
  simdjson_inline simd8<uint8_t>
68745
  min_val(const simd8<uint8_t> other) const {
68746
    return (__m128i)vec_min(this->value, (__m128i)other);
68747
  }
68748
  // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
68749
  simdjson_inline simd8<uint8_t>
68750
  gt_bits(const simd8<uint8_t> other) const {
68751
    return this->saturating_sub(other);
68752
  }
68753
  // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
68754
  simdjson_inline simd8<uint8_t>
68755
  lt_bits(const simd8<uint8_t> other) const {
68756
    return other.saturating_sub(*this);
68757
  }
68758
  simdjson_inline simd8<bool>
68759
  operator<=(const simd8<uint8_t> other) const {
68760
    return other.max_val(*this) == other;
68761
  }
68762
  simdjson_inline simd8<bool>
68763
  operator>=(const simd8<uint8_t> other) const {
68764
    return other.min_val(*this) == other;
68765
  }
68766
  simdjson_inline simd8<bool>
68767
  operator>(const simd8<uint8_t> other) const {
68768
    return this->gt_bits(other).any_bits_set();
68769
  }
68770
  simdjson_inline simd8<bool>
68771
  operator<(const simd8<uint8_t> other) const {
68772
    return this->gt_bits(other).any_bits_set();
68773
  }
68774
68775
  // Bit-specific operations
68776
  simdjson_inline simd8<bool> bits_not_set() const {
68777
    return (__m128i)vec_cmpeq(this->value, (__m128i)vec_splats(uint8_t(0)));
68778
  }
68779
  simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const {
68780
    return (*this & bits).bits_not_set();
68781
  }
68782
  simdjson_inline simd8<bool> any_bits_set() const {
68783
    return ~this->bits_not_set();
68784
  }
68785
  simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const {
68786
    return ~this->bits_not_set(bits);
68787
  }
68788
  simdjson_inline bool bits_not_set_anywhere() const {
68789
    return vec_all_eq(this->value, (__m128i)vec_splats(0));
68790
  }
68791
  simdjson_inline bool any_bits_set_anywhere() const {
68792
    return !bits_not_set_anywhere();
68793
  }
68794
  simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const {
68795
    return vec_all_eq(vec_and(this->value, (__m128i)bits),
68796
                      (__m128i)vec_splats(0));
68797
  }
68798
  simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const {
68799
    return !bits_not_set_anywhere(bits);
68800
  }
68801
  template <int N> simdjson_inline simd8<uint8_t> shr() const {
68802
    return simd8<uint8_t>(
68803
        (__m128i)vec_sr(this->value, (__m128i)vec_splat_u8(N)));
68804
  }
68805
  template <int N> simdjson_inline simd8<uint8_t> shl() const {
68806
    return simd8<uint8_t>(
68807
        (__m128i)vec_sl(this->value, (__m128i)vec_splat_u8(N)));
68808
  }
68809
};
68810
68811
template <typename T> struct simd8x64 {
68812
  static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
68813
  static_assert(NUM_CHUNKS == 4,
68814
                "PPC64 kernel should use four registers per 64-byte block.");
68815
  const simd8<T> chunks[NUM_CHUNKS];
68816
68817
  simd8x64(const simd8x64<T> &o) = delete; // no copy allowed
68818
  simd8x64<T> &
68819
  operator=(const simd8<T>& other) = delete; // no assignment allowed
68820
  simd8x64() = delete;                      // no default constructor allowed
68821
68822
  simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1,
68823
                                  const simd8<T> chunk2, const simd8<T> chunk3)
68824
      : chunks{chunk0, chunk1, chunk2, chunk3} {}
68825
  simdjson_inline simd8x64(const T ptr[64])
68826
      : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr + 16),
68827
               simd8<T>::load(ptr + 32), simd8<T>::load(ptr + 48)} {}
68828
68829
  simdjson_inline void store(T ptr[64]) const {
68830
    this->chunks[0].store(ptr + sizeof(simd8<T>) * 0);
68831
    this->chunks[1].store(ptr + sizeof(simd8<T>) * 1);
68832
    this->chunks[2].store(ptr + sizeof(simd8<T>) * 2);
68833
    this->chunks[3].store(ptr + sizeof(simd8<T>) * 3);
68834
  }
68835
68836
  simdjson_inline simd8<T> reduce_or() const {
68837
    return (this->chunks[0] | this->chunks[1]) |
68838
           (this->chunks[2] | this->chunks[3]);
68839
  }
68840
68841
  simdjson_inline uint64_t compress(uint64_t mask, T *output) const {
68842
    this->chunks[0].compress(uint16_t(mask), output);
68843
    this->chunks[1].compress(uint16_t(mask >> 16),
68844
                             output + 16 - count_ones(mask & 0xFFFF));
68845
    this->chunks[2].compress(uint16_t(mask >> 32),
68846
                             output + 32 - count_ones(mask & 0xFFFFFFFF));
68847
    this->chunks[3].compress(uint16_t(mask >> 48),
68848
                             output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
68849
    return 64 - count_ones(mask);
68850
  }
68851
68852
  simdjson_inline uint64_t to_bitmask() const {
68853
    uint64_t r0 = uint32_t(this->chunks[0].to_bitmask());
68854
    uint64_t r1 = this->chunks[1].to_bitmask();
68855
    uint64_t r2 = this->chunks[2].to_bitmask();
68856
    uint64_t r3 = this->chunks[3].to_bitmask();
68857
    return r0 | (r1 << 16) | (r2 << 32) | (r3 << 48);
68858
  }
68859
68860
  simdjson_inline uint64_t eq(const T m) const {
68861
    const simd8<T> mask = simd8<T>::splat(m);
68862
    return simd8x64<bool>(this->chunks[0] == mask, this->chunks[1] == mask,
68863
                          this->chunks[2] == mask, this->chunks[3] == mask)
68864
        .to_bitmask();
68865
  }
68866
68867
  simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
68868
    return simd8x64<bool>(this->chunks[0] == other.chunks[0],
68869
                          this->chunks[1] == other.chunks[1],
68870
                          this->chunks[2] == other.chunks[2],
68871
                          this->chunks[3] == other.chunks[3])
68872
        .to_bitmask();
68873
  }
68874
68875
  simdjson_inline uint64_t lteq(const T m) const {
68876
    const simd8<T> mask = simd8<T>::splat(m);
68877
    return simd8x64<bool>(this->chunks[0] <= mask, this->chunks[1] <= mask,
68878
                          this->chunks[2] <= mask, this->chunks[3] <= mask)
68879
        .to_bitmask();
68880
  }
68881
}; // struct simd8x64<T>
68882
68883
} // namespace simd
68884
} // unnamed namespace
68885
} // namespace ppc64
68886
} // namespace simdjson
68887
68888
#endif // SIMDJSON_PPC64_SIMD_INPUT_H
68889
/* end file simdjson/ppc64/simd.h */
68890
/* including simdjson/ppc64/stringparsing_defs.h: #include "simdjson/ppc64/stringparsing_defs.h" */
68891
/* begin file simdjson/ppc64/stringparsing_defs.h */
68892
#ifndef SIMDJSON_PPC64_STRINGPARSING_DEFS_H
68893
#define SIMDJSON_PPC64_STRINGPARSING_DEFS_H
68894
68895
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68896
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
68897
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/bitmanipulation.h" */
68898
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/simd.h" */
68899
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68900
68901
namespace simdjson {
68902
namespace ppc64 {
68903
namespace {
68904
68905
using namespace simd;
68906
68907
// Holds backslashes and quotes locations.
68908
struct backslash_and_quote {
68909
public:
68910
  static constexpr uint32_t BYTES_PROCESSED = 32;
68911
  simdjson_inline static backslash_and_quote
68912
  copy_and_find(const uint8_t *src, uint8_t *dst);
68913
68914
  simdjson_inline bool has_quote_first() {
68915
    return ((bs_bits - 1) & quote_bits) != 0;
68916
  }
68917
  simdjson_inline bool has_backslash() { return bs_bits != 0; }
68918
  simdjson_inline int quote_index() {
68919
    return trailing_zeroes(quote_bits);
68920
  }
68921
  simdjson_inline int backslash_index() {
68922
    return trailing_zeroes(bs_bits);
68923
  }
68924
68925
  uint32_t bs_bits;
68926
  uint32_t quote_bits;
68927
}; // struct backslash_and_quote
68928
68929
simdjson_inline backslash_and_quote
68930
backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
68931
  // this can read up to 31 bytes beyond the buffer size, but we require
68932
  // SIMDJSON_PADDING of padding
68933
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1),
68934
                "backslash and quote finder must process fewer than "
68935
                "SIMDJSON_PADDING bytes");
68936
  simd8<uint8_t> v0(src);
68937
  simd8<uint8_t> v1(src + sizeof(v0));
68938
  v0.store(dst);
68939
  v1.store(dst + sizeof(v0));
68940
68941
  // Getting a 64-bit bitmask is much cheaper than multiple 16-bit bitmasks on
68942
  // PPC; therefore, we smash them together into a 64-byte mask and get the
68943
  // bitmask from there.
68944
  uint64_t bs_and_quote =
68945
      simd8x64<bool>(v0 == '\\', v1 == '\\', v0 == '"', v1 == '"').to_bitmask();
68946
  return {
68947
      uint32_t(bs_and_quote),      // bs_bits
68948
      uint32_t(bs_and_quote >> 32) // quote_bits
68949
  };
68950
}
68951
68952
} // unnamed namespace
68953
} // namespace ppc64
68954
} // namespace simdjson
68955
68956
#endif // SIMDJSON_PPC64_STRINGPARSING_DEFS_H
68957
/* end file simdjson/ppc64/stringparsing_defs.h */
68958
68959
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
68960
/* end file simdjson/ppc64/begin.h */
68961
/* including simdjson/generic/ondemand/amalgamated.h for ppc64: #include "simdjson/generic/ondemand/amalgamated.h" */
68962
/* begin file simdjson/generic/ondemand/amalgamated.h for ppc64 */
68963
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
68964
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
68965
#endif
68966
68967
// Stuff other things depend on
68968
/* including simdjson/generic/ondemand/base.h for ppc64: #include "simdjson/generic/ondemand/base.h" */
68969
/* begin file simdjson/generic/ondemand/base.h for ppc64 */
68970
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
68971
68972
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
68973
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_BASE_H */
68974
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
68975
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
68976
68977
namespace simdjson {
68978
namespace ppc64 {
68979
/**
68980
 * A fast, simple, DOM-like interface that parses JSON as you use it.
68981
 *
68982
 * Designed for maximum speed and a lower memory profile.
68983
 */
68984
namespace ondemand {
68985
68986
/** Represents the depth of a JSON value (number of nested arrays/objects). */
68987
using depth_t = int32_t;
68988
68989
/** @copydoc simdjson::ppc64::number_type */
68990
using number_type = simdjson::ppc64::number_type;
68991
68992
/** @private Position in the JSON buffer indexes */
68993
using token_position = const uint32_t *;
68994
68995
class array;
68996
class array_iterator;
68997
class document;
68998
class document_reference;
68999
class document_stream;
69000
class field;
69001
class json_iterator;
69002
enum class json_type;
69003
struct number;
69004
class object;
69005
class object_iterator;
69006
class parser;
69007
class raw_json_string;
69008
class token_iterator;
69009
class value;
69010
class value_iterator;
69011
69012
} // namespace ondemand
69013
} // namespace ppc64
69014
} // namespace simdjson
69015
69016
#endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H
69017
/* end file simdjson/generic/ondemand/base.h for ppc64 */
69018
/* including simdjson/generic/ondemand/value_iterator.h for ppc64: #include "simdjson/generic/ondemand/value_iterator.h" */
69019
/* begin file simdjson/generic/ondemand/value_iterator.h for ppc64 */
69020
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
69021
69022
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
69023
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H */
69024
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
69025
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
69026
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
69027
69028
namespace simdjson {
69029
namespace ppc64 {
69030
namespace ondemand {
69031
69032
/**
69033
 * Iterates through a single JSON value at a particular depth.
69034
 *
69035
 * Does not keep track of the type of value: provides methods for objects, arrays and scalars and expects
69036
 * the caller to call the right ones.
69037
 *
69038
 * @private This is not intended for external use.
69039
 */
69040
class value_iterator {
69041
protected:
69042
  /** The underlying JSON iterator */
69043
  json_iterator *_json_iter{};
69044
  /** The depth of this value */
69045
  depth_t _depth{};
69046
  /**
69047
   * The starting token index for this value
69048
   */
69049
  token_position _start_position{};
69050
69051
public:
69052
  simdjson_inline value_iterator() noexcept = default;
69053
69054
  /**
69055
   * Denote that we're starting a document.
69056
   */
69057
  simdjson_inline void start_document() noexcept;
69058
69059
  /**
69060
   * Skips a non-iterated or partially-iterated JSON value, whether it is a scalar, array or object.
69061
   *
69062
   * Optimized for scalars.
69063
   */
69064
  simdjson_warn_unused simdjson_inline error_code skip_child() noexcept;
69065
69066
  /**
69067
   * Tell whether the iterator is at the EOF mark
69068
   */
69069
  simdjson_inline bool at_end() const noexcept;
69070
69071
  /**
69072
   * Tell whether the iterator is at the start of the value
69073
   */
69074
  simdjson_inline bool at_start() const noexcept;
69075
69076
  /**
69077
   * Tell whether the value is open--if the value has not been used, or the array/object is still open.
69078
   */
69079
  simdjson_inline bool is_open() const noexcept;
69080
69081
  /**
69082
   * Tell whether the value is at an object's first field (just after the {).
69083
   */
69084
  simdjson_inline bool at_first_field() const noexcept;
69085
69086
  /**
69087
   * Abandon all iteration.
69088
   */
69089
  simdjson_inline void abandon() noexcept;
69090
69091
  /**
69092
   * Get the child value as a value_iterator.
69093
   */
69094
  simdjson_inline value_iterator child_value() const noexcept;
69095
69096
  /**
69097
   * Get the depth of this value.
69098
   */
69099
  simdjson_inline int32_t depth() const noexcept;
69100
69101
  /**
69102
   * Get the JSON type of this value.
69103
   *
69104
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
69105
   */
69106
  simdjson_inline simdjson_result<json_type> type() const noexcept;
69107
69108
  /**
69109
   * @addtogroup object Object iteration
69110
   *
69111
   * Methods to iterate and find object fields. These methods generally *assume* the value is
69112
   * actually an object; the caller is responsible for keeping track of that fact.
69113
   *
69114
   * @{
69115
   */
69116
69117
  /**
69118
   * Start an object iteration.
69119
   *
69120
   * @returns Whether the object had any fields (returns false for empty).
69121
   * @error INCORRECT_TYPE if there is no opening {
69122
   */
69123
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_object() noexcept;
69124
  /**
69125
   * Start an object iteration from the root.
69126
   *
69127
   * @returns Whether the object had any fields (returns false for empty).
69128
   * @error INCORRECT_TYPE if there is no opening {
69129
   * @error TAPE_ERROR if there is no matching } at end of document
69130
   */
69131
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_object() noexcept;
69132
  /**
69133
   * Checks whether an object could be started from the root. May be called by start_root_object.
69134
   *
69135
   * @returns SUCCESS if it is possible to safely start an object from the root (document level).
69136
   * @error INCORRECT_TYPE if there is no opening {
69137
   * @error TAPE_ERROR if there is no matching } at end of document
69138
   */
69139
  simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept;
69140
  /**
69141
   * Start an object iteration after the user has already checked and moved past the {.
69142
   *
69143
   * Does not move the iterator unless the object is empty ({}).
69144
   *
69145
   * @returns Whether the object had any fields (returns false for empty).
69146
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
69147
   *        array or object is incomplete).
69148
   */
69149
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_object() noexcept;
69150
  /**
69151
   * Start an object iteration from the root, after the user has already checked and moved past the {.
69152
   *
69153
   * Does not move the iterator unless the object is empty ({}).
69154
   *
69155
   * @returns Whether the object had any fields (returns false for empty).
69156
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
69157
   *        array or object is incomplete).
69158
   */
69159
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_object() noexcept;
69160
69161
  /**
69162
   * Moves to the next field in an object.
69163
   *
69164
   * Looks for , and }. If } is found, the object is finished and the iterator advances past it.
69165
   * Otherwise, it advances to the next value.
69166
   *
69167
   * @return whether there is another field in the object.
69168
   * @error TAPE_ERROR If there is a comma missing between fields.
69169
   * @error TAPE_ERROR If there is a comma, but not enough tokens remaining to have a key, :, and value.
69170
   */
69171
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_field() noexcept;
69172
69173
  /**
69174
   * Get the current field's key.
69175
   */
69176
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> field_key() noexcept;
69177
69178
  /**
69179
   * Pass the : in the field and move to its value.
69180
   */
69181
  simdjson_warn_unused simdjson_inline error_code field_value() noexcept;
69182
69183
  /**
69184
   * Find the next field with the given key.
69185
   *
69186
   * Assumes you have called next_field() or otherwise matched the previous value.
69187
   *
69188
   * This means the iterator must be sitting at the next key:
69189
   *
69190
   * ```
69191
   * { "a": 1, "b": 2 }
69192
   *           ^
69193
   * ```
69194
   *
69195
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
69196
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
69197
   * fail to match some keys with escapes (\u, \n, etc.).
69198
   */
69199
  simdjson_warn_unused simdjson_inline error_code find_field(const std::string_view key) noexcept;
69200
69201
  /**
69202
   * Find the next field with the given key, *without* unescaping. This assumes object order: it
69203
   * will not find the field if it was already passed when looking for some *other* field.
69204
   *
69205
   * Assumes you have called next_field() or otherwise matched the previous value.
69206
   *
69207
   * This means the iterator must be sitting at the next key:
69208
   *
69209
   * ```
69210
   * { "a": 1, "b": 2 }
69211
   *           ^
69212
   * ```
69213
   *
69214
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
69215
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
69216
   * fail to match some keys with escapes (\u, \n, etc.).
69217
   */
69218
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
69219
69220
  /**
69221
   * Find the field with the given key without regard to order, and *without* unescaping.
69222
   *
69223
   * This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
69224
   *
69225
   * Assumes you have called next_field() or otherwise matched the previous value.
69226
   *
69227
   * This means the iterator must be sitting at the next key:
69228
   *
69229
   * ```
69230
   * { "a": 1, "b": 2 }
69231
   *           ^
69232
   * ```
69233
   *
69234
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
69235
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
69236
   * fail to match some keys with escapes (\u, \n, etc.).
69237
   */
69238
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
69239
69240
  /** @} */
69241
69242
  /**
69243
   * @addtogroup array Array iteration
69244
   * Methods to iterate over array elements. These methods generally *assume* the value is actually
69245
   * an object; the caller is responsible for keeping track of that fact.
69246
   * @{
69247
   */
69248
69249
  /**
69250
   * Check for an opening [ and start an array iteration.
69251
   *
69252
   * @returns Whether the array had any elements (returns false for empty).
69253
   * @error INCORRECT_TYPE If there is no [.
69254
   */
69255
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_array() noexcept;
69256
  /**
69257
   * Check for an opening [ and start an array iteration while at the root.
69258
   *
69259
   * @returns Whether the array had any elements (returns false for empty).
69260
   * @error INCORRECT_TYPE If there is no [.
69261
   * @error TAPE_ERROR if there is no matching ] at end of document
69262
   */
69263
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_array() noexcept;
69264
  /**
69265
   * Checks whether an array could be started from the root. May be called by start_root_array.
69266
   *
69267
   * @returns SUCCESS if it is possible to safely start an array from the root (document level).
69268
   * @error INCORRECT_TYPE If there is no [.
69269
   * @error TAPE_ERROR if there is no matching ] at end of document
69270
   */
69271
  simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept;
69272
  /**
69273
   * Start an array iteration, after the user has already checked and moved past the [.
69274
   *
69275
   * Does not move the iterator unless the array is empty ([]).
69276
   *
69277
   * @returns Whether the array had any elements (returns false for empty).
69278
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
69279
   *        array or object is incomplete).
69280
   */
69281
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_array() noexcept;
69282
  /**
69283
   * Start an array iteration from the root, after the user has already checked and moved past the [.
69284
   *
69285
   * Does not move the iterator unless the array is empty ([]).
69286
   *
69287
   * @returns Whether the array had any elements (returns false for empty).
69288
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
69289
   *        array or object is incomplete).
69290
   */
69291
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_array() noexcept;
69292
69293
  /**
69294
   * Moves to the next element in an array.
69295
   *
69296
   * Looks for , and ]. If ] is found, the array is finished and the iterator advances past it.
69297
   * Otherwise, it advances to the next value.
69298
   *
69299
   * @return Whether there is another element in the array.
69300
   * @error TAPE_ERROR If there is a comma missing between elements.
69301
   */
69302
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_element() noexcept;
69303
69304
  /**
69305
   * Get a child value iterator.
69306
   */
69307
  simdjson_warn_unused simdjson_inline value_iterator child() const noexcept;
69308
69309
  /** @} */
69310
69311
  /**
69312
   * @defgroup scalar Scalar values
69313
   * @addtogroup scalar
69314
   * @{
69315
   */
69316
69317
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
69318
  template <typename string_type>
69319
  simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
69320
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
69321
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
69322
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
69323
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
69324
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
69325
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
69326
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
69327
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
69328
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
69329
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
69330
  simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
69331
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
69332
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
69333
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
69334
69335
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
69336
  template <typename string_type>
69337
  simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
69338
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
69339
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
69340
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
69341
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
69342
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
69343
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
69344
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
69345
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
69346
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
69347
  simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
69348
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
69349
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
69350
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
69351
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
69352
69353
  simdjson_inline error_code error() const noexcept;
69354
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
69355
  simdjson_inline const json_iterator &json_iter() const noexcept;
69356
  simdjson_inline json_iterator &json_iter() noexcept;
69357
69358
  simdjson_inline void assert_is_valid() const noexcept;
69359
  simdjson_inline bool is_valid() const noexcept;
69360
69361
  /** @} */
69362
protected:
69363
  /**
69364
   * Restarts an array iteration.
69365
   * @returns Whether the array has any elements (returns false for empty).
69366
   */
69367
  simdjson_inline simdjson_result<bool> reset_array() noexcept;
69368
  /**
69369
   * Restarts an object iteration.
69370
   * @returns Whether the object has any fields (returns false for empty).
69371
   */
69372
  simdjson_inline simdjson_result<bool> reset_object() noexcept;
69373
  /**
69374
   * move_at_start(): moves us so that we are pointing at the beginning of
69375
   * the container. It updates the index so that at_start() is true and it
69376
   * syncs the depth. The user can then create a new container instance.
69377
   *
69378
   * Usage: used with value::count_elements().
69379
   **/
69380
  simdjson_inline void move_at_start() noexcept;
69381
69382
  /**
69383
   * move_at_container_start(): moves us so that we are pointing at the beginning of
69384
   * the container so that assert_at_container_start() passes.
69385
   *
69386
   * Usage: used with reset_array() and reset_object().
69387
   **/
69388
   simdjson_inline void move_at_container_start() noexcept;
69389
  /* Useful for debugging and logging purposes. */
69390
  inline std::string to_string() const noexcept;
69391
  simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
69392
69393
  simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
69394
  simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
69395
  simdjson_inline const uint8_t *peek_start() const noexcept;
69396
  simdjson_inline uint32_t peek_start_length() const noexcept;
69397
  simdjson_inline uint32_t peek_root_length() const noexcept;
69398
69399
  /**
69400
   * The general idea of the advance_... methods and the peek_* methods
69401
   * is that you first peek and check that you have desired type. If you do,
69402
   * and only if you do, then you advance.
69403
   *
69404
   * We used to unconditionally advance. But this made reasoning about our
69405
   * current state difficult.
69406
   * Suppose you always advance. Look at the 'value' matching the key
69407
   * "shadowable" in the following example...
69408
   *
69409
   * ({"globals":{"a":{"shadowable":[}}}})
69410
   *
69411
   * If the user thinks it is a Boolean and asks for it, then we check the '[',
69412
   * decide it is not a Boolean, but still move into the next character ('}'). Now
69413
   * we are left pointing at '}' right after a '['. And we have not yet reported
69414
   * an error, only that we do not have a Boolean.
69415
   *
69416
   * If, instead, you just stand your ground until it is content that you know, then
69417
   * you will only even move beyond the '[' if the user tells you that you have an
69418
   * array. So you will be at the '}' character inside the array and, hopefully, you
69419
   * will then catch the error because an array cannot start with '}', but the code
69420
   * processing Boolean values does not know this.
69421
   *
69422
   * So the contract is: first call 'peek_...' and then call 'advance_...' only
69423
   * if you have determined that it is a type you can handle.
69424
   *
69425
   * Unfortunately, it makes the code more verbose, longer and maybe more error prone.
69426
   */
69427
69428
  simdjson_inline void advance_scalar(const char *type) noexcept;
69429
  simdjson_inline void advance_root_scalar(const char *type) noexcept;
69430
  simdjson_inline void advance_non_root_scalar(const char *type) noexcept;
69431
69432
  simdjson_inline const uint8_t *peek_scalar(const char *type) noexcept;
69433
  simdjson_inline const uint8_t *peek_root_scalar(const char *type) noexcept;
69434
  simdjson_inline const uint8_t *peek_non_root_scalar(const char *type) noexcept;
69435
69436
69437
  simdjson_inline error_code start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept;
69438
  simdjson_inline error_code end_container() noexcept;
69439
69440
  /**
69441
   * Advance to a place expecting a value (increasing depth).
69442
   *
69443
   * @return The current token (the one left behind).
69444
   * @error TAPE_ERROR If the document ended early.
69445
   */
69446
  simdjson_inline simdjson_result<const uint8_t *> advance_to_value() noexcept;
69447
69448
  simdjson_inline error_code incorrect_type_error(const char *message) const noexcept;
69449
  simdjson_inline error_code error_unless_more_tokens(uint32_t tokens=1) const noexcept;
69450
69451
  simdjson_inline bool is_at_start() const noexcept;
69452
  /**
69453
   * is_at_iterator_start() returns true on an array or object after it has just been
69454
   * created, whether the instance is empty or not.
69455
   *
69456
   * Usage: used by array::begin() in debug mode (SIMDJSON_DEVELOPMENT_CHECKS)
69457
   */
69458
  simdjson_inline bool is_at_iterator_start() const noexcept;
69459
69460
  /**
69461
   * Assuming that we are within an object, this returns true if we
69462
   * are pointing at a key.
69463
   *
69464
   * Usage: the skip_child() method should never be used while we are pointing
69465
   * at a key inside an object.
69466
   */
69467
  simdjson_inline bool is_at_key() const noexcept;
69468
69469
  inline void assert_at_start() const noexcept;
69470
  inline void assert_at_container_start() const noexcept;
69471
  inline void assert_at_root() const noexcept;
69472
  inline void assert_at_child() const noexcept;
69473
  inline void assert_at_next() const noexcept;
69474
  inline void assert_at_non_root_start() const noexcept;
69475
69476
  /** Get the starting position of this value */
69477
  simdjson_inline token_position start_position() const noexcept;
69478
69479
  /** @copydoc error_code json_iterator::position() const noexcept; */
69480
  simdjson_inline token_position position() const noexcept;
69481
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
69482
  simdjson_inline token_position last_position() const noexcept;
69483
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
69484
  simdjson_inline token_position end_position() const noexcept;
69485
  /** @copydoc error_code json_iterator::report_error(error_code error, const char *message) noexcept; */
69486
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
69487
69488
  friend class document;
69489
  friend class object;
69490
  friend class array;
69491
  friend class value;
69492
  friend class field;
69493
}; // value_iterator
69494
69495
} // namespace ondemand
69496
} // namespace ppc64
69497
} // namespace simdjson
69498
69499
namespace simdjson {
69500
69501
template<>
69502
struct simdjson_result<ppc64::ondemand::value_iterator> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::value_iterator> {
69503
public:
69504
  simdjson_inline simdjson_result(ppc64::ondemand::value_iterator &&value) noexcept; ///< @private
69505
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
69506
  simdjson_inline simdjson_result() noexcept = default;
69507
};
69508
69509
} // namespace simdjson
69510
69511
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
69512
/* end file simdjson/generic/ondemand/value_iterator.h for ppc64 */
69513
/* including simdjson/generic/ondemand/value.h for ppc64: #include "simdjson/generic/ondemand/value.h" */
69514
/* begin file simdjson/generic/ondemand/value.h for ppc64 */
69515
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H
69516
69517
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
69518
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_H */
69519
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
69520
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
69521
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
69522
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
69523
69524
namespace simdjson {
69525
namespace ppc64 {
69526
namespace ondemand {
69527
69528
/**
69529
 * An ephemeral JSON value returned during iteration. It is only valid for as long as you do
69530
 * not access more data in the JSON document.
69531
 */
69532
class value {
69533
public:
69534
  /**
69535
   * Create a new invalid value.
69536
   *
69537
   * Exists so you can declare a variable and later assign to it before use.
69538
   */
69539
  simdjson_inline value() noexcept = default;
69540
69541
  /**
69542
   * Get this value as the given type.
69543
   *
69544
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
69545
   *
69546
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
69547
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
69548
   *
69549
   * @returns A value of the given type, parsed from the JSON.
69550
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
69551
   */
69552
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
69553
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
69554
    // immediately fail.
69555
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
69556
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
69557
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
69558
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
69559
      " You may also add support for custom types, see our documentation.");
69560
  }
69561
69562
  /**
69563
   * Get this value as the given type.
69564
   *
69565
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
69566
   *
69567
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
69568
   * @returns INCORRECT_TYPE If the JSON value is not an object.
69569
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
69570
   */
69571
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
69572
69573
  /**
69574
   * Cast this JSON value to an array.
69575
   *
69576
   * @returns An object that can be used to iterate the array.
69577
   * @returns INCORRECT_TYPE If the JSON value is not an array.
69578
   */
69579
  simdjson_inline simdjson_result<array> get_array() noexcept;
69580
69581
  /**
69582
   * Cast this JSON value to an object.
69583
   *
69584
   * @returns An object that can be used to look up or iterate fields.
69585
   * @returns INCORRECT_TYPE If the JSON value is not an object.
69586
   */
69587
  simdjson_inline simdjson_result<object> get_object() noexcept;
69588
69589
  /**
69590
   * Cast this JSON value to an unsigned integer.
69591
   *
69592
   * @returns A unsigned 64-bit integer.
69593
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
69594
   */
69595
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
69596
69597
  /**
69598
   * Cast this JSON value (inside string) to a unsigned integer.
69599
   *
69600
   * @returns A unsigned 64-bit integer.
69601
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
69602
   */
69603
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
69604
69605
  /**
69606
   * Cast this JSON value to a signed integer.
69607
   *
69608
   * @returns A signed 64-bit integer.
69609
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
69610
   */
69611
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
69612
69613
  /**
69614
   * Cast this JSON value (inside string) to a signed integer.
69615
   *
69616
   * @returns A signed 64-bit integer.
69617
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
69618
   */
69619
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
69620
69621
  /**
69622
   * Cast this JSON value to a double.
69623
   *
69624
   * @returns A double.
69625
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
69626
   */
69627
  simdjson_inline simdjson_result<double> get_double() noexcept;
69628
69629
  /**
69630
   * Cast this JSON value (inside string) to a double
69631
   *
69632
   * @returns A double.
69633
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
69634
   */
69635
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
69636
69637
  /**
69638
   * Cast this JSON value to a string.
69639
   *
69640
   * The string is guaranteed to be valid UTF-8.
69641
   *
69642
   * Equivalent to get<std::string_view>().
69643
   *
69644
   * Important: a value should be consumed once. Calling get_string() twice on the same value
69645
   * is an error.
69646
   *
69647
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
69648
   *          time it parses a document or when it is destroyed.
69649
   * @returns INCORRECT_TYPE if the JSON value is not a string.
69650
   */
69651
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
69652
69653
  /**
69654
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
69655
   *
69656
   * The string is guaranteed to be valid UTF-8.
69657
   *
69658
   * Important: a value should be consumed once. Calling get_string() twice on the same value
69659
   * is an error.
69660
   *
69661
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
69662
   * We recommend you avoid allocating an std::string unless you need to.
69663
   *
69664
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
69665
   */
69666
  template <typename string_type>
69667
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
69668
69669
  /**
69670
   * Cast this JSON value to a "wobbly" string.
69671
   *
69672
   * The string is may not be a valid UTF-8 string.
69673
   * See https://simonsapin.github.io/wtf-8/
69674
   *
69675
   * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value
69676
   * is an error.
69677
   *
69678
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
69679
   *          time it parses a document or when it is destroyed.
69680
   * @returns INCORRECT_TYPE if the JSON value is not a string.
69681
   */
69682
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
69683
  /**
69684
   * Cast this JSON value to a raw_json_string.
69685
   *
69686
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
69687
   *
69688
   * @returns A pointer to the raw JSON for the given string.
69689
   * @returns INCORRECT_TYPE if the JSON value is not a string.
69690
   */
69691
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
69692
69693
  /**
69694
   * Cast this JSON value to a bool.
69695
   *
69696
   * @returns A bool value.
69697
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
69698
   */
69699
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
69700
69701
  /**
69702
   * Checks if this JSON value is null. If and only if the value is
69703
   * null, then it is consumed (we advance). If we find a token that
69704
   * begins with 'n' but is not 'null', then an error is returned.
69705
   *
69706
   * @returns Whether the value is null.
69707
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
69708
   */
69709
  simdjson_inline simdjson_result<bool> is_null() noexcept;
69710
69711
#if SIMDJSON_EXCEPTIONS
69712
  /**
69713
   * Cast this JSON value to an instance of type T. The programmer is responsible for
69714
   * providing an implementation of get<T> for the type T, if T is not one of the types
69715
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.).
69716
   *
69717
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
69718
   *
69719
   * @returns An instance of type T
69720
   */
69721
  template <class T>
69722
  explicit simdjson_inline operator T() noexcept(false);
69723
  /**
69724
   * Cast this JSON value to an array.
69725
   *
69726
   * @returns An object that can be used to iterate the array.
69727
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
69728
   */
69729
  simdjson_inline operator array() noexcept(false);
69730
  /**
69731
   * Cast this JSON value to an object.
69732
   *
69733
   * @returns An object that can be used to look up or iterate fields.
69734
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
69735
   */
69736
  simdjson_inline operator object() noexcept(false);
69737
  /**
69738
   * Cast this JSON value to an unsigned integer.
69739
   *
69740
   * @returns A signed 64-bit integer.
69741
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
69742
   */
69743
  simdjson_inline operator uint64_t() noexcept(false);
69744
  /**
69745
   * Cast this JSON value to a signed integer.
69746
   *
69747
   * @returns A signed 64-bit integer.
69748
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
69749
   */
69750
  simdjson_inline operator int64_t() noexcept(false);
69751
  /**
69752
   * Cast this JSON value to a double.
69753
   *
69754
   * @returns A double.
69755
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
69756
   */
69757
  simdjson_inline operator double() noexcept(false);
69758
  /**
69759
   * Cast this JSON value to a string.
69760
   *
69761
   * The string is guaranteed to be valid UTF-8.
69762
   *
69763
   * Equivalent to get<std::string_view>().
69764
   *
69765
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
69766
   *          time it parses a document or when it is destroyed.
69767
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
69768
   */
69769
  simdjson_inline operator std::string_view() noexcept(false);
69770
  /**
69771
   * Cast this JSON value to a raw_json_string.
69772
   *
69773
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
69774
   *
69775
   * @returns A pointer to the raw JSON for the given string.
69776
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
69777
   */
69778
  simdjson_inline operator raw_json_string() noexcept(false);
69779
  /**
69780
   * Cast this JSON value to a bool.
69781
   *
69782
   * @returns A bool value.
69783
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
69784
   */
69785
  simdjson_inline operator bool() noexcept(false);
69786
#endif
69787
69788
  /**
69789
   * Begin array iteration.
69790
   *
69791
   * Part of the std::iterable interface.
69792
   *
69793
   * @returns INCORRECT_TYPE If the JSON value is not an array.
69794
   */
69795
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
69796
  /**
69797
   * Sentinel representing the end of the array.
69798
   *
69799
   * Part of the std::iterable interface.
69800
   */
69801
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
69802
  /**
69803
   * This method scans the array and counts the number of elements.
69804
   * The count_elements method should always be called before you have begun
69805
   * iterating through the array: it is expected that you are pointing at
69806
   * the beginning of the array.
69807
   * The runtime complexity is linear in the size of the array. After
69808
   * calling this function, if successful, the array is 'rewinded' at its
69809
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
69810
   * there is a missing comma), then an error is returned and it is no longer
69811
   * safe to continue.
69812
   *
69813
   * Performance hint: You should only call count_elements() as a last
69814
   * resort as it may require scanning the document twice or more.
69815
   */
69816
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
69817
  /**
69818
   * This method scans the object and counts the number of key-value pairs.
69819
   * The count_fields method should always be called before you have begun
69820
   * iterating through the object: it is expected that you are pointing at
69821
   * the beginning of the object.
69822
   * The runtime complexity is linear in the size of the object. After
69823
   * calling this function, if successful, the object is 'rewinded' at its
69824
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
69825
   * there is a missing comma), then an error is returned and it is no longer
69826
   * safe to continue.
69827
   *
69828
   * To check that an object is empty, it is more performant to use
69829
   * the is_empty() method on the object instance.
69830
   *
69831
   * Performance hint: You should only call count_fields() as a last
69832
   * resort as it may require scanning the document twice or more.
69833
   */
69834
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
69835
  /**
69836
   * Get the value at the given index in the array. This function has linear-time complexity.
69837
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
69838
   *
69839
   * @return The value at the given index, or:
69840
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
69841
   */
69842
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
69843
  /**
69844
   * Look up a field by name on an object (order-sensitive).
69845
   *
69846
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
69847
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
69848
   *
69849
   * ```c++
69850
   * simdjson::ondemand::parser parser;
69851
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
69852
   * double z = obj.find_field("z");
69853
   * double y = obj.find_field("y");
69854
   * double x = obj.find_field("x");
69855
   * ```
69856
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
69857
   * that only one field is returned.
69858
69859
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
69860
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
69861
   *
69862
   * @param key The key to look up.
69863
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
69864
   */
69865
  simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept;
69866
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
69867
  simdjson_inline simdjson_result<value> find_field(const char *key) noexcept;
69868
69869
  /**
69870
   * Look up a field by name on an object, without regard to key order.
69871
   *
69872
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
69873
   * and often appears negligible. It starts out normally, starting out at the last field; but if
69874
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
69875
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
69876
   * in question is large. The fact that the extra code is there also bumps the executable size.
69877
   *
69878
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
69879
   * default behavior failed to look up a field just because it was in the wrong order--and many
69880
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
69881
   *
69882
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
69883
   * that only one field is returned.
69884
   *
69885
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
69886
   * field as not there when they are not in order).
69887
   *
69888
   * @param key The key to look up.
69889
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
69890
   */
69891
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
69892
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
69893
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
69894
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
69895
  simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept;
69896
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
69897
  simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
69898
69899
  /**
69900
   * Get the type of this JSON value. It does not validate or consume the value.
69901
   * E.g., you must still call "is_null()" to check that a value is null even if
69902
   * "type()" returns json_type::null.
69903
   *
69904
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
69905
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
69906
   * let it throw an exception).
69907
   *
69908
   * @return The type of JSON value (json_type::array, json_type::object, json_type::string,
69909
   *     json_type::number, json_type::boolean, or json_type::null).
69910
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
69911
   */
69912
  simdjson_inline simdjson_result<json_type> type() noexcept;
69913
69914
  /**
69915
   * Checks whether the value is a scalar (string, number, null, Boolean).
69916
   * Returns false when there it is an array or object.
69917
   *
69918
   * @returns true if the type is string, number, null, Boolean
69919
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
69920
   */
69921
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
69922
  /**
69923
   * Checks whether the value is a string.
69924
   *
69925
   * @returns true if the type is string
69926
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
69927
   */
69928
  simdjson_inline simdjson_result<bool> is_string() noexcept;
69929
69930
  /**
69931
   * Checks whether the value is a negative number.
69932
   *
69933
   * @returns true if the number if negative.
69934
   */
69935
  simdjson_inline bool is_negative() noexcept;
69936
  /**
69937
   * Checks whether the value is an integer number. Note that
69938
   * this requires to partially parse the number string. If
69939
   * the value is determined to be an integer, it may still
69940
   * not parse properly as an integer in subsequent steps
69941
   * (e.g., it might overflow).
69942
   *
69943
   * Performance note: if you call this function systematically
69944
   * before parsing a number, you may have fallen for a performance
69945
   * anti-pattern.
69946
   *
69947
   * @returns true if the number if negative.
69948
   */
69949
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
69950
  /**
69951
   * Determine the number type (integer or floating-point number) as quickly
69952
   * as possible. This function does not fully validate the input. It is
69953
   * useful when you only need to classify the numbers, without parsing them.
69954
   *
69955
   * If you are planning to retrieve the value or you need full validation,
69956
   * consider using the get_number() method instead: it will fully parse
69957
   * and validate the input, and give you access to the type:
69958
   * get_number().get_number_type().
69959
   *
69960
   * get_number_type() is number_type::unsigned_integer if we have
69961
   * an integer greater or equal to 9223372036854775808.
69962
   * get_number_type() is number_type::signed_integer if we have an
69963
   * integer that is less than 9223372036854775808.
69964
   * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits,
69965
   * in which case the digit_count is set to the length of the big integer string.
69966
   * Otherwise, get_number_type() has value number_type::floating_point_number.
69967
   *
69968
   * This function requires processing the number string, but it is expected
69969
   * to be faster than get_number().get_number_type() because it is does not
69970
   * parse the number value.
69971
   *
69972
   * @returns the type of the number
69973
   */
69974
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
69975
69976
  /**
69977
   * Attempt to parse an ondemand::number. An ondemand::number may
69978
   * contain an integer value or a floating-point value, the simdjson
69979
   * library will autodetect the type. Thus it is a dynamically typed
69980
   * number. Before accessing the value, you must determine the detected
69981
   * type.
69982
   *
69983
   * number.get_number_type() is number_type::signed_integer if we have
69984
   * an integer in [-9223372036854775808,9223372036854775808)
69985
   * You can recover the value by calling number.get_int64() and you
69986
   * have that number.is_int64() is true.
69987
   *
69988
   * number.get_number_type() is number_type::unsigned_integer if we have
69989
   * an integer in [9223372036854775808,18446744073709551616)
69990
   * You can recover the value by calling number.get_uint64() and you
69991
   * have that number.is_uint64() is true.
69992
   *
69993
   * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code.
69994
   *
69995
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
69996
   * and we have a binary64 number.
69997
   * You can recover the value by calling number.get_double() and you
69998
   * have that number.is_double() is true.
69999
   *
70000
   * You must check the type before accessing the value: it is an error
70001
   * to call "get_int64()" when number.get_number_type() is not
70002
   * number_type::signed_integer and when number.is_int64() is false.
70003
   *
70004
   * Performance note: this is designed with performance in mind. When
70005
   * calling 'get_number()', you scan the number string only once, determining
70006
   * efficiently the type and storing it in an efficient manner.
70007
   */
70008
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
70009
70010
  /**
70011
   * Get the raw JSON for this token.
70012
   *
70013
   * The string_view will always point into the input buffer.
70014
   *
70015
   * The string_view will start at the beginning of the token, and include the entire token
70016
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
70017
   * string token always begins with a " and is always terminated by the final ", possibly
70018
   * followed by a number of spaces.
70019
   *
70020
   * The string_view is *not* null-terminated. However, if this is a scalar (string, number,
70021
   * boolean, or null), the character after the end of the string_view is guaranteed to be
70022
   * a non-space token.
70023
   *
70024
   * Tokens include:
70025
   * - {
70026
   * - [
70027
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
70028
   * - -1.2e-100
70029
   * - true
70030
   * - false
70031
   * - null
70032
   *
70033
   * See also value::raw_json().
70034
   */
70035
  simdjson_inline std::string_view raw_json_token() noexcept;
70036
70037
  /**
70038
   * Get a string_view pointing at this value in the JSON document.
70039
   * If this element is an array or an object, it consumes the array or the object
70040
   * and returns a string_view instance corresponding to the
70041
   * array as represented in JSON. It points inside the original document.
70042
   * If this element is a scalar (string, number, Boolean, null), it returns what
70043
   * raw_json_token() would return.
70044
   */
70045
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
70046
70047
  /**
70048
   * Returns the current location in the document if in bounds.
70049
   */
70050
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
70051
70052
  /**
70053
   * Returns the current depth in the document if in bounds.
70054
   *
70055
   * E.g.,
70056
   *  0 = finished with document
70057
   *  1 = document root value (could be [ or {, not yet known)
70058
   *  2 = , or } inside root array/object
70059
   *  3 = key or value inside root array/object.
70060
   */
70061
  simdjson_inline int32_t current_depth() const noexcept;
70062
70063
  /**
70064
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
70065
   * https://tools.ietf.org/html/rfc6901 standard.
70066
   *
70067
   *   ondemand::parser parser;
70068
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
70069
   *   auto doc = parser.iterate(json);
70070
   *   doc.at_pointer("/foo/a/1") == 20
70071
   *
70072
   * It is allowed for a key to be the empty string:
70073
   *
70074
   *   ondemand::parser parser;
70075
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
70076
   *   auto doc = parser.iterate(json);
70077
   *   doc.at_pointer("//a/1") == 20
70078
   *
70079
   * Note that at_pointer() called on the document automatically calls the document's rewind
70080
   * method between each call. It invalidates all previously accessed arrays, objects and values
70081
   * that have not been consumed.
70082
   *
70083
   * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not
70084
   * standardized (by RFC 6901). We provide some experimental support for JSON pointers
70085
   * on non-document instances.  Yet it is not the case when calling at_pointer on an array
70086
   * or an object instance: there is no rewind and no invalidation.
70087
   *
70088
   * You may only call at_pointer on an array after it has been created, but before it has
70089
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
70090
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
70091
   * to call at_pointer on the same array.
70092
   *
70093
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
70094
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
70095
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
70096
   *
70097
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
70098
   *
70099
   * @return The value associated with the given JSON pointer, or:
70100
   *         - NO_SUCH_FIELD if a field does not exist in an object
70101
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
70102
   *         - INCORRECT_TYPE if a non-integer is used to access an array
70103
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
70104
   */
70105
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
70106
70107
  /**
70108
   * Get the value associated with the given JSONPath expression. We only support
70109
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
70110
   * names and array indices.
70111
   *
70112
   * @return The value associated with the given JSONPath expression, or:
70113
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
70114
   *         - NO_SUCH_FIELD if a field does not exist in an object
70115
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
70116
   *         - INCORRECT_TYPE if a non-integer is used to access an array
70117
   */
70118
  simdjson_inline simdjson_result<value> at_path(std::string_view at_path) noexcept;
70119
70120
70121
protected:
70122
  /**
70123
   * Create a value.
70124
   */
70125
  simdjson_inline value(const value_iterator &iter) noexcept;
70126
70127
  /**
70128
   * Skip this value, allowing iteration to continue.
70129
   */
70130
  simdjson_inline void skip() noexcept;
70131
70132
  /**
70133
   * Start a value at the current position.
70134
   *
70135
   * (It should already be started; this is just a self-documentation method.)
70136
   */
70137
  static simdjson_inline value start(const value_iterator &iter) noexcept;
70138
70139
  /**
70140
   * Resume a value.
70141
   */
70142
  static simdjson_inline value resume(const value_iterator &iter) noexcept;
70143
70144
  /**
70145
   * Get the object, starting or resuming it as necessary
70146
   */
70147
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
70148
70149
  // simdjson_inline void log_value(const char *type) const noexcept;
70150
  // simdjson_inline void log_error(const char *message) const noexcept;
70151
70152
  value_iterator iter{};
70153
70154
  friend class document;
70155
  friend class array_iterator;
70156
  friend class field;
70157
  friend class object;
70158
  friend struct simdjson_result<value>;
70159
  friend struct simdjson_result<field>;
70160
  friend class field;
70161
};
70162
70163
} // namespace ondemand
70164
} // namespace ppc64
70165
} // namespace simdjson
70166
70167
namespace simdjson {
70168
70169
template<>
70170
struct simdjson_result<ppc64::ondemand::value> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::value> {
70171
public:
70172
  simdjson_inline simdjson_result(ppc64::ondemand::value &&value) noexcept; ///< @private
70173
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
70174
  simdjson_inline simdjson_result() noexcept = default;
70175
70176
  simdjson_inline simdjson_result<ppc64::ondemand::array> get_array() noexcept;
70177
  simdjson_inline simdjson_result<ppc64::ondemand::object> get_object() noexcept;
70178
70179
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
70180
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
70181
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
70182
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
70183
  simdjson_inline simdjson_result<double> get_double() noexcept;
70184
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
70185
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
70186
  template <typename string_type>
70187
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
70188
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
70189
  simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> get_raw_json_string() noexcept;
70190
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
70191
  simdjson_inline simdjson_result<bool> is_null() noexcept;
70192
70193
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
70194
70195
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
70196
70197
#if SIMDJSON_EXCEPTIONS
70198
  template <class T>
70199
  explicit simdjson_inline operator T() noexcept(false);
70200
  simdjson_inline operator ppc64::ondemand::array() noexcept(false);
70201
  simdjson_inline operator ppc64::ondemand::object() noexcept(false);
70202
  simdjson_inline operator uint64_t() noexcept(false);
70203
  simdjson_inline operator int64_t() noexcept(false);
70204
  simdjson_inline operator double() noexcept(false);
70205
  simdjson_inline operator std::string_view() noexcept(false);
70206
  simdjson_inline operator ppc64::ondemand::raw_json_string() noexcept(false);
70207
  simdjson_inline operator bool() noexcept(false);
70208
#endif
70209
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
70210
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
70211
  simdjson_inline simdjson_result<ppc64::ondemand::value> at(size_t index) noexcept;
70212
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> begin() & noexcept;
70213
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> end() & noexcept;
70214
70215
  /**
70216
   * Look up a field by name on an object (order-sensitive).
70217
   *
70218
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
70219
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
70220
   *
70221
   * ```c++
70222
   * simdjson::ondemand::parser parser;
70223
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
70224
   * double z = obj.find_field("z");
70225
   * double y = obj.find_field("y");
70226
   * double x = obj.find_field("x");
70227
   * ```
70228
   *
70229
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
70230
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
70231
   *
70232
   * @param key The key to look up.
70233
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
70234
   */
70235
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(std::string_view key) noexcept;
70236
  /** @overload simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(std::string_view key) noexcept; */
70237
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(const char *key) noexcept;
70238
70239
  /**
70240
   * Look up a field by name on an object, without regard to key order.
70241
   *
70242
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
70243
   * and often appears negligible. It starts out normally, starting out at the last field; but if
70244
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
70245
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
70246
   * in question is large. The fact that the extra code is there also bumps the executable size.
70247
   *
70248
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
70249
   * default behavior failed to look up a field just because it was in the wrong order--and many
70250
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
70251
   *
70252
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
70253
   * field as not there when they are not in order).
70254
   *
70255
   * @param key The key to look up.
70256
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
70257
   */
70258
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) noexcept;
70259
  /** @overload simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
70260
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(const char *key) noexcept;
70261
  /** @overload simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
70262
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](std::string_view key) noexcept;
70263
  /** @overload simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
70264
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](const char *key) noexcept;
70265
70266
  /**
70267
   * Get the type of this JSON value.
70268
   *
70269
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
70270
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
70271
   * let it throw an exception).
70272
   */
70273
  simdjson_inline simdjson_result<ppc64::ondemand::json_type> type() noexcept;
70274
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
70275
  simdjson_inline simdjson_result<bool> is_string() noexcept;
70276
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
70277
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
70278
  simdjson_inline simdjson_result<ppc64::number_type> get_number_type() noexcept;
70279
  simdjson_inline simdjson_result<ppc64::ondemand::number> get_number() noexcept;
70280
70281
  /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
70282
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
70283
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
70284
70285
  /** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
70286
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
70287
  /** @copydoc simdjson_inline int32_t current_depth() const noexcept */
70288
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
70289
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
70290
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_path(std::string_view json_path) noexcept;
70291
};
70292
70293
} // namespace simdjson
70294
70295
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H
70296
/* end file simdjson/generic/ondemand/value.h for ppc64 */
70297
/* including simdjson/generic/ondemand/logger.h for ppc64: #include "simdjson/generic/ondemand/logger.h" */
70298
/* begin file simdjson/generic/ondemand/logger.h for ppc64 */
70299
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
70300
70301
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
70302
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_H */
70303
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
70304
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
70305
70306
namespace simdjson {
70307
namespace ppc64 {
70308
namespace ondemand {
70309
70310
// Logging should be free unless SIMDJSON_VERBOSE_LOGGING is set. Importantly, it is critical
70311
// that the call to the log functions be side-effect free. Thus, for example, you should not
70312
// create temporary std::string instances.
70313
namespace logger {
70314
70315
enum class log_level : int32_t {
70316
  info = 0,
70317
  error = 1
70318
};
70319
70320
#if SIMDJSON_VERBOSE_LOGGING
70321
  static constexpr const bool LOG_ENABLED = true;
70322
#else
70323
  static constexpr const bool LOG_ENABLED = false;
70324
#endif
70325
70326
// We do not want these functions to be 'really inlined' since real inlining is
70327
// for performance purposes and if you are using the loggers, you do not care about
70328
// performance (or should not).
70329
static inline void log_headers() noexcept;
70330
// If args are provided, title will be treated as format string
70331
template <typename... Args>
70332
static inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
70333
template <typename... Args>
70334
static inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
70335
static inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
70336
static inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
70337
static inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
70338
static inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
70339
static inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
70340
static inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
70341
70342
static inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail="") noexcept;
70343
static inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
70344
70345
static inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
70346
static inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
70347
static inline void log_start_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
70348
static inline void log_end_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
70349
static inline void log_error(const value_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
70350
70351
} // namespace logger
70352
} // namespace ondemand
70353
} // namespace ppc64
70354
} // namespace simdjson
70355
70356
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
70357
/* end file simdjson/generic/ondemand/logger.h for ppc64 */
70358
/* including simdjson/generic/ondemand/token_iterator.h for ppc64: #include "simdjson/generic/ondemand/token_iterator.h" */
70359
/* begin file simdjson/generic/ondemand/token_iterator.h for ppc64 */
70360
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
70361
70362
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
70363
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H */
70364
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
70365
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
70366
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
70367
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
70368
70369
namespace simdjson {
70370
namespace ppc64 {
70371
namespace ondemand {
70372
70373
/**
70374
 * Iterates through JSON tokens (`{` `}` `[` `]` `,` `:` `"<string>"` `123` `true` `false` `null`)
70375
 * detected by stage 1.
70376
 *
70377
 * @private This is not intended for external use.
70378
 */
70379
class token_iterator {
70380
public:
70381
  /**
70382
   * Create a new invalid token_iterator.
70383
   *
70384
   * Exists so you can declare a variable and later assign to it before use.
70385
   */
70386
  simdjson_inline token_iterator() noexcept = default;
70387
  simdjson_inline token_iterator(token_iterator &&other) noexcept = default;
70388
  simdjson_inline token_iterator &operator=(token_iterator &&other) noexcept = default;
70389
  simdjson_inline token_iterator(const token_iterator &other) noexcept = default;
70390
  simdjson_inline token_iterator &operator=(const token_iterator &other) noexcept = default;
70391
70392
  /**
70393
   * Advance to the next token (returning the current one).
70394
   */
70395
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
70396
  /**
70397
   * Reports the current offset in bytes from the start of the underlying buffer.
70398
   */
70399
  simdjson_inline uint32_t current_offset() const noexcept;
70400
  /**
70401
   * Get the JSON text for a given token (relative).
70402
   *
70403
   * This is not null-terminated; it is a view into the JSON.
70404
   *
70405
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
70406
   *              1 = next token, -1 = prev token.
70407
   *
70408
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
70409
   * it is not used...
70410
   */
70411
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
70412
  /**
70413
   * Get the maximum length of the JSON text for a given token.
70414
   *
70415
   * The length will include any whitespace at the end of the token.
70416
   *
70417
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
70418
   *              1 = next token, -1 = prev token.
70419
   */
70420
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
70421
70422
  /**
70423
   * Get the JSON text for a given token.
70424
   *
70425
   * This is not null-terminated; it is a view into the JSON.
70426
   *
70427
   * @param position The position of the token.
70428
   *
70429
   */
70430
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
70431
  /**
70432
   * Get the maximum length of the JSON text for a given token.
70433
   *
70434
   * The length will include any whitespace at the end of the token.
70435
   *
70436
   * @param position The position of the token.
70437
   */
70438
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
70439
  /**
70440
   * Get the maximum length of the JSON text for a root token.
70441
   *
70442
   * The length will include any whitespace at the end of the token.
70443
   *
70444
   * @param position The position of the token (start of the document).
70445
   */
70446
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
70447
  /**
70448
   * Return the current index.
70449
   */
70450
  simdjson_inline token_position position() const noexcept;
70451
  /**
70452
   * Reset to a previously saved index.
70453
   */
70454
  simdjson_inline void set_position(token_position target_position) noexcept;
70455
70456
  // NOTE: we don't support a full C++ iterator interface, because we expect people to make
70457
  // different calls to advance the iterator based on *their own* state.
70458
70459
  simdjson_inline bool operator==(const token_iterator &other) const noexcept;
70460
  simdjson_inline bool operator!=(const token_iterator &other) const noexcept;
70461
  simdjson_inline bool operator>(const token_iterator &other) const noexcept;
70462
  simdjson_inline bool operator>=(const token_iterator &other) const noexcept;
70463
  simdjson_inline bool operator<(const token_iterator &other) const noexcept;
70464
  simdjson_inline bool operator<=(const token_iterator &other) const noexcept;
70465
70466
protected:
70467
  simdjson_inline token_iterator(const uint8_t *buf, token_position position) noexcept;
70468
70469
  /**
70470
   * Get the index of the JSON text for a given token (relative).
70471
   *
70472
   * This is not null-terminated; it is a view into the JSON.
70473
   *
70474
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
70475
   *              1 = next token, -1 = prev token.
70476
   */
70477
  simdjson_inline uint32_t peek_index(int32_t delta=0) const noexcept;
70478
  /**
70479
   * Get the index of the JSON text for a given token.
70480
   *
70481
   * This is not null-terminated; it is a view into the JSON.
70482
   *
70483
   * @param position The position of the token.
70484
   *
70485
   */
70486
  simdjson_inline uint32_t peek_index(token_position position) const noexcept;
70487
70488
  const uint8_t *buf{};
70489
  token_position _position{};
70490
70491
  friend class json_iterator;
70492
  friend class value_iterator;
70493
  friend class object;
70494
  template <typename... Args>
70495
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
70496
  template <typename... Args>
70497
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
70498
};
70499
70500
} // namespace ondemand
70501
} // namespace ppc64
70502
} // namespace simdjson
70503
70504
namespace simdjson {
70505
70506
template<>
70507
struct simdjson_result<ppc64::ondemand::token_iterator> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::token_iterator> {
70508
public:
70509
  simdjson_inline simdjson_result(ppc64::ondemand::token_iterator &&value) noexcept; ///< @private
70510
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
70511
  simdjson_inline simdjson_result() noexcept = default;
70512
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
70513
};
70514
70515
} // namespace simdjson
70516
70517
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
70518
/* end file simdjson/generic/ondemand/token_iterator.h for ppc64 */
70519
/* including simdjson/generic/ondemand/json_iterator.h for ppc64: #include "simdjson/generic/ondemand/json_iterator.h" */
70520
/* begin file simdjson/generic/ondemand/json_iterator.h for ppc64 */
70521
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
70522
70523
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
70524
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H */
70525
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
70526
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
70527
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
70528
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
70529
70530
namespace simdjson {
70531
namespace ppc64 {
70532
namespace ondemand {
70533
70534
/**
70535
 * Iterates through JSON tokens, keeping track of depth and string buffer.
70536
 *
70537
 * @private This is not intended for external use.
70538
 */
70539
class json_iterator {
70540
protected:
70541
  token_iterator token{};
70542
  ondemand::parser *parser{};
70543
  /**
70544
   * Next free location in the string buffer.
70545
   *
70546
   * Used by raw_json_string::unescape() to have a place to unescape strings to.
70547
   */
70548
  uint8_t *_string_buf_loc{};
70549
  /**
70550
   * JSON error, if there is one.
70551
   *
70552
   * INCORRECT_TYPE and NO_SUCH_FIELD are *not* stored here, ever.
70553
   *
70554
   * PERF NOTE: we *hope* this will be elided into control flow, as it is only used (a) in the first
70555
   * iteration of the loop, or (b) for the final iteration after a missing comma is found in ++. If
70556
   * this is not elided, we should make sure it's at least not using up a register. Failing that,
70557
   * we should store it in document so there's only one of them.
70558
   */
70559
  error_code error{SUCCESS};
70560
  /**
70561
   * Depth of the current token in the JSON.
70562
   *
70563
   * - 0 = finished with document
70564
   * - 1 = document root value (could be [ or {, not yet known)
70565
   * - 2 = , or } inside root array/object
70566
   * - 3 = key or value inside root array/object.
70567
   */
70568
  depth_t _depth{};
70569
  /**
70570
   * Beginning of the document indexes.
70571
   * Normally we have root == parser->implementation->structural_indexes.get()
70572
   * but this may differ, especially in streaming mode (where we have several
70573
   * documents);
70574
   */
70575
  token_position _root{};
70576
  /**
70577
   * Normally, a json_iterator operates over a single document, but in
70578
   * some cases, we may have a stream of documents. This attribute is meant
70579
   * as meta-data: the json_iterator works the same irrespective of the
70580
   * value of this attribute.
70581
   */
70582
  bool _streaming{false};
70583
70584
public:
70585
  simdjson_inline json_iterator() noexcept = default;
70586
  simdjson_inline json_iterator(json_iterator &&other) noexcept;
70587
  simdjson_inline json_iterator &operator=(json_iterator &&other) noexcept;
70588
  simdjson_inline explicit json_iterator(const json_iterator &other) noexcept = default;
70589
  simdjson_inline json_iterator &operator=(const json_iterator &other) noexcept = default;
70590
  /**
70591
   * Skips a JSON value, whether it is a scalar, array or object.
70592
   */
70593
  simdjson_warn_unused simdjson_inline error_code skip_child(depth_t parent_depth) noexcept;
70594
70595
  /**
70596
   * Tell whether the iterator is still at the start
70597
   */
70598
  simdjson_inline bool at_root() const noexcept;
70599
70600
  /**
70601
   * Tell whether we should be expected to run in streaming
70602
   * mode (iterating over many documents). It is pure metadata
70603
   * that does not affect how the iterator works. It is used by
70604
   * start_root_array() and start_root_object().
70605
   */
70606
  simdjson_inline bool streaming() const noexcept;
70607
70608
  /**
70609
   * Get the root value iterator
70610
   */
70611
  simdjson_inline token_position root_position() const noexcept;
70612
  /**
70613
   * Assert that we are at the document depth (== 1)
70614
   */
70615
  simdjson_inline void assert_at_document_depth() const noexcept;
70616
  /**
70617
   * Assert that we are at the root of the document
70618
   */
70619
  simdjson_inline void assert_at_root() const noexcept;
70620
70621
  /**
70622
   * Tell whether the iterator is at the EOF mark
70623
   */
70624
  simdjson_inline bool at_end() const noexcept;
70625
70626
  /**
70627
   * Tell whether the iterator is live (has not been moved).
70628
   */
70629
  simdjson_inline bool is_alive() const noexcept;
70630
70631
  /**
70632
   * Abandon this iterator, setting depth to 0 (as if the document is finished).
70633
   */
70634
  simdjson_inline void abandon() noexcept;
70635
70636
  /**
70637
   * Advance the current token without modifying depth.
70638
   */
70639
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
70640
70641
  /**
70642
   * Returns true if there is a single token in the index (i.e., it is
70643
   * a JSON with a scalar value such as a single number).
70644
   *
70645
   * @return whether there is a single token
70646
   */
70647
  simdjson_inline bool is_single_token() const noexcept;
70648
70649
  /**
70650
   * Assert that there are at least the given number of tokens left.
70651
   *
70652
   * Has no effect in release builds.
70653
   */
70654
  simdjson_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
70655
  /**
70656
   * Assert that the given position addresses an actual token (is within bounds).
70657
   *
70658
   * Has no effect in release builds.
70659
   */
70660
  simdjson_inline void assert_valid_position(token_position position) const noexcept;
70661
  /**
70662
   * Get the JSON text for a given token (relative).
70663
   *
70664
   * This is not null-terminated; it is a view into the JSON.
70665
   *
70666
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
70667
   *
70668
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
70669
   * it is not used ...
70670
   */
70671
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
70672
  /**
70673
   * Get the maximum length of the JSON text for the current token (or relative).
70674
   *
70675
   * The length will include any whitespace at the end of the token.
70676
   *
70677
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
70678
   */
70679
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
70680
  /**
70681
   * Get a pointer to the current location in the input buffer.
70682
   *
70683
   * This is not null-terminated; it is a view into the JSON.
70684
   *
70685
   * You may be pointing outside of the input buffer: it is not generally
70686
   * safe to dereference this pointer.
70687
   */
70688
  simdjson_inline const uint8_t *unsafe_pointer() const noexcept;
70689
  /**
70690
   * Get the JSON text for a given token.
70691
   *
70692
   * This is not null-terminated; it is a view into the JSON.
70693
   *
70694
   * @param position The position of the token to retrieve.
70695
   *
70696
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
70697
   * it is not used ...
70698
   */
70699
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
70700
  /**
70701
   * Get the maximum length of the JSON text for the current token (or relative).
70702
   *
70703
   * The length will include any whitespace at the end of the token.
70704
   *
70705
   * @param position The position of the token to retrieve.
70706
   */
70707
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
70708
  /**
70709
   * Get the maximum length of the JSON text for the current root token.
70710
   *
70711
   * The length will include any whitespace at the end of the token.
70712
   *
70713
   * @param position The position of the token to retrieve.
70714
   */
70715
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
70716
  /**
70717
   * Get the JSON text for the last token in the document.
70718
   *
70719
   * This is not null-terminated; it is a view into the JSON.
70720
   *
70721
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
70722
   * it is not used ...
70723
   */
70724
  simdjson_inline const uint8_t *peek_last() const noexcept;
70725
70726
  /**
70727
   * Ascend one level.
70728
   *
70729
   * Validates that the depth - 1 == parent_depth.
70730
   *
70731
   * @param parent_depth the expected parent depth.
70732
   */
70733
  simdjson_inline void ascend_to(depth_t parent_depth) noexcept;
70734
70735
  /**
70736
   * Descend one level.
70737
   *
70738
   * Validates that the new depth == child_depth.
70739
   *
70740
   * @param child_depth the expected child depth.
70741
   */
70742
  simdjson_inline void descend_to(depth_t child_depth) noexcept;
70743
  simdjson_inline void descend_to(depth_t child_depth, int32_t delta) noexcept;
70744
70745
  /**
70746
   * Get current depth.
70747
   */
70748
  simdjson_inline depth_t depth() const noexcept;
70749
70750
  /**
70751
   * Get current (writeable) location in the string buffer.
70752
   */
70753
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
70754
70755
  /**
70756
   * Report an unrecoverable error, preventing further iteration.
70757
   *
70758
   * @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
70759
   * @param message An error message to report with the error.
70760
   */
70761
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
70762
70763
  /**
70764
   * Log error, but don't stop iteration.
70765
   * @param error The error to report. Must be INCORRECT_TYPE, or NO_SUCH_FIELD.
70766
   * @param message An error message to report with the error.
70767
   */
70768
  simdjson_inline error_code optional_error(error_code error, const char *message) noexcept;
70769
70770
  /**
70771
   * Take an input in json containing max_len characters and attempt to copy it over to tmpbuf, a buffer with
70772
   * N bytes of capacity. It will return false if N is too small (smaller than max_len) of if it is zero.
70773
   * The buffer (tmpbuf) is padded with space characters.
70774
   */
70775
  simdjson_warn_unused simdjson_inline bool copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept;
70776
70777
  simdjson_inline token_position position() const noexcept;
70778
  /**
70779
   * Write the raw_json_string to the string buffer and return a string_view.
70780
   * Each raw_json_string should be unescaped once, or else the string buffer might
70781
   * overflow.
70782
   */
70783
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
70784
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
70785
70786
  simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
70787
70788
  simdjson_inline error_code consume_character(char c) noexcept;
70789
#if SIMDJSON_DEVELOPMENT_CHECKS
70790
  simdjson_inline token_position start_position(depth_t depth) const noexcept;
70791
  simdjson_inline void set_start_position(depth_t depth, token_position position) noexcept;
70792
#endif
70793
70794
  /* Useful for debugging and logging purposes. */
70795
  inline std::string to_string() const noexcept;
70796
70797
  /**
70798
   * Returns the current location in the document if in bounds.
70799
   */
70800
  inline simdjson_result<const char *> current_location() const noexcept;
70801
70802
  /**
70803
   * Updates this json iterator so that it is back at the beginning of the document,
70804
   * as if it had just been created.
70805
   */
70806
  inline void rewind() noexcept;
70807
  /**
70808
   * This checks whether the {,},[,] are balanced so that the document
70809
   * ends with proper zero depth. This requires scanning the whole document
70810
   * and it may be expensive. It is expected that it will be rarely called.
70811
   * It does not attempt to match { with } and [ with ].
70812
   */
70813
  inline bool balanced() const noexcept;
70814
protected:
70815
  simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
70816
  /// The last token before the end
70817
  simdjson_inline token_position last_position() const noexcept;
70818
  /// The token *at* the end. This points at gibberish and should only be used for comparison.
70819
  simdjson_inline token_position end_position() const noexcept;
70820
  /// The end of the buffer.
70821
  simdjson_inline token_position end() const noexcept;
70822
70823
  friend class document;
70824
  friend class document_stream;
70825
  friend class object;
70826
  friend class array;
70827
  friend class value;
70828
  friend class raw_json_string;
70829
  friend class parser;
70830
  friend class value_iterator;
70831
  friend class field;
70832
  template <typename... Args>
70833
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
70834
  template <typename... Args>
70835
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
70836
}; // json_iterator
70837
70838
} // namespace ondemand
70839
} // namespace ppc64
70840
} // namespace simdjson
70841
70842
namespace simdjson {
70843
70844
template<>
70845
struct simdjson_result<ppc64::ondemand::json_iterator> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::json_iterator> {
70846
public:
70847
  simdjson_inline simdjson_result(ppc64::ondemand::json_iterator &&value) noexcept; ///< @private
70848
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
70849
70850
  simdjson_inline simdjson_result() noexcept = default;
70851
};
70852
70853
} // namespace simdjson
70854
70855
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
70856
/* end file simdjson/generic/ondemand/json_iterator.h for ppc64 */
70857
/* including simdjson/generic/ondemand/json_type.h for ppc64: #include "simdjson/generic/ondemand/json_type.h" */
70858
/* begin file simdjson/generic/ondemand/json_type.h for ppc64 */
70859
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
70860
70861
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
70862
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H */
70863
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
70864
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
70865
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
70866
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
70867
70868
namespace simdjson {
70869
namespace ppc64 {
70870
namespace ondemand {
70871
70872
/**
70873
 * The type of a JSON value.
70874
 */
70875
enum class json_type {
70876
    // Start at 1 to catch uninitialized / default values more easily
70877
    array=1, ///< A JSON array   ( [ 1, 2, 3 ... ] )
70878
    object,  ///< A JSON object  ( { "a": 1, "b" 2, ... } )
70879
    number,  ///< A JSON number  ( 1 or -2.3 or 4.5e6 ...)
70880
    string,  ///< A JSON string  ( "a" or "hello world\n" ...)
70881
    boolean, ///< A JSON boolean (true or false)
70882
    null     ///< A JSON null    (null)
70883
};
70884
70885
/**
70886
 * A type representing a JSON number.
70887
 * The design of the struct is deliberately straight-forward. All
70888
 * functions return standard values with no error check.
70889
 */
70890
struct number {
70891
70892
  /**
70893
   * return the automatically determined type of
70894
   * the number: number_type::floating_point_number,
70895
   * number_type::signed_integer or number_type::unsigned_integer.
70896
   *
70897
   *    enum class number_type {
70898
   *        floating_point_number=1, /// a binary64 number
70899
   *        signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
70900
   *        unsigned_integer         /// a positive integer larger or equal to 1<<63
70901
   *    };
70902
   */
70903
  simdjson_inline ondemand::number_type get_number_type() const noexcept;
70904
  /**
70905
   * return true if the automatically determined type of
70906
   * the number is number_type::unsigned_integer.
70907
   */
70908
  simdjson_inline bool is_uint64() const noexcept;
70909
  /**
70910
   * return the value as a uint64_t, only valid if is_uint64() is true.
70911
   */
70912
  simdjson_inline uint64_t get_uint64() const noexcept;
70913
  simdjson_inline operator uint64_t() const noexcept;
70914
70915
  /**
70916
   * return true if the automatically determined type of
70917
   * the number is number_type::signed_integer.
70918
   */
70919
  simdjson_inline bool is_int64() const noexcept;
70920
  /**
70921
   * return the value as a int64_t, only valid if is_int64() is true.
70922
   */
70923
  simdjson_inline int64_t get_int64() const noexcept;
70924
  simdjson_inline operator int64_t() const noexcept;
70925
70926
70927
  /**
70928
   * return true if the automatically determined type of
70929
   * the number is number_type::floating_point_number.
70930
   */
70931
  simdjson_inline bool is_double() const noexcept;
70932
  /**
70933
   * return the value as a double, only valid if is_double() is true.
70934
   */
70935
  simdjson_inline double get_double() const noexcept;
70936
  simdjson_inline operator double() const noexcept;
70937
70938
  /**
70939
   * Convert the number to a double. Though it always succeed, the conversion
70940
   * may be lossy if the number cannot be represented exactly.
70941
   */
70942
  simdjson_inline double as_double() const noexcept;
70943
70944
70945
protected:
70946
  /**
70947
   * The next block of declaration is designed so that we can call the number parsing
70948
   * functions on a number type. They are protected and should never be used outside
70949
   * of the core simdjson library.
70950
   */
70951
  friend class value_iterator;
70952
  template<typename W>
70953
  friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
70954
  template<typename W>
70955
  friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
70956
  /** Store a signed 64-bit value to the number. */
70957
  simdjson_inline void append_s64(int64_t value) noexcept;
70958
  /** Store an unsigned 64-bit value to the number. */
70959
  simdjson_inline void append_u64(uint64_t value) noexcept;
70960
  /** Store a double value to the number. */
70961
  simdjson_inline void append_double(double value) noexcept;
70962
  /** Specifies that the value is a double, but leave it undefined. */
70963
  simdjson_inline void skip_double() noexcept;
70964
  /**
70965
   * End of friend declarations.
70966
   */
70967
70968
  /**
70969
   * Our attributes are a union type (size = 64 bits)
70970
   * followed by a type indicator.
70971
   */
70972
  union {
70973
    double floating_point_number;
70974
    int64_t signed_integer;
70975
    uint64_t unsigned_integer;
70976
  } payload{0};
70977
  number_type type{number_type::signed_integer};
70978
};
70979
70980
/**
70981
 * Write the JSON type to the output stream
70982
 *
70983
 * @param out The output stream.
70984
 * @param type The json_type.
70985
 */
70986
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
70987
70988
#if SIMDJSON_EXCEPTIONS
70989
/**
70990
 * Send JSON type to an output stream.
70991
 *
70992
 * @param out The output stream.
70993
 * @param type The json_type.
70994
 * @throw simdjson_error if the result being printed has an error. If there is an error with the
70995
 *        underlying output stream, that error will be propagated (simdjson_error will not be
70996
 *        thrown).
70997
 */
70998
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false);
70999
#endif
71000
71001
} // namespace ondemand
71002
} // namespace ppc64
71003
} // namespace simdjson
71004
71005
namespace simdjson {
71006
71007
template<>
71008
struct simdjson_result<ppc64::ondemand::json_type> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::json_type> {
71009
public:
71010
  simdjson_inline simdjson_result(ppc64::ondemand::json_type &&value) noexcept; ///< @private
71011
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
71012
  simdjson_inline simdjson_result() noexcept = default;
71013
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
71014
};
71015
71016
} // namespace simdjson
71017
71018
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
71019
/* end file simdjson/generic/ondemand/json_type.h for ppc64 */
71020
/* including simdjson/generic/ondemand/raw_json_string.h for ppc64: #include "simdjson/generic/ondemand/raw_json_string.h" */
71021
/* begin file simdjson/generic/ondemand/raw_json_string.h for ppc64 */
71022
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
71023
71024
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
71025
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H */
71026
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
71027
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
71028
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
71029
71030
namespace simdjson {
71031
namespace ppc64 {
71032
namespace ondemand {
71033
71034
/**
71035
 * A string escaped per JSON rules, terminated with quote ("). They are used to represent
71036
 * unescaped keys inside JSON documents.
71037
 *
71038
 * (In other words, a pointer to the beginning of a string, just after the start quote, inside a
71039
 * JSON file.)
71040
 *
71041
 * This class is deliberately simplistic and has little functionality. You can
71042
 * compare a raw_json_string instance with an unescaped C string, but
71043
 * that is nearly all you can do.
71044
 *
71045
 * The raw_json_string is unescaped. If you wish to write an unescaped version of it to your own
71046
 * buffer, you may do so using the parser.unescape(string, buff) method, using an ondemand::parser
71047
 * instance. Doing so requires you to have a sufficiently large buffer.
71048
 *
71049
 * The raw_json_string instances originate typically from field instance which in turn represent
71050
 * key-value pairs from object instances. From a field instance, you get the raw_json_string
71051
 * instance by calling key(). You can, if you want a more usable string_view instance, call
71052
 * the unescaped_key() method on the field instance. You may also create a raw_json_string from
71053
 * any other string value, with the value.get_raw_json_string() method. Again, you can get
71054
 * a more usable string_view instance by calling get_string().
71055
 *
71056
 */
71057
class raw_json_string {
71058
public:
71059
  /**
71060
   * Create a new invalid raw_json_string.
71061
   *
71062
   * Exists so you can declare a variable and later assign to it before use.
71063
   */
71064
  simdjson_inline raw_json_string() noexcept = default;
71065
71066
  /**
71067
   * Create a new invalid raw_json_string pointed at the given location in the JSON.
71068
   *
71069
   * The given location must be just *after* the beginning quote (") in the JSON file.
71070
   *
71071
   * It *must* be terminated by a ", and be a valid JSON string.
71072
   */
71073
  simdjson_inline raw_json_string(const uint8_t * _buf) noexcept;
71074
  /**
71075
   * Get the raw pointer to the beginning of the string in the JSON (just after the ").
71076
   *
71077
   * It is possible for this function to return a null pointer if the instance
71078
   * has outlived its existence.
71079
   */
71080
  simdjson_inline const char * raw() const noexcept;
71081
71082
  /**
71083
   * This compares the current instance to the std::string_view target: returns true if
71084
   * they are byte-by-byte equal (no escaping is done) on target.size() characters,
71085
   * and if the raw_json_string instance has a quote character at byte index target.size().
71086
   * We never read more than length + 1 bytes in the raw_json_string instance.
71087
   * If length is smaller than target.size(), this will return false.
71088
   *
71089
   * The std::string_view instance may contain any characters. However, the caller
71090
   * is responsible for setting length so that length bytes may be read in the
71091
   * raw_json_string.
71092
   *
71093
   * Performance: the comparison may be done using memcmp which may be efficient
71094
   * for long strings.
71095
   */
71096
  simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept;
71097
71098
  /**
71099
   * This compares the current instance to the std::string_view target: returns true if
71100
   * they are byte-by-byte equal (no escaping is done).
71101
   * The std::string_view instance should not contain unescaped quote characters:
71102
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
71103
   *
71104
   * Performance: the comparison is done byte-by-byte which might be inefficient for
71105
   * long strings.
71106
   *
71107
   * If target is a compile-time constant, and your compiler likes you,
71108
   * you should be able to do the following without performance penalty...
71109
   *
71110
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
71111
   *   s.unsafe_is_equal(target);
71112
   */
71113
  simdjson_inline bool unsafe_is_equal(std::string_view target) const noexcept;
71114
71115
  /**
71116
   * This compares the current instance to the C string target: returns true if
71117
   * they are byte-by-byte equal (no escaping is done).
71118
   * The provided C string should not contain an unescaped quote character:
71119
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
71120
   *
71121
   * If target is a compile-time constant, and your compiler likes you,
71122
   * you should be able to do the following without performance penalty...
71123
   *
71124
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
71125
   *   s.unsafe_is_equal(target);
71126
   */
71127
  simdjson_inline bool unsafe_is_equal(const char* target) const noexcept;
71128
71129
  /**
71130
   * This compares the current instance to the std::string_view target: returns true if
71131
   * they are byte-by-byte equal (no escaping is done).
71132
   */
71133
  simdjson_inline bool is_equal(std::string_view target) const noexcept;
71134
71135
  /**
71136
   * This compares the current instance to the C string target: returns true if
71137
   * they are byte-by-byte equal (no escaping is done).
71138
   */
71139
  simdjson_inline bool is_equal(const char* target) const noexcept;
71140
71141
  /**
71142
   * Returns true if target is free from unescaped quote. If target is known at
71143
   * compile-time, we might expect the computation to happen at compile time with
71144
   * many compilers (not all!).
71145
   */
71146
  static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
71147
  static simdjson_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
71148
71149
private:
71150
71151
71152
  /**
71153
   * This will set the inner pointer to zero, effectively making
71154
   * this instance unusable.
71155
   */
71156
  simdjson_inline void consume() noexcept { buf = nullptr; }
71157
71158
  /**
71159
   * Checks whether the inner pointer is non-null and thus usable.
71160
   */
71161
  simdjson_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
71162
71163
  /**
71164
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
71165
   * The result will be a valid UTF-8.
71166
   *
71167
   * ## IMPORTANT: string_view lifetime
71168
   *
71169
   * The string_view is only valid until the next parse() call on the parser.
71170
   *
71171
   * @param iter A json_iterator, which contains a buffer where the string will be written.
71172
   * @param allow_replacement Whether we allow replacement of invalid surrogate pairs.
71173
   */
71174
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(json_iterator &iter, bool allow_replacement) const noexcept;
71175
71176
  /**
71177
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
71178
   * The result may not be a valid UTF-8. https://simonsapin.github.io/wtf-8/
71179
   *
71180
   * ## IMPORTANT: string_view lifetime
71181
   *
71182
   * The string_view is only valid until the next parse() call on the parser.
71183
   *
71184
   * @param iter A json_iterator, which contains a buffer where the string will be written.
71185
   */
71186
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(json_iterator &iter) const noexcept;
71187
  const uint8_t * buf{};
71188
  friend class object;
71189
  friend class field;
71190
  friend class parser;
71191
  friend struct simdjson_result<raw_json_string>;
71192
};
71193
71194
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &, const raw_json_string &) noexcept;
71195
71196
/**
71197
 * Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user is responsible
71198
 * for providing a string with no unescaped quote. Note that unescaped quotes cannot be present in valid JSON strings.
71199
 */
71200
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept;
71201
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept;
71202
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept;
71203
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept;
71204
71205
71206
} // namespace ondemand
71207
} // namespace ppc64
71208
} // namespace simdjson
71209
71210
namespace simdjson {
71211
71212
template<>
71213
struct simdjson_result<ppc64::ondemand::raw_json_string> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::raw_json_string> {
71214
public:
71215
  simdjson_inline simdjson_result(ppc64::ondemand::raw_json_string &&value) noexcept; ///< @private
71216
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
71217
  simdjson_inline simdjson_result() noexcept = default;
71218
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
71219
71220
  simdjson_inline simdjson_result<const char *> raw() const noexcept;
71221
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(ppc64::ondemand::json_iterator &iter, bool allow_replacement) const noexcept;
71222
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(ppc64::ondemand::json_iterator &iter) const noexcept;
71223
};
71224
71225
} // namespace simdjson
71226
71227
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
71228
/* end file simdjson/generic/ondemand/raw_json_string.h for ppc64 */
71229
/* including simdjson/generic/ondemand/parser.h for ppc64: #include "simdjson/generic/ondemand/parser.h" */
71230
/* begin file simdjson/generic/ondemand/parser.h for ppc64 */
71231
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_H
71232
71233
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
71234
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_H */
71235
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
71236
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
71237
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
71238
71239
#include <memory>
71240
71241
namespace simdjson {
71242
namespace ppc64 {
71243
namespace ondemand {
71244
71245
/**
71246
 * The default batch size for document_stream instances for this On Demand kernel.
71247
 * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value
71248
 * in the future.
71249
 */
71250
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
71251
/**
71252
 * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
71253
 * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
71254
 * most users will want a much larger batch size.
71255
 *
71256
 * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
71257
 * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
71258
 */
71259
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
71260
71261
/**
71262
 * A JSON fragment iterator.
71263
 *
71264
 * This holds the actual iterator as well as the buffer for writing strings.
71265
 */
71266
class parser {
71267
public:
71268
  /**
71269
   * Create a JSON parser.
71270
   *
71271
   * The new parser will have zero capacity.
71272
   */
71273
  inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
71274
71275
  inline parser(parser &&other) noexcept = default;
71276
  simdjson_inline parser(const parser &other) = delete;
71277
  simdjson_inline parser &operator=(const parser &other) = delete;
71278
  simdjson_inline parser &operator=(parser &&other) noexcept = default;
71279
71280
  /** Deallocate the JSON parser. */
71281
  inline ~parser() noexcept = default;
71282
71283
  /**
71284
   * Start iterating an on-demand JSON document.
71285
   *
71286
   *   ondemand::parser parser;
71287
   *   document doc = parser.iterate(json);
71288
   *
71289
   * It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
71290
   * Otherwise the iterate method may return an error. In particular, the whole input should be
71291
   * valid: we do not attempt to tolerate incorrect content either before or after a JSON
71292
   * document. If there is a UTF-8 BOM, the parser skips it.
71293
   *
71294
   * ### IMPORTANT: Validate what you use
71295
   *
71296
   * Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
71297
   * iterate does not parse and validate the whole document.
71298
   *
71299
   * ### IMPORTANT: Buffer Lifetime
71300
   *
71301
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
71302
   * long as the document iteration.
71303
   *
71304
   * ### IMPORTANT: Document Lifetime
71305
   *
71306
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
71307
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
71308
   * you call parse() again or destroy the parser.
71309
   *
71310
   * ### REQUIRED: Buffer Padding
71311
   *
71312
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
71313
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
71314
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
71315
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
71316
   *
71317
   * @param json The JSON to parse.
71318
   * @param len The length of the JSON.
71319
   * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
71320
   *
71321
   * @return The document, or an error:
71322
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
71323
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
71324
   *           allocation fails.
71325
   *         - EMPTY if the document is all whitespace.
71326
   *         - UTF8_ERROR if the document is not valid UTF-8.
71327
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
71328
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
71329
   */
71330
  simdjson_warn_unused simdjson_result<document> iterate(padded_string_view json) & noexcept;
71331
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71332
  simdjson_warn_unused simdjson_result<document> iterate(const char *json, size_t len, size_t capacity) & noexcept;
71333
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71334
  simdjson_warn_unused simdjson_result<document> iterate(const uint8_t *json, size_t len, size_t capacity) & noexcept;
71335
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71336
  simdjson_warn_unused simdjson_result<document> iterate(std::string_view json, size_t capacity) & noexcept;
71337
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71338
  simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
71339
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71340
  simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
71341
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71342
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
71343
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71344
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
71345
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
71346
  simdjson_warn_unused simdjson_result<document> iterate(padded_string &&json) & noexcept = delete;
71347
71348
  /**
71349
   * @private
71350
   *
71351
   * Start iterating an on-demand JSON document.
71352
   *
71353
   *   ondemand::parser parser;
71354
   *   json_iterator doc = parser.iterate(json);
71355
   *
71356
   * ### IMPORTANT: Buffer Lifetime
71357
   *
71358
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
71359
   * long as the document iteration.
71360
   *
71361
   * ### IMPORTANT: Document Lifetime
71362
   *
71363
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
71364
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
71365
   * you call parse() again or destroy the parser.
71366
   *
71367
   * The ondemand::document instance holds the iterator. The document must remain in scope
71368
   * while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
71369
   *
71370
   * ### REQUIRED: Buffer Padding
71371
   *
71372
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
71373
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
71374
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
71375
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
71376
   *
71377
   * @param json The JSON to parse.
71378
   *
71379
   * @return The iterator, or an error:
71380
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
71381
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
71382
   *           allocation fails.
71383
   *         - EMPTY if the document is all whitespace.
71384
   *         - UTF8_ERROR if the document is not valid UTF-8.
71385
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
71386
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
71387
   */
71388
  simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
71389
71390
71391
  /**
71392
   * Parse a buffer containing many JSON documents.
71393
   *
71394
   *   auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
71395
   *   ondemand::parser parser;
71396
   *   ondemand::document_stream docs = parser.iterate_many(json);
71397
   *   for (auto & doc : docs) {
71398
   *     std::cout << doc["foo"] << std::endl;
71399
   *   }
71400
   *   // Prints 1 2 3
71401
   *
71402
   * No copy of the input buffer is made.
71403
   *
71404
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
71405
   *
71406
   * The caller is responsabile to ensure that the input string data remains unchanged and is
71407
   * not deleted during the loop.
71408
   *
71409
   * ### Format
71410
   *
71411
   * The buffer must contain a series of one or more JSON documents, concatenated into a single
71412
   * buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
71413
   * then starts parsing the next document at that point. (It does this with more parallelism and
71414
   * lookahead than you might think, though.)
71415
   *
71416
   * documents that consist of an object or array may omit the whitespace between them, concatenating
71417
   * with no separator. Documents that consist of a single primitive (i.e. documents that are not
71418
   * arrays or objects) MUST be separated with ASCII whitespace.
71419
   *
71420
   * The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
71421
   * If there is a UTF-8 BOM, the parser skips it.
71422
   *
71423
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
71424
   * Setting batch_size to excessively large or excessively small values may impact negatively the
71425
   * performance.
71426
   *
71427
   * ### REQUIRED: Buffer Padding
71428
   *
71429
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
71430
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
71431
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
71432
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
71433
   *
71434
   * ### Threads
71435
   *
71436
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
71437
   * hood to do some lookahead.
71438
   *
71439
   * ### Parser Capacity
71440
   *
71441
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
71442
   * to handle it (up to max_capacity).
71443
   *
71444
   * @param buf The concatenated JSON to parse.
71445
   * @param len The length of the concatenated JSON.
71446
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
71447
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
71448
   *                   parse as many documents as possible in one tight loop.
71449
   *                   Defaults to 10MB, which has been a reasonable sweet spot in our tests.
71450
   * @param allow_comma_separated (defaults on false) This allows a mode where the documents are
71451
   *                   separated by commas instead of whitespace. It comes with a performance
71452
   *                   penalty because the entire document is indexed at once (and the document must be
71453
   *                   less than 4 GB), and there is no multithreading. In this mode, the batch_size parameter
71454
   *                   is effectively ignored, as it is set to at least the document size.
71455
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
71456
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails
71457
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
71458
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
71459
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
71460
   */
71461
  inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
71462
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
71463
  inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
71464
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
71465
  inline simdjson_result<document_stream> iterate_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
71466
  inline simdjson_result<document_stream> iterate_many(const std::string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
71467
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
71468
  inline simdjson_result<document_stream> iterate_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
71469
  inline simdjson_result<document_stream> iterate_many(const padded_string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
71470
71471
  /** @private We do not want to allow implicit conversion from C string to std::string. */
71472
  simdjson_result<document_stream> iterate_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
71473
71474
  /** The capacity of this parser (the largest document it can process). */
71475
  simdjson_inline size_t capacity() const noexcept;
71476
  /** The maximum capacity of this parser (the largest document it is allowed to process). */
71477
  simdjson_inline size_t max_capacity() const noexcept;
71478
  simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
71479
  /**
71480
   * The maximum depth of this parser (the most deeply nested objects and arrays it can process).
71481
   * This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
71482
   * The document's instance current_depth() method should be used to monitor the parsing
71483
   * depth and limit it if desired.
71484
   */
71485
  simdjson_inline size_t max_depth() const noexcept;
71486
71487
  /**
71488
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
71489
   * and `max_depth` depth.
71490
   *
71491
   * The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
71492
   * The document's instance current_depth() method should be used to monitor the parsing
71493
   * depth and limit it if desired.
71494
   *
71495
   * @param capacity The new capacity.
71496
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
71497
   * @return The error, if there is one.
71498
   */
71499
  simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
71500
71501
  #ifdef SIMDJSON_THREADS_ENABLED
71502
  /**
71503
   * The parser instance can use threads when they are available to speed up some
71504
   * operations. It is enabled by default. Changing this attribute will change the
71505
   * behavior of the parser for future operations.
71506
   */
71507
  bool threaded{true};
71508
  #endif
71509
71510
  /**
71511
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
71512
   * The result must be valid UTF-8.
71513
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
71514
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
71515
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
71516
   *
71517
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
71518
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
71519
   * instead of get_raw_json_string()).
71520
   *
71521
   * ## IMPORTANT: string_view lifetime
71522
   *
71523
   * The string_view is only valid as long as the bytes in dst.
71524
   *
71525
   * @param raw_json_string input
71526
   * @param dst A pointer to a buffer at least large enough to write this string as well as
71527
   *            an additional SIMDJSON_PADDING bytes.
71528
   * @param allow_replacement Whether we allow a replacement if the input string contains unmatched surrogate pairs.
71529
   * @return A string_view pointing at the unescaped string in dst
71530
   * @error STRING_ERROR if escapes are incorrect.
71531
   */
71532
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement = false) const noexcept;
71533
71534
  /**
71535
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
71536
   * The result may not be valid UTF-8. See https://simonsapin.github.io/wtf-8/
71537
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
71538
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
71539
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
71540
   *
71541
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
71542
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
71543
   * instead of get_raw_json_string()).
71544
   *
71545
   * ## IMPORTANT: string_view lifetime
71546
   *
71547
   * The string_view is only valid as long as the bytes in dst.
71548
   *
71549
   * @param raw_json_string input
71550
   * @param dst A pointer to a buffer at least large enough to write this string as well as
71551
   *            an additional SIMDJSON_PADDING bytes.
71552
   * @return A string_view pointing at the unescaped string in dst
71553
   * @error STRING_ERROR if escapes are incorrect.
71554
   */
71555
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept;
71556
71557
private:
71558
  /** @private [for benchmarking access] The implementation to use */
71559
  std::unique_ptr<internal::dom_parser_implementation> implementation{};
71560
  size_t _capacity{0};
71561
  size_t _max_capacity;
71562
  size_t _max_depth{DEFAULT_MAX_DEPTH};
71563
  std::unique_ptr<uint8_t[]> string_buf{};
71564
#if SIMDJSON_DEVELOPMENT_CHECKS
71565
  std::unique_ptr<token_position[]> start_positions{};
71566
#endif
71567
71568
  friend class json_iterator;
71569
  friend class document_stream;
71570
};
71571
71572
} // namespace ondemand
71573
} // namespace ppc64
71574
} // namespace simdjson
71575
71576
namespace simdjson {
71577
71578
template<>
71579
struct simdjson_result<ppc64::ondemand::parser> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::parser> {
71580
public:
71581
  simdjson_inline simdjson_result(ppc64::ondemand::parser &&value) noexcept; ///< @private
71582
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
71583
  simdjson_inline simdjson_result() noexcept = default;
71584
};
71585
71586
} // namespace simdjson
71587
71588
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_H
71589
/* end file simdjson/generic/ondemand/parser.h for ppc64 */
71590
71591
// All other declarations
71592
/* including simdjson/generic/ondemand/array.h for ppc64: #include "simdjson/generic/ondemand/array.h" */
71593
/* begin file simdjson/generic/ondemand/array.h for ppc64 */
71594
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
71595
71596
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
71597
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H */
71598
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
71599
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
71600
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
71601
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
71602
71603
namespace simdjson {
71604
namespace ppc64 {
71605
namespace ondemand {
71606
71607
/**
71608
 * A forward-only JSON array.
71609
 */
71610
class array {
71611
public:
71612
  /**
71613
   * Create a new invalid array.
71614
   *
71615
   * Exists so you can declare a variable and later assign to it before use.
71616
   */
71617
  simdjson_inline array() noexcept = default;
71618
71619
  /**
71620
   * Begin array iteration.
71621
   *
71622
   * Part of the std::iterable interface.
71623
   */
71624
  simdjson_inline simdjson_result<array_iterator> begin() noexcept;
71625
  /**
71626
   * Sentinel representing the end of the array.
71627
   *
71628
   * Part of the std::iterable interface.
71629
   */
71630
  simdjson_inline simdjson_result<array_iterator> end() noexcept;
71631
  /**
71632
   * This method scans the array and counts the number of elements.
71633
   * The count_elements method should always be called before you have begun
71634
   * iterating through the array: it is expected that you are pointing at
71635
   * the beginning of the array.
71636
   * The runtime complexity is linear in the size of the array. After
71637
   * calling this function, if successful, the array is 'rewinded' at its
71638
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
71639
   * there is a missing comma), then an error is returned and it is no longer
71640
   * safe to continue.
71641
   *
71642
   * To check that an array is empty, it is more performant to use
71643
   * the is_empty() method.
71644
   */
71645
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
71646
  /**
71647
   * This method scans the beginning of the array and checks whether the
71648
   * array is empty.
71649
   * The runtime complexity is constant time. After
71650
   * calling this function, if successful, the array is 'rewinded' at its
71651
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
71652
   * there is a missing comma), then an error is returned and it is no longer
71653
   * safe to continue.
71654
   */
71655
  simdjson_inline simdjson_result<bool> is_empty() & noexcept;
71656
  /**
71657
   * Reset the iterator so that we are pointing back at the
71658
   * beginning of the array. You should still consume values only once even if you
71659
   * can iterate through the array more than once. If you unescape a string
71660
   * within the array more than once, you have unsafe code. Note that rewinding
71661
   * an array means that you may need to reparse it anew: it is not a free
71662
   * operation.
71663
   *
71664
   * @returns true if the array contains some elements (not empty)
71665
   */
71666
  inline simdjson_result<bool> reset() & noexcept;
71667
  /**
71668
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
71669
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
71670
   * as the root of its own JSON document.
71671
   *
71672
   *   ondemand::parser parser;
71673
   *   auto json = R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded;
71674
   *   auto doc = parser.iterate(json);
71675
   *   doc.at_pointer("/0/foo/a/1") == 20
71676
   *
71677
   * Note that at_pointer() called on the document automatically calls the document's rewind
71678
   * method between each call. It invalidates all previously accessed arrays, objects and values
71679
   * that have not been consumed. Yet it is not the case when calling at_pointer on an array
71680
   * instance: there is no rewind and no invalidation.
71681
   *
71682
   * You may only call at_pointer on an array after it has been created, but before it has
71683
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
71684
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
71685
   * to call at_pointer on the same array.
71686
   *
71687
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
71688
   *
71689
   * @return The value associated with the given JSON pointer, or:
71690
   *         - NO_SUCH_FIELD if a field does not exist in an object
71691
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
71692
   *         - INCORRECT_TYPE if a non-integer is used to access an array
71693
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
71694
   */
71695
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
71696
71697
  /**
71698
   * Get the value associated with the given JSONPath expression. We only support
71699
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
71700
   * names and array indices.
71701
   *
71702
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
71703
   *
71704
   * @return The value associated with the given JSONPath expression, or:
71705
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
71706
   *         - NO_SUCH_FIELD if a field does not exist in an object
71707
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
71708
   *         - INCORRECT_TYPE if a non-integer is used to access an array
71709
  */
71710
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
71711
71712
  /**
71713
   * Consumes the array and returns a string_view instance corresponding to the
71714
   * array as represented in JSON. It points inside the original document.
71715
   */
71716
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
71717
71718
  /**
71719
   * Get the value at the given index. This function has linear-time complexity.
71720
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
71721
   *
71722
   * @return The value at the given index, or:
71723
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
71724
   */
71725
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
71726
protected:
71727
  /**
71728
   * Go to the end of the array, no matter where you are right now.
71729
   */
71730
  simdjson_inline error_code consume() noexcept;
71731
71732
  /**
71733
   * Begin array iteration.
71734
   *
71735
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
71736
   *        resulting array.
71737
   * @error INCORRECT_TYPE if the iterator is not at [.
71738
   */
71739
  static simdjson_inline simdjson_result<array> start(value_iterator &iter) noexcept;
71740
  /**
71741
   * Begin array iteration from the root.
71742
   *
71743
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
71744
   *        resulting array.
71745
   * @error INCORRECT_TYPE if the iterator is not at [.
71746
   * @error TAPE_ERROR if there is no closing ] at the end of the document.
71747
   */
71748
  static simdjson_inline simdjson_result<array> start_root(value_iterator &iter) noexcept;
71749
  /**
71750
   * Begin array iteration.
71751
   *
71752
   * This version of the method should be called after the initial [ has been verified, and is
71753
   * intended for use by switch statements that check the type of a value.
71754
   *
71755
   * @param iter The iterator. Must be after the initial [. Will be *moved* into the resulting array.
71756
   */
71757
  static simdjson_inline simdjson_result<array> started(value_iterator &iter) noexcept;
71758
71759
  /**
71760
   * Create an array at the given Internal array creation. Call array::start() or array::started() instead of this.
71761
   *
71762
   * @param iter The iterator. Must either be at the start of the first element with iter.is_alive()
71763
   *        == true, or past the [] with is_alive() == false if the array is empty. Will be *moved*
71764
   *        into the resulting array.
71765
   */
71766
  simdjson_inline array(const value_iterator &iter) noexcept;
71767
71768
  /**
71769
   * Iterator marking current position.
71770
   *
71771
   * iter.is_alive() == false indicates iteration is complete.
71772
   */
71773
  value_iterator iter{};
71774
71775
  friend class value;
71776
  friend class document;
71777
  friend struct simdjson_result<value>;
71778
  friend struct simdjson_result<array>;
71779
  friend class array_iterator;
71780
};
71781
71782
} // namespace ondemand
71783
} // namespace ppc64
71784
} // namespace simdjson
71785
71786
namespace simdjson {
71787
71788
template<>
71789
struct simdjson_result<ppc64::ondemand::array> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::array> {
71790
public:
71791
  simdjson_inline simdjson_result(ppc64::ondemand::array &&value) noexcept; ///< @private
71792
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
71793
  simdjson_inline simdjson_result() noexcept = default;
71794
71795
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> begin() noexcept;
71796
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> end() noexcept;
71797
  inline simdjson_result<size_t> count_elements() & noexcept;
71798
  inline simdjson_result<bool> is_empty() & noexcept;
71799
  inline simdjson_result<bool> reset() & noexcept;
71800
  simdjson_inline simdjson_result<ppc64::ondemand::value> at(size_t index) noexcept;
71801
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
71802
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_path(std::string_view json_path) noexcept;
71803
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
71804
71805
};
71806
71807
} // namespace simdjson
71808
71809
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
71810
/* end file simdjson/generic/ondemand/array.h for ppc64 */
71811
/* including simdjson/generic/ondemand/array_iterator.h for ppc64: #include "simdjson/generic/ondemand/array_iterator.h" */
71812
/* begin file simdjson/generic/ondemand/array_iterator.h for ppc64 */
71813
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
71814
71815
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
71816
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H */
71817
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
71818
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
71819
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
71820
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
71821
71822
71823
namespace simdjson {
71824
namespace ppc64 {
71825
namespace ondemand {
71826
71827
/**
71828
 * A forward-only JSON array.
71829
 *
71830
 * This is an input_iterator, meaning:
71831
 * - It is forward-only
71832
 * - * must be called exactly once per element.
71833
 * - ++ must be called exactly once in between each * (*, ++, *, ++, * ...)
71834
 */
71835
class array_iterator {
71836
public:
71837
  /** Create a new, invalid array iterator. */
71838
  simdjson_inline array_iterator() noexcept = default;
71839
71840
  //
71841
  // Iterator interface
71842
  //
71843
71844
  /**
71845
   * Get the current element.
71846
   *
71847
   * Part of the std::iterator interface.
71848
   */
71849
  simdjson_inline simdjson_result<value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
71850
  /**
71851
   * Check if we are at the end of the JSON.
71852
   *
71853
   * Part of the std::iterator interface.
71854
   *
71855
   * @return true if there are no more elements in the JSON array.
71856
   */
71857
  simdjson_inline bool operator==(const array_iterator &) const noexcept;
71858
  /**
71859
   * Check if there are more elements in the JSON array.
71860
   *
71861
   * Part of the std::iterator interface.
71862
   *
71863
   * @return true if there are more elements in the JSON array.
71864
   */
71865
  simdjson_inline bool operator!=(const array_iterator &) const noexcept;
71866
  /**
71867
   * Move to the next element.
71868
   *
71869
   * Part of the std::iterator interface.
71870
   */
71871
  simdjson_inline array_iterator &operator++() noexcept;
71872
71873
private:
71874
  value_iterator iter{};
71875
71876
  simdjson_inline array_iterator(const value_iterator &iter) noexcept;
71877
71878
  friend class array;
71879
  friend class value;
71880
  friend struct simdjson_result<array_iterator>;
71881
};
71882
71883
} // namespace ondemand
71884
} // namespace ppc64
71885
} // namespace simdjson
71886
71887
namespace simdjson {
71888
71889
template<>
71890
struct simdjson_result<ppc64::ondemand::array_iterator> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::array_iterator> {
71891
public:
71892
  simdjson_inline simdjson_result(ppc64::ondemand::array_iterator &&value) noexcept; ///< @private
71893
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
71894
  simdjson_inline simdjson_result() noexcept = default;
71895
71896
  //
71897
  // Iterator interface
71898
  //
71899
71900
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
71901
  simdjson_inline bool operator==(const simdjson_result<ppc64::ondemand::array_iterator> &) const noexcept;
71902
  simdjson_inline bool operator!=(const simdjson_result<ppc64::ondemand::array_iterator> &) const noexcept;
71903
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> &operator++() noexcept;
71904
};
71905
71906
} // namespace simdjson
71907
71908
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
71909
/* end file simdjson/generic/ondemand/array_iterator.h for ppc64 */
71910
/* including simdjson/generic/ondemand/document.h for ppc64: #include "simdjson/generic/ondemand/document.h" */
71911
/* begin file simdjson/generic/ondemand/document.h for ppc64 */
71912
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
71913
71914
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
71915
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */
71916
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
71917
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
71918
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
71919
71920
namespace simdjson {
71921
namespace ppc64 {
71922
namespace ondemand {
71923
71924
/**
71925
 * A JSON document. It holds a json_iterator instance.
71926
 *
71927
 * Used by tokens to get text, and string buffer location.
71928
 *
71929
 * You must keep the document around during iteration.
71930
 */
71931
class document {
71932
public:
71933
  /**
71934
   * Create a new invalid document.
71935
   *
71936
   * Exists so you can declare a variable and later assign to it before use.
71937
   */
71938
  simdjson_inline document() noexcept = default;
71939
  simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
71940
  simdjson_inline document(document &&other) noexcept = default;
71941
  simdjson_inline document &operator=(const document &other) noexcept = delete;
71942
  simdjson_inline document &operator=(document &&other) noexcept = default;
71943
71944
  /**
71945
   * Cast this JSON value to an array.
71946
   *
71947
   * @returns An object that can be used to iterate the array.
71948
   * @returns INCORRECT_TYPE If the JSON value is not an array.
71949
   */
71950
  simdjson_inline simdjson_result<array> get_array() & noexcept;
71951
  /**
71952
   * Cast this JSON value to an object.
71953
   *
71954
   * @returns An object that can be used to look up or iterate fields.
71955
   * @returns INCORRECT_TYPE If the JSON value is not an object.
71956
   */
71957
  simdjson_inline simdjson_result<object> get_object() & noexcept;
71958
  /**
71959
   * Cast this JSON value to an unsigned integer.
71960
   *
71961
   * @returns A signed 64-bit integer.
71962
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
71963
   */
71964
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
71965
  /**
71966
   * Cast this JSON value (inside string) to an unsigned integer.
71967
   *
71968
   * @returns A signed 64-bit integer.
71969
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
71970
   */
71971
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
71972
  /**
71973
   * Cast this JSON value to a signed integer.
71974
   *
71975
   * @returns A signed 64-bit integer.
71976
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
71977
   */
71978
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
71979
  /**
71980
   * Cast this JSON value (inside string) to a signed integer.
71981
   *
71982
   * @returns A signed 64-bit integer.
71983
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
71984
   */
71985
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
71986
  /**
71987
   * Cast this JSON value to a double.
71988
   *
71989
   * @returns A double.
71990
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
71991
   */
71992
  simdjson_inline simdjson_result<double> get_double() noexcept;
71993
71994
  /**
71995
   * Cast this JSON value (inside string) to a double.
71996
   *
71997
   * @returns A double.
71998
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
71999
   */
72000
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
72001
  /**
72002
   * Cast this JSON value to a string.
72003
   *
72004
   * The string is guaranteed to be valid UTF-8.
72005
   *
72006
   * Important: Calling get_string() twice on the same document is an error.
72007
   *
72008
   * @param Whether to allow a replacement character for unmatched surrogate pairs.
72009
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
72010
   *          time it parses a document or when it is destroyed.
72011
   * @returns INCORRECT_TYPE if the JSON value is not a string.
72012
   */
72013
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
72014
  /**
72015
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
72016
   *
72017
   * The string is guaranteed to be valid UTF-8.
72018
   *
72019
   * Important: a value should be consumed once. Calling get_string() twice on the same value
72020
   * is an error.
72021
   *
72022
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
72023
   * We recommend you avoid allocating an std::string unless you need to.
72024
   *
72025
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
72026
   */
72027
  template <typename string_type>
72028
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
72029
  /**
72030
   * Cast this JSON value to a string.
72031
   *
72032
   * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/
72033
   *
72034
   * Important: Calling get_wobbly_string() twice on the same document is an error.
72035
   *
72036
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
72037
   *          time it parses a document or when it is destroyed.
72038
   * @returns INCORRECT_TYPE if the JSON value is not a string.
72039
   */
72040
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
72041
  /**
72042
   * Cast this JSON value to a raw_json_string.
72043
   *
72044
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
72045
   *
72046
   * @returns A pointer to the raw JSON for the given string.
72047
   * @returns INCORRECT_TYPE if the JSON value is not a string.
72048
   */
72049
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
72050
  /**
72051
   * Cast this JSON value to a bool.
72052
   *
72053
   * @returns A bool value.
72054
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
72055
   */
72056
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
72057
  /**
72058
   * Cast this JSON value to a value when the document is an object or an array.
72059
   *
72060
   * You must not have begun iterating through the object or array. When
72061
   * SIMDJSON_DEVELOPMENT_CHECKS is set to 1 (which is the case when building in Debug mode
72062
   * by default), and you have already begun iterating,
72063
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
72064
   * rewind() to reset the document to its initial state before calling this method.
72065
   *
72066
   * @returns A value if a JSON array or object cannot be found.
72067
   * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
72068
   */
72069
  simdjson_inline simdjson_result<value> get_value() noexcept;
72070
72071
  /**
72072
   * Checks if this JSON value is null.  If and only if the value is
72073
   * null, then it is consumed (we advance). If we find a token that
72074
   * begins with 'n' but is not 'null', then an error is returned.
72075
   *
72076
   * @returns Whether the value is null.
72077
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
72078
   */
72079
  simdjson_inline simdjson_result<bool> is_null() noexcept;
72080
72081
  /**
72082
   * Get this value as the given type.
72083
   *
72084
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
72085
   *
72086
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
72087
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
72088
   *
72089
   * @returns A value of the given type, parsed from the JSON.
72090
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
72091
   */
72092
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
72093
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
72094
    // immediately fail.
72095
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
72096
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
72097
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
72098
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
72099
      " You may also add support for custom types, see our documentation.");
72100
  }
72101
  /** @overload template<typename T> simdjson_result<T> get() & noexcept */
72102
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
72103
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
72104
    // immediately fail.
72105
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
72106
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
72107
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
72108
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
72109
      " You may also add support for custom types, see our documentation.");
72110
  }
72111
72112
  /**
72113
   * Get this value as the given type.
72114
   *
72115
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
72116
   *
72117
   * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
72118
   *
72119
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
72120
   * @returns INCORRECT_TYPE If the JSON value is not an object.
72121
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
72122
   */
72123
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
72124
  /** @overload template<typename T> error_code get(T &out) & noexcept */
72125
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
72126
72127
#if SIMDJSON_EXCEPTIONS
72128
  /**
72129
   * Cast this JSON value to an instance of type T. The programmer is responsible for
72130
   * providing an implementation of get<T> for the type T, if T is not one of the types
72131
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.)
72132
   *
72133
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
72134
   *
72135
   * @returns An instance of type T
72136
   */
72137
  template <class T>
72138
  explicit simdjson_inline operator T() noexcept(false);
72139
  /**
72140
   * Cast this JSON value to an array.
72141
   *
72142
   * @returns An object that can be used to iterate the array.
72143
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
72144
   */
72145
  simdjson_inline operator array() & noexcept(false);
72146
  /**
72147
   * Cast this JSON value to an object.
72148
   *
72149
   * @returns An object that can be used to look up or iterate fields.
72150
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
72151
   */
72152
  simdjson_inline operator object() & noexcept(false);
72153
  /**
72154
   * Cast this JSON value to an unsigned integer.
72155
   *
72156
   * @returns A signed 64-bit integer.
72157
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
72158
   */
72159
  simdjson_inline operator uint64_t() noexcept(false);
72160
  /**
72161
   * Cast this JSON value to a signed integer.
72162
   *
72163
   * @returns A signed 64-bit integer.
72164
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
72165
   */
72166
  simdjson_inline operator int64_t() noexcept(false);
72167
  /**
72168
   * Cast this JSON value to a double.
72169
   *
72170
   * @returns A double.
72171
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
72172
   */
72173
  simdjson_inline operator double() noexcept(false);
72174
  /**
72175
   * Cast this JSON value to a string.
72176
   *
72177
   * The string is guaranteed to be valid UTF-8.
72178
   *
72179
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
72180
   *          time it parses a document or when it is destroyed.
72181
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
72182
   */
72183
  simdjson_inline operator std::string_view() noexcept(false);
72184
  /**
72185
   * Cast this JSON value to a raw_json_string.
72186
   *
72187
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
72188
   *
72189
   * @returns A pointer to the raw JSON for the given string.
72190
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
72191
   */
72192
  simdjson_inline operator raw_json_string() noexcept(false);
72193
  /**
72194
   * Cast this JSON value to a bool.
72195
   *
72196
   * @returns A bool value.
72197
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
72198
   */
72199
  simdjson_inline operator bool() noexcept(false);
72200
  /**
72201
   * Cast this JSON value to a value when the document is an object or an array.
72202
   *
72203
   * You must not have begun iterating through the object or array. When
72204
   * SIMDJSON_DEVELOPMENT_CHECKS is defined, and you have already begun iterating,
72205
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
72206
   * rewind() to reset the document to its initial state before calling this method.
72207
   *
72208
   * @returns A value value if a JSON array or object cannot be found.
72209
   * @exception SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
72210
   */
72211
  simdjson_inline operator value() noexcept(false);
72212
#endif
72213
  /**
72214
   * This method scans the array and counts the number of elements.
72215
   * The count_elements method should always be called before you have begun
72216
   * iterating through the array: it is expected that you are pointing at
72217
   * the beginning of the array.
72218
   * The runtime complexity is linear in the size of the array. After
72219
   * calling this function, if successful, the array is 'rewinded' at its
72220
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
72221
   * there is a missing comma), then an error is returned and it is no longer
72222
   * safe to continue.
72223
   */
72224
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
72225
   /**
72226
   * This method scans the object and counts the number of key-value pairs.
72227
   * The count_fields method should always be called before you have begun
72228
   * iterating through the object: it is expected that you are pointing at
72229
   * the beginning of the object.
72230
   * The runtime complexity is linear in the size of the object. After
72231
   * calling this function, if successful, the object is 'rewinded' at its
72232
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
72233
   * there is a missing comma), then an error is returned and it is no longer
72234
   * safe to continue.
72235
   *
72236
   * To check that an object is empty, it is more performant to use
72237
   * the is_empty() method.
72238
   */
72239
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
72240
  /**
72241
   * Get the value at the given index in the array. This function has linear-time complexity.
72242
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
72243
   *
72244
   * @return The value at the given index, or:
72245
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
72246
   */
72247
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
72248
  /**
72249
   * Begin array iteration.
72250
   *
72251
   * Part of the std::iterable interface.
72252
   */
72253
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
72254
  /**
72255
   * Sentinel representing the end of the array.
72256
   *
72257
   * Part of the std::iterable interface.
72258
   */
72259
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
72260
72261
  /**
72262
   * Look up a field by name on an object (order-sensitive).
72263
   *
72264
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
72265
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
72266
   *
72267
   * ```c++
72268
   * simdjson::ondemand::parser parser;
72269
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
72270
   * double z = obj.find_field("z");
72271
   * double y = obj.find_field("y");
72272
   * double x = obj.find_field("x");
72273
   * ```
72274
   *
72275
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
72276
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
72277
   *
72278
   *
72279
   * You must consume the fields on an object one at a time. A request for a new key
72280
   * invalidates previous field values: it makes them unsafe. E.g., the array
72281
   * given by content["bids"].get_array() should not be accessed after you have called
72282
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
72283
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
72284
   * OUT_OF_ORDER_ITERATION error is generated.
72285
   *
72286
   * You are expected to access keys only once. You should access the value corresponding to
72287
   * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
72288
   * is an error.
72289
   *
72290
   * @param key The key to look up.
72291
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
72292
   */
72293
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
72294
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
72295
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
72296
72297
  /**
72298
   * Look up a field by name on an object, without regard to key order.
72299
   *
72300
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
72301
   * and often appears negligible. It starts out normally, starting out at the last field; but if
72302
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
72303
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
72304
   * in question is large. The fact that the extra code is there also bumps the executable size.
72305
   *
72306
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
72307
   * default behavior failed to look up a field just because it was in the wrong order--and many
72308
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
72309
   *
72310
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
72311
   * field was not there when they are not in order).
72312
   *
72313
   * You must consume the fields on an object one at a time. A request for a new key
72314
   * invalidates previous field values: it makes them unsafe. E.g., the array
72315
   * given by content["bids"].get_array() should not be accessed after you have called
72316
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
72317
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
72318
   * OUT_OF_ORDER_ITERATION error is generated.
72319
   *
72320
   * You are expected to access keys only once. You should access the value corresponding to a key
72321
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
72322
   * is an error.
72323
   *
72324
   * @param key The key to look up.
72325
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
72326
   */
72327
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
72328
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
72329
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
72330
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
72331
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
72332
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
72333
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
72334
72335
  /**
72336
   * Get the type of this JSON value. It does not validate or consume the value.
72337
   * E.g., you must still call "is_null()" to check that a value is null even if
72338
   * "type()" returns json_type::null.
72339
   *
72340
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
72341
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
72342
   * let it throw an exception).
72343
   *
72344
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
72345
   */
72346
  simdjson_inline simdjson_result<json_type> type() noexcept;
72347
72348
  /**
72349
   * Checks whether the document is a scalar (string, number, null, Boolean).
72350
   * Returns false when there it is an array or object.
72351
   *
72352
   * @returns true if the type is string, number, null, Boolean
72353
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
72354
   */
72355
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
72356
72357
  /**
72358
   * Checks whether the document is a string.
72359
   *
72360
   * @returns true if the type is string
72361
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
72362
   */
72363
  simdjson_inline simdjson_result<bool> is_string() noexcept;
72364
72365
  /**
72366
   * Checks whether the document is a negative number.
72367
   *
72368
   * @returns true if the number if negative.
72369
   */
72370
  simdjson_inline bool is_negative() noexcept;
72371
  /**
72372
   * Checks whether the document is an integer number. Note that
72373
   * this requires to partially parse the number string. If
72374
   * the value is determined to be an integer, it may still
72375
   * not parse properly as an integer in subsequent steps
72376
   * (e.g., it might overflow).
72377
   *
72378
   * @returns true if the number if negative.
72379
   */
72380
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
72381
  /**
72382
   * Determine the number type (integer or floating-point number) as quickly
72383
   * as possible. This function does not fully validate the input. It is
72384
   * useful when you only need to classify the numbers, without parsing them.
72385
   *
72386
   * If you are planning to retrieve the value or you need full validation,
72387
   * consider using the get_number() method instead: it will fully parse
72388
   * and validate the input, and give you access to the type:
72389
   * get_number().get_number_type().
72390
   *
72391
   * get_number_type() is number_type::unsigned_integer if we have
72392
   * an integer greater or equal to 9223372036854775808 and no larger than 18446744073709551615.
72393
   * get_number_type() is number_type::signed_integer if we have an
72394
   * integer that is less than 9223372036854775808 and greater or equal to -9223372036854775808.
72395
   * get_number_type() is number_type::big_integer if we have an integer outside
72396
   * of those ranges (either larger than 18446744073709551615 or smaller than -9223372036854775808).
72397
   * Otherwise, get_number_type() has value number_type::floating_point_number
72398
   *
72399
   * This function requires processing the number string, but it is expected
72400
   * to be faster than get_number().get_number_type() because it is does not
72401
   * parse the number value.
72402
   *
72403
   * @returns the type of the number
72404
   */
72405
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
72406
72407
  /**
72408
   * Attempt to parse an ondemand::number. An ondemand::number may
72409
   * contain an integer value or a floating-point value, the simdjson
72410
   * library will autodetect the type. Thus it is a dynamically typed
72411
   * number. Before accessing the value, you must determine the detected
72412
   * type.
72413
   *
72414
   * number.get_number_type() is number_type::signed_integer if we have
72415
   * an integer in [-9223372036854775808,9223372036854775808)
72416
   * You can recover the value by calling number.get_int64() and you
72417
   * have that number.is_int64() is true.
72418
   *
72419
   * number.get_number_type() is number_type::unsigned_integer if we have
72420
   * an integer in [9223372036854775808,18446744073709551616)
72421
   * You can recover the value by calling number.get_uint64() and you
72422
   * have that number.is_uint64() is true.
72423
   *
72424
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
72425
   * and we have a binary64 number.
72426
   * You can recover the value by calling number.get_double() and you
72427
   * have that number.is_double() is true.
72428
   *
72429
   * You must check the type before accessing the value: it is an error
72430
   * to call "get_int64()" when number.get_number_type() is not
72431
   * number_type::signed_integer and when number.is_int64() is false.
72432
   */
72433
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
72434
72435
  /**
72436
   * Get the raw JSON for this token.
72437
   *
72438
   * The string_view will always point into the input buffer.
72439
   *
72440
   * The string_view will start at the beginning of the token, and include the entire token
72441
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
72442
   * string token always begins with a " and is always terminated by the final ", possibly
72443
   * followed by a number of spaces.
72444
   *
72445
   * The string_view is *not* null-terminated. If this is a scalar (string, number,
72446
   * boolean, or null), the character after the end of the string_view may be the padded buffer.
72447
   *
72448
   * Tokens include:
72449
   * - {
72450
   * - [
72451
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
72452
   * - -1.2e-100
72453
   * - true
72454
   * - false
72455
   * - null
72456
   */
72457
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
72458
72459
  /**
72460
   * Reset the iterator inside the document instance so we are pointing back at the
72461
   * beginning of the document, as if it had just been created. It invalidates all
72462
   * values, objects and arrays that you have created so far (including unescaped strings).
72463
   */
72464
  inline void rewind() noexcept;
72465
  /**
72466
   * Returns debugging information.
72467
   */
72468
  inline std::string to_debug_string() noexcept;
72469
  /**
72470
   * Some unrecoverable error conditions may render the document instance unusable.
72471
   * The is_alive() method returns true when the document is still suitable.
72472
   */
72473
  inline bool is_alive() noexcept;
72474
72475
  /**
72476
   * Returns the current location in the document if in bounds.
72477
   */
72478
  inline simdjson_result<const char *> current_location() const noexcept;
72479
72480
  /**
72481
   * Returns true if this document has been fully parsed.
72482
   * If you have consumed the whole document and at_end() returns
72483
   * false, then there may be trailing content.
72484
   */
72485
  inline bool at_end() const noexcept;
72486
72487
  /**
72488
   * Returns the current depth in the document if in bounds.
72489
   *
72490
   * E.g.,
72491
   *  0 = finished with document
72492
   *  1 = document root value (could be [ or {, not yet known)
72493
   *  2 = , or } inside root array/object
72494
   *  3 = key or value inside root array/object.
72495
   */
72496
  simdjson_inline int32_t current_depth() const noexcept;
72497
72498
  /**
72499
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
72500
   * https://tools.ietf.org/html/rfc6901 standard.
72501
   *
72502
   *   ondemand::parser parser;
72503
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
72504
   *   auto doc = parser.iterate(json);
72505
   *   doc.at_pointer("/foo/a/1") == 20
72506
   *
72507
   * It is allowed for a key to be the empty string:
72508
   *
72509
   *   ondemand::parser parser;
72510
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
72511
   *   auto doc = parser.iterate(json);
72512
   *   doc.at_pointer("//a/1") == 20
72513
   *
72514
   * Key values are matched exactly, without unescaping or Unicode normalization.
72515
   * We do a byte-by-byte comparison. E.g.
72516
   *
72517
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
72518
   *   auto doc = parser.iterate(json);
72519
   *   doc.at_pointer("/\\u00E9") == 123
72520
   *   doc.at_pointer((const char*)u8"/\u00E9") returns an error (NO_SUCH_FIELD)
72521
   *
72522
   * Note that at_pointer() automatically calls rewind between each call. Thus
72523
   * all values, objects and arrays that you have created so far (including unescaped strings)
72524
   * are invalidated. After calling at_pointer, you need to consume the result: string values
72525
   * should be stored in your own variables, arrays should be decoded and stored in your own array-like
72526
   * structures and so forth.
72527
   *
72528
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
72529
   *
72530
   * @return The value associated with the given JSON pointer, or:
72531
   *         - NO_SUCH_FIELD if a field does not exist in an object
72532
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
72533
   *         - INCORRECT_TYPE if a non-integer is used to access an array
72534
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
72535
   *         - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
72536
   */
72537
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
72538
72539
  /**
72540
   * Get the value associated with the given JSONPath expression. We only support
72541
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
72542
   * names and array indices.
72543
   *
72544
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
72545
   *
72546
   * Key values are matched exactly, without unescaping or Unicode normalization.
72547
   * We do a byte-by-byte comparison. E.g.
72548
   *
72549
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
72550
   *   auto doc = parser.iterate(json);
72551
   *   doc.at_path(".\\u00E9") == 123
72552
   *   doc.at_path((const char*)u8".\u00E9") returns an error (NO_SUCH_FIELD)
72553
   *
72554
   * @return The value associated with the given JSONPath expression, or:
72555
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
72556
   *         - NO_SUCH_FIELD if a field does not exist in an object
72557
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
72558
   *         - INCORRECT_TYPE if a non-integer is used to access an array
72559
   */
72560
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
72561
72562
  /**
72563
   * Consumes the document and returns a string_view instance corresponding to the
72564
   * document as represented in JSON. It points inside the original byte array containing
72565
   * the JSON document.
72566
   */
72567
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
72568
protected:
72569
  /**
72570
   * Consumes the document.
72571
   */
72572
  simdjson_inline error_code consume() noexcept;
72573
72574
  simdjson_inline document(ondemand::json_iterator &&iter) noexcept;
72575
  simdjson_inline const uint8_t *text(uint32_t idx) const noexcept;
72576
72577
  simdjson_inline value_iterator resume_value_iterator() noexcept;
72578
  simdjson_inline value_iterator get_root_value_iterator() noexcept;
72579
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
72580
  static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept;
72581
72582
  //
72583
  // Fields
72584
  //
72585
  json_iterator iter{}; ///< Current position in the document
72586
  static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0
72587
72588
  friend class array_iterator;
72589
  friend class value;
72590
  friend class ondemand::parser;
72591
  friend class object;
72592
  friend class array;
72593
  friend class field;
72594
  friend class token;
72595
  friend class document_stream;
72596
  friend class document_reference;
72597
};
72598
72599
72600
/**
72601
 * A document_reference is a thin wrapper around a document reference instance.
72602
 */
72603
class document_reference {
72604
public:
72605
  simdjson_inline document_reference() noexcept;
72606
  simdjson_inline document_reference(document &d) noexcept;
72607
  simdjson_inline document_reference(const document_reference &other) noexcept = default;
72608
  simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default;
72609
  simdjson_inline void rewind() noexcept;
72610
  simdjson_inline simdjson_result<array> get_array() & noexcept;
72611
  simdjson_inline simdjson_result<object> get_object() & noexcept;
72612
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
72613
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
72614
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
72615
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
72616
  simdjson_inline simdjson_result<double> get_double() noexcept;
72617
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
72618
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
72619
  template <typename string_type>
72620
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
72621
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
72622
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
72623
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
72624
  simdjson_inline simdjson_result<value> get_value() noexcept;
72625
72626
  simdjson_inline simdjson_result<bool> is_null() noexcept;
72627
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
72628
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
72629
  simdjson_inline operator document&() const noexcept;
72630
#if SIMDJSON_EXCEPTIONS
72631
  template <class T>
72632
  explicit simdjson_inline operator T() noexcept(false);
72633
  simdjson_inline operator array() & noexcept(false);
72634
  simdjson_inline operator object() & noexcept(false);
72635
  simdjson_inline operator uint64_t() noexcept(false);
72636
  simdjson_inline operator int64_t() noexcept(false);
72637
  simdjson_inline operator double() noexcept(false);
72638
  simdjson_inline operator std::string_view() noexcept(false);
72639
  simdjson_inline operator raw_json_string() noexcept(false);
72640
  simdjson_inline operator bool() noexcept(false);
72641
  simdjson_inline operator value() noexcept(false);
72642
#endif
72643
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
72644
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
72645
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
72646
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
72647
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
72648
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
72649
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
72650
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
72651
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
72652
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
72653
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
72654
72655
  simdjson_inline simdjson_result<json_type> type() noexcept;
72656
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
72657
  simdjson_inline simdjson_result<bool> is_string() noexcept;
72658
72659
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
72660
  simdjson_inline int32_t current_depth() const noexcept;
72661
  simdjson_inline bool is_negative() noexcept;
72662
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
72663
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
72664
  simdjson_inline simdjson_result<number> get_number() noexcept;
72665
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
72666
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
72667
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
72668
72669
private:
72670
  document *doc{nullptr};
72671
};
72672
} // namespace ondemand
72673
} // namespace ppc64
72674
} // namespace simdjson
72675
72676
namespace simdjson {
72677
72678
template<>
72679
struct simdjson_result<ppc64::ondemand::document> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::document> {
72680
public:
72681
  simdjson_inline simdjson_result(ppc64::ondemand::document &&value) noexcept; ///< @private
72682
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
72683
  simdjson_inline simdjson_result() noexcept = default;
72684
  simdjson_inline error_code rewind() noexcept;
72685
72686
  simdjson_inline simdjson_result<ppc64::ondemand::array> get_array() & noexcept;
72687
  simdjson_inline simdjson_result<ppc64::ondemand::object> get_object() & noexcept;
72688
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
72689
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
72690
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
72691
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
72692
  simdjson_inline simdjson_result<double> get_double() noexcept;
72693
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
72694
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
72695
  template <typename string_type>
72696
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
72697
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
72698
  simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> get_raw_json_string() noexcept;
72699
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
72700
  simdjson_inline simdjson_result<ppc64::ondemand::value> get_value() noexcept;
72701
  simdjson_inline simdjson_result<bool> is_null() noexcept;
72702
72703
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
72704
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept;
72705
72706
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
72707
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
72708
#if SIMDJSON_EXCEPTIONS
72709
  template <class T, typename std::enable_if<std::is_same<T, ppc64::ondemand::document>::value == false>::type>
72710
  explicit simdjson_inline operator T() noexcept(false);
72711
  simdjson_inline operator ppc64::ondemand::array() & noexcept(false);
72712
  simdjson_inline operator ppc64::ondemand::object() & noexcept(false);
72713
  simdjson_inline operator uint64_t() noexcept(false);
72714
  simdjson_inline operator int64_t() noexcept(false);
72715
  simdjson_inline operator double() noexcept(false);
72716
  simdjson_inline operator std::string_view() noexcept(false);
72717
  simdjson_inline operator ppc64::ondemand::raw_json_string() noexcept(false);
72718
  simdjson_inline operator bool() noexcept(false);
72719
  simdjson_inline operator ppc64::ondemand::value() noexcept(false);
72720
#endif
72721
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
72722
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
72723
  simdjson_inline simdjson_result<ppc64::ondemand::value> at(size_t index) & noexcept;
72724
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> begin() & noexcept;
72725
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> end() & noexcept;
72726
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(std::string_view key) & noexcept;
72727
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(const char *key) & noexcept;
72728
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](std::string_view key) & noexcept;
72729
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](const char *key) & noexcept;
72730
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
72731
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(const char *key) & noexcept;
72732
  simdjson_inline simdjson_result<ppc64::ondemand::json_type> type() noexcept;
72733
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
72734
  simdjson_inline simdjson_result<bool> is_string() noexcept;
72735
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
72736
  simdjson_inline int32_t current_depth() const noexcept;
72737
  simdjson_inline bool at_end() const noexcept;
72738
  simdjson_inline bool is_negative() noexcept;
72739
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
72740
  simdjson_inline simdjson_result<ppc64::number_type> get_number_type() noexcept;
72741
  simdjson_inline simdjson_result<ppc64::ondemand::number> get_number() noexcept;
72742
  /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */
72743
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
72744
72745
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
72746
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_path(std::string_view json_path) noexcept;
72747
};
72748
72749
72750
} // namespace simdjson
72751
72752
72753
72754
namespace simdjson {
72755
72756
template<>
72757
struct simdjson_result<ppc64::ondemand::document_reference> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::document_reference> {
72758
public:
72759
  simdjson_inline simdjson_result(ppc64::ondemand::document_reference value, error_code error) noexcept;
72760
  simdjson_inline simdjson_result() noexcept = default;
72761
  simdjson_inline error_code rewind() noexcept;
72762
72763
  simdjson_inline simdjson_result<ppc64::ondemand::array> get_array() & noexcept;
72764
  simdjson_inline simdjson_result<ppc64::ondemand::object> get_object() & noexcept;
72765
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
72766
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
72767
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
72768
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
72769
  simdjson_inline simdjson_result<double> get_double() noexcept;
72770
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
72771
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
72772
  template <typename string_type>
72773
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
72774
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
72775
  simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> get_raw_json_string() noexcept;
72776
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
72777
  simdjson_inline simdjson_result<ppc64::ondemand::value> get_value() noexcept;
72778
  simdjson_inline simdjson_result<bool> is_null() noexcept;
72779
#if SIMDJSON_EXCEPTIONS
72780
  template <class T, typename std::enable_if<std::is_same<T, ppc64::ondemand::document_reference>::value == false>::type>
72781
  explicit simdjson_inline operator T() noexcept(false);
72782
  simdjson_inline operator ppc64::ondemand::array() & noexcept(false);
72783
  simdjson_inline operator ppc64::ondemand::object() & noexcept(false);
72784
  simdjson_inline operator uint64_t() noexcept(false);
72785
  simdjson_inline operator int64_t() noexcept(false);
72786
  simdjson_inline operator double() noexcept(false);
72787
  simdjson_inline operator std::string_view() noexcept(false);
72788
  simdjson_inline operator ppc64::ondemand::raw_json_string() noexcept(false);
72789
  simdjson_inline operator bool() noexcept(false);
72790
  simdjson_inline operator ppc64::ondemand::value() noexcept(false);
72791
#endif
72792
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
72793
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
72794
  simdjson_inline simdjson_result<ppc64::ondemand::value> at(size_t index) & noexcept;
72795
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> begin() & noexcept;
72796
  simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> end() & noexcept;
72797
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(std::string_view key) & noexcept;
72798
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(const char *key) & noexcept;
72799
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](std::string_view key) & noexcept;
72800
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](const char *key) & noexcept;
72801
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
72802
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(const char *key) & noexcept;
72803
  simdjson_inline simdjson_result<ppc64::ondemand::json_type> type() noexcept;
72804
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
72805
  simdjson_inline simdjson_result<bool> is_string() noexcept;
72806
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
72807
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
72808
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
72809
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
72810
  simdjson_inline simdjson_result<ppc64::number_type> get_number_type() noexcept;
72811
  simdjson_inline simdjson_result<ppc64::ondemand::number> get_number() noexcept;
72812
  /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */
72813
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
72814
72815
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
72816
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_path(std::string_view json_path) noexcept;
72817
};
72818
72819
72820
} // namespace simdjson
72821
72822
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
72823
/* end file simdjson/generic/ondemand/document.h for ppc64 */
72824
/* including simdjson/generic/ondemand/document_stream.h for ppc64: #include "simdjson/generic/ondemand/document_stream.h" */
72825
/* begin file simdjson/generic/ondemand/document_stream.h for ppc64 */
72826
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
72827
72828
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
72829
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H */
72830
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
72831
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
72832
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
72833
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
72834
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
72835
72836
#ifdef SIMDJSON_THREADS_ENABLED
72837
#include <thread>
72838
#include <mutex>
72839
#include <condition_variable>
72840
#endif
72841
72842
namespace simdjson {
72843
namespace ppc64 {
72844
namespace ondemand {
72845
72846
#ifdef SIMDJSON_THREADS_ENABLED
72847
/** @private Custom worker class **/
72848
struct stage1_worker {
72849
  stage1_worker() noexcept = default;
72850
  stage1_worker(const stage1_worker&) = delete;
72851
  stage1_worker(stage1_worker&&) = delete;
72852
  stage1_worker operator=(const stage1_worker&) = delete;
72853
  ~stage1_worker();
72854
  /**
72855
   * We only start the thread when it is needed, not at object construction, this may throw.
72856
   * You should only call this once.
72857
   **/
72858
  void start_thread();
72859
  /**
72860
   * Start a stage 1 job. You should first call 'run', then 'finish'.
72861
   * You must call start_thread once before.
72862
   */
72863
  void run(document_stream * ds, parser * stage1, size_t next_batch_start);
72864
  /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
72865
  void finish();
72866
72867
private:
72868
72869
  /**
72870
   * Normally, we would never stop the thread. But we do in the destructor.
72871
   * This function is only safe assuming that you are not waiting for results. You
72872
   * should have called run, then finish, and be done.
72873
   **/
72874
  void stop_thread();
72875
72876
  std::thread thread{};
72877
  /** These three variables define the work done by the thread. **/
72878
  ondemand::parser * stage1_thread_parser{};
72879
  size_t _next_batch_start{};
72880
  document_stream * owner{};
72881
  /**
72882
   * We have two state variables. This could be streamlined to one variable in the future but
72883
   * we use two for clarity.
72884
   */
72885
  bool has_work{false};
72886
  bool can_work{true};
72887
72888
  /**
72889
   * We lock using a mutex.
72890
   */
72891
  std::mutex locking_mutex{};
72892
  std::condition_variable cond_var{};
72893
72894
  friend class document_stream;
72895
};
72896
#endif  // SIMDJSON_THREADS_ENABLED
72897
72898
/**
72899
 * A forward-only stream of documents.
72900
 *
72901
 * Produced by parser::iterate_many.
72902
 *
72903
 */
72904
class document_stream {
72905
public:
72906
  /**
72907
   * Construct an uninitialized document_stream.
72908
   *
72909
   *  ```c++
72910
   *  document_stream docs;
72911
   *  auto error = parser.iterate_many(json).get(docs);
72912
   *  ```
72913
   */
72914
  simdjson_inline document_stream() noexcept;
72915
  /** Move one document_stream to another. */
72916
  simdjson_inline document_stream(document_stream &&other) noexcept = default;
72917
  /** Move one document_stream to another. */
72918
  simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
72919
72920
  simdjson_inline ~document_stream() noexcept;
72921
72922
  /**
72923
   * Returns the input size in bytes.
72924
   */
72925
  inline size_t size_in_bytes() const noexcept;
72926
72927
  /**
72928
   * After iterating through the stream, this method
72929
   * returns the number of bytes that were not parsed at the end
72930
   * of the stream. If truncated_bytes() differs from zero,
72931
   * then the input was truncated maybe because incomplete JSON
72932
   * documents were found at the end of the stream. You
72933
   * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
72934
   *
72935
   * You should only call truncated_bytes() after streaming through all
72936
   * documents, like so:
72937
   *
72938
   *   document_stream stream = parser.iterate_many(json,window);
72939
   *   for(auto & doc : stream) {
72940
   *      // do something with doc
72941
   *   }
72942
   *   size_t truncated = stream.truncated_bytes();
72943
   *
72944
   */
72945
  inline size_t truncated_bytes() const noexcept;
72946
72947
  class iterator {
72948
  public:
72949
    using value_type = simdjson_result<document>;
72950
    using reference  = simdjson_result<ondemand::document_reference>;
72951
    using pointer    = void;
72952
    using difference_type   = std::ptrdiff_t;
72953
    using iterator_category = std::input_iterator_tag;
72954
72955
    /**
72956
     * Default constructor.
72957
     */
72958
    simdjson_inline iterator() noexcept;
72959
    /**
72960
     * Get the current document (or error).
72961
     */
72962
    simdjson_inline reference operator*() noexcept;
72963
    /**
72964
     * Advance to the next document (prefix).
72965
     */
72966
    inline iterator& operator++() noexcept;
72967
    /**
72968
     * Check if we're at the end yet.
72969
     * @param other the end iterator to compare to.
72970
     */
72971
    simdjson_inline bool operator!=(const iterator &other) const noexcept;
72972
    /**
72973
     * @private
72974
     *
72975
     * Gives the current index in the input document in bytes.
72976
     *
72977
     *   document_stream stream = parser.parse_many(json,window);
72978
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
72979
     *      auto doc = *i;
72980
     *      size_t index = i.current_index();
72981
     *   }
72982
     *
72983
     * This function (current_index()) is experimental and the usage
72984
     * may change in future versions of simdjson: we find the API somewhat
72985
     * awkward and we would like to offer something friendlier.
72986
     */
72987
     simdjson_inline size_t current_index() const noexcept;
72988
72989
     /**
72990
     * @private
72991
     *
72992
     * Gives a view of the current document at the current position.
72993
     *
72994
     *   document_stream stream = parser.iterate_many(json,window);
72995
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
72996
     *      std::string_view v = i.source();
72997
     *   }
72998
     *
72999
     * The returned string_view instance is simply a map to the (unparsed)
73000
     * source string: it may thus include white-space characters and all manner
73001
     * of padding.
73002
     *
73003
     * This function (source()) is experimental and the usage
73004
     * may change in future versions of simdjson: we find the API somewhat
73005
     * awkward and we would like to offer something friendlier.
73006
     *
73007
     */
73008
     simdjson_inline std::string_view source() const noexcept;
73009
73010
    /**
73011
     * Returns error of the stream (if any).
73012
     */
73013
     inline error_code error() const noexcept;
73014
73015
  private:
73016
    simdjson_inline iterator(document_stream *s, bool finished) noexcept;
73017
    /** The document_stream we're iterating through. */
73018
    document_stream* stream;
73019
    /** Whether we're finished or not. */
73020
    bool finished;
73021
73022
    friend class document;
73023
    friend class document_stream;
73024
    friend class json_iterator;
73025
  };
73026
73027
  /**
73028
   * Start iterating the documents in the stream.
73029
   */
73030
  simdjson_inline iterator begin() noexcept;
73031
  /**
73032
   * The end of the stream, for iterator comparison purposes.
73033
   */
73034
  simdjson_inline iterator end() noexcept;
73035
73036
private:
73037
73038
  document_stream &operator=(const document_stream &) = delete; // Disallow copying
73039
  document_stream(const document_stream &other) = delete; // Disallow copying
73040
73041
  /**
73042
   * Construct a document_stream. Does not allocate or parse anything until the iterator is
73043
   * used.
73044
   *
73045
   * @param parser is a reference to the parser instance used to generate this document_stream
73046
   * @param buf is the raw byte buffer we need to process
73047
   * @param len is the length of the raw byte buffer in bytes
73048
   * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
73049
   */
73050
  simdjson_inline document_stream(
73051
    ondemand::parser &parser,
73052
    const uint8_t *buf,
73053
    size_t len,
73054
    size_t batch_size,
73055
    bool allow_comma_separated
73056
  ) noexcept;
73057
73058
  /**
73059
   * Parse the first document in the buffer. Used by begin(), to handle allocation and
73060
   * initialization.
73061
   */
73062
  inline void start() noexcept;
73063
73064
  /**
73065
   * Parse the next document found in the buffer previously given to document_stream.
73066
   *
73067
   * The content should be a valid JSON document encoded as UTF-8. If there is a
73068
   * UTF-8 BOM, the parser skips it.
73069
   *
73070
   * You do NOT need to pre-allocate a parser.  This function takes care of
73071
   * pre-allocating a capacity defined by the batch_size defined when creating the
73072
   * document_stream object.
73073
   *
73074
   * The function returns simdjson::EMPTY if there is no more data to be parsed.
73075
   *
73076
   * The function returns simdjson::SUCCESS (as integer = 0) in case of success
73077
   * and indicates that the buffer has successfully been parsed to the end.
73078
   * Every document it contained has been parsed without error.
73079
   *
73080
   * The function returns an error code from simdjson/simdjson.h in case of failure
73081
   * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
73082
   * the simdjson::error_message function converts these error codes into a string).
73083
   *
73084
   * You can also check validity by calling parser.is_valid(). The same parser can
73085
   * and should be reused for the other documents in the buffer.
73086
   */
73087
  inline void next() noexcept;
73088
73089
  /** Move the json_iterator of the document to the location of the next document in the stream. */
73090
  inline void next_document() noexcept;
73091
73092
  /** Get the next document index. */
73093
  inline size_t next_batch_start() const noexcept;
73094
73095
  /** Pass the next batch through stage 1 with the given parser. */
73096
  inline error_code run_stage1(ondemand::parser &p, size_t batch_start) noexcept;
73097
73098
  // Fields
73099
  ondemand::parser *parser;
73100
  const uint8_t *buf;
73101
  size_t len;
73102
  size_t batch_size;
73103
  bool allow_comma_separated;
73104
  /**
73105
   * We are going to use just one document instance. The document owns
73106
   * the json_iterator. It implies that we only ever pass a reference
73107
   * to the document to the users.
73108
   */
73109
  document doc{};
73110
  /** The error (or lack thereof) from the current document. */
73111
  error_code error;
73112
  size_t batch_start{0};
73113
  size_t doc_index{};
73114
73115
  #ifdef SIMDJSON_THREADS_ENABLED
73116
  /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
73117
  bool use_thread;
73118
73119
  inline void load_from_stage1_thread() noexcept;
73120
73121
  /** Start a thread to run stage 1 on the next batch. */
73122
  inline void start_stage1_thread() noexcept;
73123
73124
  /** Wait for the stage 1 thread to finish and capture the results. */
73125
  inline void finish_stage1_thread() noexcept;
73126
73127
  /** The error returned from the stage 1 thread. */
73128
  error_code stage1_thread_error{UNINITIALIZED};
73129
  /** The thread used to run stage 1 against the next batch in the background. */
73130
  std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
73131
  /**
73132
   * The parser used to run stage 1 in the background. Will be swapped
73133
   * with the regular parser when finished.
73134
   */
73135
  ondemand::parser stage1_thread_parser{};
73136
73137
  friend struct stage1_worker;
73138
  #endif // SIMDJSON_THREADS_ENABLED
73139
73140
  friend class parser;
73141
  friend class document;
73142
  friend class json_iterator;
73143
  friend struct simdjson_result<ondemand::document_stream>;
73144
  friend struct internal::simdjson_result_base<ondemand::document_stream>;
73145
};  // document_stream
73146
73147
} // namespace ondemand
73148
} // namespace ppc64
73149
} // namespace simdjson
73150
73151
namespace simdjson {
73152
template<>
73153
struct simdjson_result<ppc64::ondemand::document_stream> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::document_stream> {
73154
public:
73155
  simdjson_inline simdjson_result(ppc64::ondemand::document_stream &&value) noexcept; ///< @private
73156
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
73157
  simdjson_inline simdjson_result() noexcept = default;
73158
};
73159
73160
} // namespace simdjson
73161
73162
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
73163
/* end file simdjson/generic/ondemand/document_stream.h for ppc64 */
73164
/* including simdjson/generic/ondemand/field.h for ppc64: #include "simdjson/generic/ondemand/field.h" */
73165
/* begin file simdjson/generic/ondemand/field.h for ppc64 */
73166
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
73167
73168
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
73169
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_H */
73170
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
73171
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
73172
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
73173
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
73174
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
73175
73176
namespace simdjson {
73177
namespace ppc64 {
73178
namespace ondemand {
73179
73180
/**
73181
 * A JSON field (key/value pair) in an object.
73182
 *
73183
 * Returned from object iteration.
73184
 *
73185
 * Extends from std::pair<raw_json_string, value> so you can use C++ algorithms that rely on pairs.
73186
 */
73187
class field : public std::pair<raw_json_string, value> {
73188
public:
73189
  /**
73190
   * Create a new invalid field.
73191
   *
73192
   * Exists so you can declare a variable and later assign to it before use.
73193
   */
73194
  simdjson_inline field() noexcept;
73195
73196
  /**
73197
   * Get the key as a string_view (for higher speed, consider raw_key).
73198
   * We deliberately use a more cumbersome name (unescaped_key) to force users
73199
   * to think twice about using it.
73200
   *
73201
   * This consumes the key: once you have called unescaped_key(), you cannot
73202
   * call it again nor can you call key().
73203
   */
73204
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescaped_key(bool allow_replacement) noexcept;
73205
  /**
73206
   * Get the key as a raw_json_string. Can be used for direct comparison with
73207
   * an unescaped C string: e.g., key() == "test".
73208
   */
73209
  simdjson_inline raw_json_string key() const noexcept;
73210
  /**
73211
   * Get the unprocessed key as a string_view. This includes the quotes and may include
73212
   * some spaces after the last quote.
73213
   */
73214
  simdjson_inline std::string_view key_raw_json_token() const noexcept;
73215
  /**
73216
   * Get the field value.
73217
   */
73218
  simdjson_inline ondemand::value &value() & noexcept;
73219
  /**
73220
   * @overload ondemand::value &ondemand::value() & noexcept
73221
   */
73222
  simdjson_inline ondemand::value value() && noexcept;
73223
73224
protected:
73225
  simdjson_inline field(raw_json_string key, ondemand::value &&value) noexcept;
73226
  static simdjson_inline simdjson_result<field> start(value_iterator &parent_iter) noexcept;
73227
  static simdjson_inline simdjson_result<field> start(const value_iterator &parent_iter, raw_json_string key) noexcept;
73228
  friend struct simdjson_result<field>;
73229
  friend class object_iterator;
73230
};
73231
73232
} // namespace ondemand
73233
} // namespace ppc64
73234
} // namespace simdjson
73235
73236
namespace simdjson {
73237
73238
template<>
73239
struct simdjson_result<ppc64::ondemand::field> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::field> {
73240
public:
73241
  simdjson_inline simdjson_result(ppc64::ondemand::field &&value) noexcept; ///< @private
73242
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
73243
  simdjson_inline simdjson_result() noexcept = default;
73244
73245
  simdjson_inline simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
73246
  simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> key() noexcept;
73247
  simdjson_inline simdjson_result<std::string_view> key_raw_json_token() noexcept;
73248
  simdjson_inline simdjson_result<ppc64::ondemand::value> value() noexcept;
73249
};
73250
73251
} // namespace simdjson
73252
73253
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_H
73254
/* end file simdjson/generic/ondemand/field.h for ppc64 */
73255
/* including simdjson/generic/ondemand/object.h for ppc64: #include "simdjson/generic/ondemand/object.h" */
73256
/* begin file simdjson/generic/ondemand/object.h for ppc64 */
73257
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
73258
73259
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
73260
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_H */
73261
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
73262
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
73263
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
73264
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
73265
73266
namespace simdjson {
73267
namespace ppc64 {
73268
namespace ondemand {
73269
73270
/**
73271
 * A forward-only JSON object field iterator.
73272
 */
73273
class object {
73274
public:
73275
  /**
73276
   * Create a new invalid object.
73277
   *
73278
   * Exists so you can declare a variable and later assign to it before use.
73279
   */
73280
  simdjson_inline object() noexcept = default;
73281
73282
  simdjson_inline simdjson_result<object_iterator> begin() noexcept;
73283
  simdjson_inline simdjson_result<object_iterator> end() noexcept;
73284
  /**
73285
   * Look up a field by name on an object (order-sensitive).
73286
   *
73287
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
73288
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
73289
   *
73290
   * ```c++
73291
   * simdjson::ondemand::parser parser;
73292
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
73293
   * double z = obj.find_field("z");
73294
   * double y = obj.find_field("y");
73295
   * double x = obj.find_field("x");
73296
   * ```
73297
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
73298
   * that only one field is returned.
73299
   *
73300
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
73301
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
73302
   *
73303
   * You must consume the fields on an object one at a time. A request for a new key
73304
   * invalidates previous field values: it makes them unsafe. The value instance you get
73305
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
73306
   * given by content["bids"].get_array() should not be accessed after you have called
73307
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
73308
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
73309
   * OUT_OF_ORDER_ITERATION error is generated.
73310
   *
73311
   * You are expected to access keys only once. You should access the value corresponding to a
73312
   * key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
73313
   * is an error.
73314
   *
73315
   * @param key The key to look up.
73316
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
73317
   */
73318
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
73319
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
73320
  simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
73321
73322
  /**
73323
   * Look up a field by name on an object, without regard to key order.
73324
   *
73325
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
73326
   * and often appears negligible. It starts out normally, starting out at the last field; but if
73327
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
73328
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
73329
   * in question is large. The fact that the extra code is there also bumps the executable size.
73330
   *
73331
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
73332
   * default behavior failed to look up a field just because it was in the wrong order--and many
73333
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
73334
   *
73335
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
73336
   * field was not there when they are not in order).
73337
   *
73338
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
73339
   * that only one field is returned.
73340
   *
73341
   * You must consume the fields on an object one at a time. A request for a new key
73342
   * invalidates previous field values: it makes them unsafe. The value instance you get
73343
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
73344
   * given by content["bids"].get_array() should not be accessed after you have called
73345
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
73346
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
73347
   * OUT_OF_ORDER_ITERATION error is generated.
73348
   *
73349
   * You are expected to access keys only once. You should access the value corresponding to a key
73350
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
73351
   *
73352
   * @param key The key to look up.
73353
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
73354
   */
73355
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
73356
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
73357
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
73358
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
73359
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
73360
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
73361
  simdjson_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
73362
73363
  /**
73364
   * Get the value associated with the given JSON pointer. We use the RFC 6901
73365
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
73366
   * as the root of its own JSON document.
73367
   *
73368
   *   ondemand::parser parser;
73369
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
73370
   *   auto doc = parser.iterate(json);
73371
   *   doc.at_pointer("/foo/a/1") == 20
73372
   *
73373
   * It is allowed for a key to be the empty string:
73374
   *
73375
   *   ondemand::parser parser;
73376
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
73377
   *   auto doc = parser.iterate(json);
73378
   *   doc.at_pointer("//a/1") == 20
73379
   *
73380
   * Note that at_pointer() called on the document automatically calls the document's rewind
73381
   * method between each call. It invalidates all previously accessed arrays, objects and values
73382
   * that have not been consumed. Yet it is not the case when calling at_pointer on an object
73383
   * instance: there is no rewind and no invalidation.
73384
   *
73385
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
73386
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
73387
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
73388
   *
73389
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
73390
   *
73391
   * @return The value associated with the given JSON pointer, or:
73392
   *         - NO_SUCH_FIELD if a field does not exist in an object
73393
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
73394
   *         - INCORRECT_TYPE if a non-integer is used to access an array
73395
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
73396
   */
73397
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
73398
73399
  /**
73400
   * Get the value associated with the given JSONPath expression. We only support
73401
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
73402
   * names and array indices.
73403
   *
73404
   * @return The value associated with the given JSONPath expression, or:
73405
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
73406
   *         - NO_SUCH_FIELD if a field does not exist in an object
73407
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
73408
   *         - INCORRECT_TYPE if a non-integer is used to access an array
73409
   */
73410
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
73411
73412
  /**
73413
   * Reset the iterator so that we are pointing back at the
73414
   * beginning of the object. You should still consume values only once even if you
73415
   * can iterate through the object more than once. If you unescape a string within
73416
   * the object more than once, you have unsafe code. Note that rewinding an object
73417
   * means that you may need to reparse it anew: it is not a free operation.
73418
   *
73419
   * @returns true if the object contains some elements (not empty)
73420
   */
73421
  inline simdjson_result<bool> reset() & noexcept;
73422
  /**
73423
   * This method scans the beginning of the object and checks whether the
73424
   * object is empty.
73425
   * The runtime complexity is constant time. After
73426
   * calling this function, if successful, the object is 'rewinded' at its
73427
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
73428
   * there is a missing comma), then an error is returned and it is no longer
73429
   * safe to continue.
73430
   */
73431
  inline simdjson_result<bool> is_empty() & noexcept;
73432
  /**
73433
   * This method scans the object and counts the number of key-value pairs.
73434
   * The count_fields method should always be called before you have begun
73435
   * iterating through the object: it is expected that you are pointing at
73436
   * the beginning of the object.
73437
   * The runtime complexity is linear in the size of the object. After
73438
   * calling this function, if successful, the object is 'rewinded' at its
73439
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
73440
   * there is a missing comma), then an error is returned and it is no longer
73441
   * safe to continue.
73442
   *
73443
   * To check that an object is empty, it is more performant to use
73444
   * the is_empty() method.
73445
   *
73446
   * Performance hint: You should only call count_fields() as a last
73447
   * resort as it may require scanning the document twice or more.
73448
   */
73449
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
73450
  /**
73451
   * Consumes the object and returns a string_view instance corresponding to the
73452
   * object as represented in JSON. It points inside the original byte array containing
73453
   * the JSON document.
73454
   */
73455
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
73456
73457
protected:
73458
  /**
73459
   * Go to the end of the object, no matter where you are right now.
73460
   */
73461
  simdjson_inline error_code consume() noexcept;
73462
  static simdjson_inline simdjson_result<object> start(value_iterator &iter) noexcept;
73463
  static simdjson_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
73464
  static simdjson_inline simdjson_result<object> started(value_iterator &iter) noexcept;
73465
  static simdjson_inline object resume(const value_iterator &iter) noexcept;
73466
  simdjson_inline object(const value_iterator &iter) noexcept;
73467
73468
  simdjson_warn_unused simdjson_inline error_code find_field_raw(const std::string_view key) noexcept;
73469
73470
  value_iterator iter{};
73471
73472
  friend class value;
73473
  friend class document;
73474
  friend struct simdjson_result<object>;
73475
};
73476
73477
} // namespace ondemand
73478
} // namespace ppc64
73479
} // namespace simdjson
73480
73481
namespace simdjson {
73482
73483
template<>
73484
struct simdjson_result<ppc64::ondemand::object> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::object> {
73485
public:
73486
  simdjson_inline simdjson_result(ppc64::ondemand::object &&value) noexcept; ///< @private
73487
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
73488
  simdjson_inline simdjson_result() noexcept = default;
73489
73490
  simdjson_inline simdjson_result<ppc64::ondemand::object_iterator> begin() noexcept;
73491
  simdjson_inline simdjson_result<ppc64::ondemand::object_iterator> end() noexcept;
73492
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(std::string_view key) & noexcept;
73493
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field(std::string_view key) && noexcept;
73494
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
73495
  simdjson_inline simdjson_result<ppc64::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
73496
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](std::string_view key) & noexcept;
73497
  simdjson_inline simdjson_result<ppc64::ondemand::value> operator[](std::string_view key) && noexcept;
73498
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
73499
  simdjson_inline simdjson_result<ppc64::ondemand::value> at_path(std::string_view json_path) noexcept;
73500
73501
  inline simdjson_result<bool> reset() noexcept;
73502
  inline simdjson_result<bool> is_empty() noexcept;
73503
  inline simdjson_result<size_t> count_fields() & noexcept;
73504
  inline simdjson_result<std::string_view> raw_json() noexcept;
73505
73506
};
73507
73508
} // namespace simdjson
73509
73510
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
73511
/* end file simdjson/generic/ondemand/object.h for ppc64 */
73512
/* including simdjson/generic/ondemand/object_iterator.h for ppc64: #include "simdjson/generic/ondemand/object_iterator.h" */
73513
/* begin file simdjson/generic/ondemand/object_iterator.h for ppc64 */
73514
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
73515
73516
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
73517
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H */
73518
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
73519
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
73520
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
73521
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
73522
73523
namespace simdjson {
73524
namespace ppc64 {
73525
namespace ondemand {
73526
73527
class object_iterator {
73528
public:
73529
  /**
73530
   * Create a new invalid object_iterator.
73531
   *
73532
   * Exists so you can declare a variable and later assign to it before use.
73533
   */
73534
  simdjson_inline object_iterator() noexcept = default;
73535
73536
  //
73537
  // Iterator interface
73538
  //
73539
73540
  // Reads key and value, yielding them to the user.
73541
  // MUST ONLY BE CALLED ONCE PER ITERATION.
73542
  simdjson_inline simdjson_result<field> operator*() noexcept;
73543
  // Assumes it's being compared with the end. true if depth < iter->depth.
73544
  simdjson_inline bool operator==(const object_iterator &) const noexcept;
73545
  // Assumes it's being compared with the end. true if depth >= iter->depth.
73546
  simdjson_inline bool operator!=(const object_iterator &) const noexcept;
73547
  // Checks for ']' and ','
73548
  simdjson_inline object_iterator &operator++() noexcept;
73549
73550
private:
73551
  /**
73552
   * The underlying JSON iterator.
73553
   *
73554
   * PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
73555
   * is first used, and never changes afterwards.
73556
   */
73557
  value_iterator iter{};
73558
73559
  simdjson_inline object_iterator(const value_iterator &iter) noexcept;
73560
  friend struct simdjson_result<object_iterator>;
73561
  friend class object;
73562
};
73563
73564
} // namespace ondemand
73565
} // namespace ppc64
73566
} // namespace simdjson
73567
73568
namespace simdjson {
73569
73570
template<>
73571
struct simdjson_result<ppc64::ondemand::object_iterator> : public ppc64::implementation_simdjson_result_base<ppc64::ondemand::object_iterator> {
73572
public:
73573
  simdjson_inline simdjson_result(ppc64::ondemand::object_iterator &&value) noexcept; ///< @private
73574
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
73575
  simdjson_inline simdjson_result() noexcept = default;
73576
73577
  //
73578
  // Iterator interface
73579
  //
73580
73581
  // Reads key and value, yielding them to the user.
73582
  simdjson_inline simdjson_result<ppc64::ondemand::field> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
73583
  // Assumes it's being compared with the end. true if depth < iter->depth.
73584
  simdjson_inline bool operator==(const simdjson_result<ppc64::ondemand::object_iterator> &) const noexcept;
73585
  // Assumes it's being compared with the end. true if depth >= iter->depth.
73586
  simdjson_inline bool operator!=(const simdjson_result<ppc64::ondemand::object_iterator> &) const noexcept;
73587
  // Checks for ']' and ','
73588
  simdjson_inline simdjson_result<ppc64::ondemand::object_iterator> &operator++() noexcept;
73589
};
73590
73591
} // namespace simdjson
73592
73593
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
73594
/* end file simdjson/generic/ondemand/object_iterator.h for ppc64 */
73595
/* including simdjson/generic/ondemand/serialization.h for ppc64: #include "simdjson/generic/ondemand/serialization.h" */
73596
/* begin file simdjson/generic/ondemand/serialization.h for ppc64 */
73597
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
73598
73599
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
73600
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H */
73601
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
73602
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
73603
73604
namespace simdjson {
73605
/**
73606
 * Create a string-view instance out of a document instance. The string-view instance
73607
 * contains JSON text that is suitable to be parsed as JSON again. It does not
73608
 * validate the content.
73609
 */
73610
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::document& x) noexcept;
73611
/**
73612
 * Create a string-view instance out of a value instance. The string-view instance
73613
 * contains JSON text that is suitable to be parsed as JSON again. The value must
73614
 * not have been accessed previously. It does not
73615
 * validate the content.
73616
 */
73617
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::value& x) noexcept;
73618
/**
73619
 * Create a string-view instance out of an object instance. The string-view instance
73620
 * contains JSON text that is suitable to be parsed as JSON again. It does not
73621
 * validate the content.
73622
 */
73623
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::object& x) noexcept;
73624
/**
73625
 * Create a string-view instance out of an array instance. The string-view instance
73626
 * contains JSON text that is suitable to be parsed as JSON again. It does not
73627
 * validate the content.
73628
 */
73629
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::array& x) noexcept;
73630
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::document> x);
73631
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::value> x);
73632
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::object> x);
73633
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::array> x);
73634
} // namespace simdjson
73635
73636
/**
73637
 * We want to support argument-dependent lookup (ADL).
73638
 * Hence we should define operator<< in the namespace
73639
 * where the argument (here value, object, etc.) resides.
73640
 * Credit: @madhur4127
73641
 * See https://github.com/simdjson/simdjson/issues/1768
73642
 */
73643
namespace simdjson { namespace ppc64 { namespace ondemand {
73644
73645
/**
73646
 * Print JSON to an output stream.  It does not
73647
 * validate the content.
73648
 *
73649
 * @param out The output stream.
73650
 * @param value The element.
73651
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
73652
 */
73653
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::value x);
73654
#if SIMDJSON_EXCEPTIONS
73655
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::value> x);
73656
#endif
73657
/**
73658
 * Print JSON to an output stream. It does not
73659
 * validate the content.
73660
 *
73661
 * @param out The output stream.
73662
 * @param value The array.
73663
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
73664
 */
73665
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::array value);
73666
#if SIMDJSON_EXCEPTIONS
73667
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::array> x);
73668
#endif
73669
/**
73670
 * Print JSON to an output stream. It does not
73671
 * validate the content.
73672
 *
73673
 * @param out The output stream.
73674
 * @param value The array.
73675
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
73676
 */
73677
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::document& value);
73678
#if SIMDJSON_EXCEPTIONS
73679
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::document>&& x);
73680
#endif
73681
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::document_reference& value);
73682
#if SIMDJSON_EXCEPTIONS
73683
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::document_reference>&& x);
73684
#endif
73685
/**
73686
 * Print JSON to an output stream. It does not
73687
 * validate the content.
73688
 *
73689
 * @param out The output stream.
73690
 * @param value The object.
73691
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
73692
 */
73693
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::object value);
73694
#if SIMDJSON_EXCEPTIONS
73695
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::object> x);
73696
#endif
73697
}}} // namespace simdjson::ppc64::ondemand
73698
73699
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
73700
/* end file simdjson/generic/ondemand/serialization.h for ppc64 */
73701
73702
// Inline definitions
73703
/* including simdjson/generic/ondemand/array-inl.h for ppc64: #include "simdjson/generic/ondemand/array-inl.h" */
73704
/* begin file simdjson/generic/ondemand/array-inl.h for ppc64 */
73705
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
73706
73707
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
73708
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H */
73709
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
73710
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
73711
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator-inl.h" */
73712
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
73713
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
73714
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
73715
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
73716
73717
namespace simdjson {
73718
namespace ppc64 {
73719
namespace ondemand {
73720
73721
//
73722
// ### Live States
73723
//
73724
// While iterating or looking up values, depth >= iter->depth. at_start may vary. Error is
73725
// always SUCCESS:
73726
//
73727
// - Start: This is the state when the array is first found and the iterator is just past the `{`.
73728
//   In this state, at_start == true.
73729
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
73730
//   iterate over, the iterator is at the `,` before the next value (or `]`). In this state,
73731
//   depth == iter->depth, at_start == false, and error == SUCCESS.
73732
// - Unfinished Business: When we hand an array/object to the user which they do not fully
73733
//   iterate over, we need to finish that iteration by skipping child values until we reach the
73734
//   Next state. In this state, depth > iter->depth, at_start == false, and error == SUCCESS.
73735
//
73736
// ## Error States
73737
//
73738
// In error states, we will yield exactly one more value before stopping. iter->depth == depth
73739
// and at_start is always false. We decrement after yielding the error, moving to the Finished
73740
// state.
73741
//
73742
// - Chained Error: When the array iterator is part of an error chain--for example, in
73743
//   `for (auto tweet : doc["tweets"])`, where the tweet element may be missing or not be an
73744
//   array--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
73745
//   iter->depth == depth, and at_start == false. We decrement depth when we yield the error.
73746
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between elements,
73747
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
73748
//   error == TAPE_ERROR, iter->depth == depth, and at_start == false.
73749
//
73750
// ## Terminal State
73751
//
73752
// The terminal state has iter->depth < depth. at_start is always false.
73753
//
73754
// - Finished: When we have reached a `]` or have reported an error, we are finished. We signal this
73755
//   by decrementing depth. In this state, iter->depth < depth, at_start == false, and
73756
//   error == SUCCESS.
73757
//
73758
73759
simdjson_inline array::array(const value_iterator &_iter) noexcept
73760
  : iter{_iter}
73761
{
73762
}
73763
73764
simdjson_inline simdjson_result<array> array::start(value_iterator &iter) noexcept {
73765
  // We don't need to know if the array is empty to start iteration, but we do want to know if there
73766
  // is an error--thus `simdjson_unused`.
73767
  simdjson_unused bool has_value;
73768
  SIMDJSON_TRY( iter.start_array().get(has_value) );
73769
  return array(iter);
73770
}
73771
simdjson_inline simdjson_result<array> array::start_root(value_iterator &iter) noexcept {
73772
  simdjson_unused bool has_value;
73773
  SIMDJSON_TRY( iter.start_root_array().get(has_value) );
73774
  return array(iter);
73775
}
73776
simdjson_inline simdjson_result<array> array::started(value_iterator &iter) noexcept {
73777
  bool has_value;
73778
  SIMDJSON_TRY(iter.started_array().get(has_value));
73779
  return array(iter);
73780
}
73781
73782
simdjson_inline simdjson_result<array_iterator> array::begin() noexcept {
73783
#if SIMDJSON_DEVELOPMENT_CHECKS
73784
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
73785
#endif
73786
  return array_iterator(iter);
73787
}
73788
simdjson_inline simdjson_result<array_iterator> array::end() noexcept {
73789
  return array_iterator(iter);
73790
}
73791
simdjson_inline error_code array::consume() noexcept {
73792
  auto error = iter.json_iter().skip_child(iter.depth()-1);
73793
  if(error) { iter.abandon(); }
73794
  return error;
73795
}
73796
73797
simdjson_inline simdjson_result<std::string_view> array::raw_json() noexcept {
73798
  const uint8_t * starting_point{iter.peek_start()};
73799
  auto error = consume();
73800
  if(error) { return error; }
73801
  // After 'consume()', we could be left pointing just beyond the document, but that
73802
  // is ok because we are not going to dereference the final pointer position, we just
73803
  // use it to compute the length in bytes.
73804
  const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
73805
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
73806
}
73807
73808
SIMDJSON_PUSH_DISABLE_WARNINGS
73809
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
73810
simdjson_inline simdjson_result<size_t> array::count_elements() & noexcept {
73811
  size_t count{0};
73812
  // Important: we do not consume any of the values.
73813
  for(simdjson_unused auto v : *this) { count++; }
73814
  // The above loop will always succeed, but we want to report errors.
73815
  if(iter.error()) { return iter.error(); }
73816
  // We need to move back at the start because we expect users to iterate through
73817
  // the array after counting the number of elements.
73818
  iter.reset_array();
73819
  return count;
73820
}
73821
SIMDJSON_POP_DISABLE_WARNINGS
73822
73823
simdjson_inline simdjson_result<bool> array::is_empty() & noexcept {
73824
  bool is_not_empty;
73825
  auto error = iter.reset_array().get(is_not_empty);
73826
  if(error) { return error; }
73827
  return !is_not_empty;
73828
}
73829
73830
inline simdjson_result<bool> array::reset() & noexcept {
73831
  return iter.reset_array();
73832
}
73833
73834
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
73835
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
73836
  json_pointer = json_pointer.substr(1);
73837
  // - means "the append position" or "the element after the end of the array"
73838
  // We don't support this, because we're returning a real element, not a position.
73839
  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
73840
73841
  // Read the array index
73842
  size_t array_index = 0;
73843
  size_t i;
73844
  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
73845
    uint8_t digit = uint8_t(json_pointer[i] - '0');
73846
    // Check for non-digit in array index. If it's there, we're trying to get a field in an object
73847
    if (digit > 9) { return INCORRECT_TYPE; }
73848
    array_index = array_index*10 + digit;
73849
  }
73850
73851
  // 0 followed by other digits is invalid
73852
  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
73853
73854
  // Empty string is invalid; so is a "/" with no digits before it
73855
  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
73856
  // Get the child
73857
  auto child = at(array_index);
73858
  // If there is an error, it ends here
73859
  if(child.error()) {
73860
    return child;
73861
  }
73862
73863
  // If there is a /, we're not done yet, call recursively.
73864
  if (i < json_pointer.length()) {
73865
    child = child.at_pointer(json_pointer.substr(i));
73866
  }
73867
  return child;
73868
}
73869
73870
inline std::string json_path_to_pointer_conversion(std::string_view json_path) {
73871
  if (json_path.empty() || (json_path.front() != '.' &&
73872
      json_path.front() != '[')) {
73873
    return "-1"; // This is just a sentinel value, the caller should check for this and return an error.
73874
  }
73875
73876
  std::string result;
73877
  // Reserve space to reduce allocations, adjusting for potential increases due
73878
  // to escaping.
73879
  result.reserve(json_path.size() * 2);
73880
73881
  size_t i = 0;
73882
73883
  while (i < json_path.length()) {
73884
    if (json_path[i] == '.') {
73885
      result += '/';
73886
    } else if (json_path[i] == '[') {
73887
      result += '/';
73888
      ++i; // Move past the '['
73889
      while (i < json_path.length() && json_path[i] != ']') {
73890
          if (json_path[i] == '~') {
73891
            result += "~0";
73892
          } else if (json_path[i] == '/') {
73893
            result += "~1";
73894
          } else {
73895
            result += json_path[i];
73896
          }
73897
          ++i;
73898
      }
73899
      if (i == json_path.length() || json_path[i] != ']') {
73900
          return "-1"; // Using sentinel value that will be handled as an error by the caller.
73901
      }
73902
    } else {
73903
      if (json_path[i] == '~') {
73904
          result += "~0";
73905
      } else if (json_path[i] == '/') {
73906
          result += "~1";
73907
      } else {
73908
          result += json_path[i];
73909
      }
73910
    }
73911
    ++i;
73912
  }
73913
73914
  return result;
73915
}
73916
73917
inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept {
73918
  auto json_pointer = json_path_to_pointer_conversion(json_path);
73919
  if (json_pointer == "-1") { return INVALID_JSON_POINTER; }
73920
  return at_pointer(json_pointer);
73921
}
73922
73923
simdjson_inline simdjson_result<value> array::at(size_t index) noexcept {
73924
  size_t i = 0;
73925
  for (auto value : *this) {
73926
    if (i == index) { return value; }
73927
    i++;
73928
  }
73929
  return INDEX_OUT_OF_BOUNDS;
73930
}
73931
73932
} // namespace ondemand
73933
} // namespace ppc64
73934
} // namespace simdjson
73935
73936
namespace simdjson {
73937
73938
simdjson_inline simdjson_result<ppc64::ondemand::array>::simdjson_result(
73939
  ppc64::ondemand::array &&value
73940
) noexcept
73941
  : implementation_simdjson_result_base<ppc64::ondemand::array>(
73942
      std::forward<ppc64::ondemand::array>(value)
73943
    )
73944
{
73945
}
73946
simdjson_inline simdjson_result<ppc64::ondemand::array>::simdjson_result(
73947
  error_code error
73948
) noexcept
73949
  : implementation_simdjson_result_base<ppc64::ondemand::array>(error)
73950
{
73951
}
73952
73953
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::array>::begin() noexcept {
73954
  if (error()) { return error(); }
73955
  return first.begin();
73956
}
73957
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::array>::end() noexcept {
73958
  if (error()) { return error(); }
73959
  return first.end();
73960
}
73961
simdjson_inline  simdjson_result<size_t> simdjson_result<ppc64::ondemand::array>::count_elements() & noexcept {
73962
  if (error()) { return error(); }
73963
  return first.count_elements();
73964
}
73965
simdjson_inline  simdjson_result<bool> simdjson_result<ppc64::ondemand::array>::is_empty() & noexcept {
73966
  if (error()) { return error(); }
73967
  return first.is_empty();
73968
}
73969
simdjson_inline  simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::array>::at(size_t index) noexcept {
73970
  if (error()) { return error(); }
73971
  return first.at(index);
73972
}
73973
simdjson_inline  simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::array>::at_pointer(std::string_view json_pointer) noexcept {
73974
  if (error()) { return error(); }
73975
  return first.at_pointer(json_pointer);
73976
}
73977
simdjson_inline  simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::array>::at_path(std::string_view json_path) noexcept {
73978
  if (error()) { return error(); }
73979
  return first.at_path(json_path);
73980
}
73981
simdjson_inline  simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::array>::raw_json() noexcept {
73982
  if (error()) { return error(); }
73983
  return first.raw_json();
73984
}
73985
} // namespace simdjson
73986
73987
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
73988
/* end file simdjson/generic/ondemand/array-inl.h for ppc64 */
73989
/* including simdjson/generic/ondemand/array_iterator-inl.h for ppc64: #include "simdjson/generic/ondemand/array_iterator-inl.h" */
73990
/* begin file simdjson/generic/ondemand/array_iterator-inl.h for ppc64 */
73991
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
73992
73993
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
73994
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H */
73995
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
73996
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
73997
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
73998
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
73999
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
74000
74001
namespace simdjson {
74002
namespace ppc64 {
74003
namespace ondemand {
74004
74005
simdjson_inline array_iterator::array_iterator(const value_iterator &_iter) noexcept
74006
  : iter{_iter}
74007
{}
74008
74009
simdjson_inline simdjson_result<value> array_iterator::operator*() noexcept {
74010
  if (iter.error()) { iter.abandon(); return iter.error(); }
74011
  return value(iter.child());
74012
}
74013
simdjson_inline bool array_iterator::operator==(const array_iterator &other) const noexcept {
74014
  return !(*this != other);
74015
}
74016
simdjson_inline bool array_iterator::operator!=(const array_iterator &) const noexcept {
74017
  return iter.is_open();
74018
}
74019
simdjson_inline array_iterator &array_iterator::operator++() noexcept {
74020
  error_code error;
74021
  // PERF NOTE this is a safety rail ... users should exit loops as soon as they receive an error, so we'll never get here.
74022
  // However, it does not seem to make a perf difference, so we add it out of an abundance of caution.
74023
  if (( error = iter.error() )) { return *this; }
74024
  if (( error = iter.skip_child() )) { return *this; }
74025
  if (( error = iter.has_next_element().error() )) { return *this; }
74026
  return *this;
74027
}
74028
74029
} // namespace ondemand
74030
} // namespace ppc64
74031
} // namespace simdjson
74032
74033
namespace simdjson {
74034
74035
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator>::simdjson_result(
74036
  ppc64::ondemand::array_iterator &&value
74037
) noexcept
74038
  : ppc64::implementation_simdjson_result_base<ppc64::ondemand::array_iterator>(std::forward<ppc64::ondemand::array_iterator>(value))
74039
{
74040
  first.iter.assert_is_valid();
74041
}
74042
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
74043
  : ppc64::implementation_simdjson_result_base<ppc64::ondemand::array_iterator>({}, error)
74044
{
74045
}
74046
74047
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::array_iterator>::operator*() noexcept {
74048
  if (error()) { return error(); }
74049
  return *first;
74050
}
74051
simdjson_inline bool simdjson_result<ppc64::ondemand::array_iterator>::operator==(const simdjson_result<ppc64::ondemand::array_iterator> &other) const noexcept {
74052
  if (!first.iter.is_valid()) { return !error(); }
74053
  return first == other.first;
74054
}
74055
simdjson_inline bool simdjson_result<ppc64::ondemand::array_iterator>::operator!=(const simdjson_result<ppc64::ondemand::array_iterator> &other) const noexcept {
74056
  if (!first.iter.is_valid()) { return error(); }
74057
  return first != other.first;
74058
}
74059
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> &simdjson_result<ppc64::ondemand::array_iterator>::operator++() noexcept {
74060
  // Clear the error if there is one, so we don't yield it twice
74061
  if (error()) { second = SUCCESS; return *this; }
74062
  ++(first);
74063
  return *this;
74064
}
74065
74066
} // namespace simdjson
74067
74068
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
74069
/* end file simdjson/generic/ondemand/array_iterator-inl.h for ppc64 */
74070
/* including simdjson/generic/ondemand/document-inl.h for ppc64: #include "simdjson/generic/ondemand/document-inl.h" */
74071
/* begin file simdjson/generic/ondemand/document-inl.h for ppc64 */
74072
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
74073
74074
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
74075
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */
74076
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
74077
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */
74078
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
74079
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
74080
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
74081
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
74082
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
74083
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
74084
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */
74085
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
74086
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
74087
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
74088
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
74089
74090
namespace simdjson {
74091
namespace ppc64 {
74092
namespace ondemand {
74093
74094
simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept
74095
  : iter{std::forward<json_iterator>(_iter)}
74096
{
74097
  logger::log_start_value(iter, "document");
74098
}
74099
74100
simdjson_inline document document::start(json_iterator &&iter) noexcept {
74101
  return document(std::forward<json_iterator>(iter));
74102
}
74103
74104
inline void document::rewind() noexcept {
74105
  iter.rewind();
74106
}
74107
74108
inline std::string document::to_debug_string() noexcept {
74109
  return iter.to_string();
74110
}
74111
74112
inline simdjson_result<const char *> document::current_location() const noexcept {
74113
  return iter.current_location();
74114
}
74115
74116
inline int32_t document::current_depth() const noexcept {
74117
  return iter.depth();
74118
}
74119
74120
inline bool document::at_end() const noexcept {
74121
  return iter.at_end();
74122
}
74123
74124
74125
inline bool document::is_alive() noexcept {
74126
  return iter.is_alive();
74127
}
74128
simdjson_inline value_iterator document::resume_value_iterator() noexcept {
74129
  return value_iterator(&iter, 1, iter.root_position());
74130
}
74131
simdjson_inline value_iterator document::get_root_value_iterator() noexcept {
74132
  return resume_value_iterator();
74133
}
74134
simdjson_inline simdjson_result<object> document::start_or_resume_object() noexcept {
74135
  if (iter.at_root()) {
74136
    return get_object();
74137
  } else {
74138
    return object::resume(resume_value_iterator());
74139
  }
74140
}
74141
simdjson_inline simdjson_result<value> document::get_value() noexcept {
74142
  // Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
74143
  // gets called.
74144
74145
  // It is the convention throughout the code that  the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether
74146
  // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error.
74147
#if SIMDJSON_DEVELOPMENT_CHECKS
74148
  if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; }
74149
#endif
74150
  // assert_at_root() serves two purposes: in Debug mode, whether or not
74151
  // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of
74152
  // the document (this will typically be redundant). In release mode, it generates
74153
  // SIMDJSON_ASSUME statements to allow the compiler to make assumptions.
74154
  iter.assert_at_root();
74155
  switch (*iter.peek()) {
74156
    case '[': {
74157
      // The following lines check that the document ends with ].
74158
      auto value_iterator = get_root_value_iterator();
74159
      auto error = value_iterator.check_root_array();
74160
      if(error) { return error; }
74161
      return value(get_root_value_iterator());
74162
    }
74163
    case '{': {
74164
      // The following lines would check that the document ends with }.
74165
      auto value_iterator = get_root_value_iterator();
74166
      auto error = value_iterator.check_root_object();
74167
      if(error) { return error; }
74168
      return value(get_root_value_iterator());
74169
    }
74170
    default:
74171
      // Unfortunately, scalar documents are a special case in simdjson and they cannot
74172
      // be safely converted to value instances.
74173
      return SCALAR_DOCUMENT_AS_VALUE;
74174
  }
74175
}
74176
simdjson_inline simdjson_result<array> document::get_array() & noexcept {
74177
  auto value = get_root_value_iterator();
74178
  return array::start_root(value);
74179
}
74180
simdjson_inline simdjson_result<object> document::get_object() & noexcept {
74181
  auto value = get_root_value_iterator();
74182
  return object::start_root(value);
74183
}
74184
74185
/**
74186
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
74187
 * give an error, so we check for trailing content. We want to disallow trailing
74188
 * content.
74189
 * Thus, in several implementations below, we pass a 'true' parameter value to
74190
 * a get_root_value_iterator() method: this indicates that we disallow trailing content.
74191
 */
74192
74193
simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
74194
  return get_root_value_iterator().get_root_uint64(true);
74195
}
74196
simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
74197
  return get_root_value_iterator().get_root_uint64_in_string(true);
74198
}
74199
simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
74200
  return get_root_value_iterator().get_root_int64(true);
74201
}
74202
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
74203
  return get_root_value_iterator().get_root_int64_in_string(true);
74204
}
74205
simdjson_inline simdjson_result<double> document::get_double() noexcept {
74206
  return get_root_value_iterator().get_root_double(true);
74207
}
74208
simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
74209
  return get_root_value_iterator().get_root_double_in_string(true);
74210
}
74211
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
74212
  return get_root_value_iterator().get_root_string(true, allow_replacement);
74213
}
74214
template <typename string_type>
74215
simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
74216
  return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
74217
}
74218
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
74219
  return get_root_value_iterator().get_root_wobbly_string(true);
74220
}
74221
simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
74222
  return get_root_value_iterator().get_root_raw_json_string(true);
74223
}
74224
simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
74225
  return get_root_value_iterator().get_root_bool(true);
74226
}
74227
simdjson_inline simdjson_result<bool> document::is_null() noexcept {
74228
  return get_root_value_iterator().is_root_null(true);
74229
}
74230
74231
template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
74232
template<> simdjson_inline simdjson_result<object> document::get() & noexcept { return get_object(); }
74233
template<> simdjson_inline simdjson_result<raw_json_string> document::get() & noexcept { return get_raw_json_string(); }
74234
template<> simdjson_inline simdjson_result<std::string_view> document::get() & noexcept { return get_string(false); }
74235
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
74236
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
74237
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
74238
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
74239
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
74240
74241
template<> simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
74242
template<> simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
74243
template<> simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
74244
template<> simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
74245
template<> simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
74246
template<> simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
74247
template<> simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
74248
74249
template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
74250
  return get<T>().get(out);
74251
}
74252
template<typename T> simdjson_inline error_code document::get(T &out) && noexcept {
74253
  return std::forward<document>(*this).get<T>().get(out);
74254
}
74255
74256
#if SIMDJSON_EXCEPTIONS
74257
template <class T>
74258
simdjson_inline document::operator T() noexcept(false) { return get<T>(); }
74259
simdjson_inline document::operator array() & noexcept(false) { return get_array(); }
74260
simdjson_inline document::operator object() & noexcept(false) { return get_object(); }
74261
simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); }
74262
simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); }
74263
simdjson_inline document::operator double() noexcept(false) { return get_double(); }
74264
simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); }
74265
simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
74266
simdjson_inline document::operator bool() noexcept(false) { return get_bool(); }
74267
simdjson_inline document::operator value() noexcept(false) { return get_value(); }
74268
74269
#endif
74270
simdjson_inline simdjson_result<size_t> document::count_elements() & noexcept {
74271
  auto a = get_array();
74272
  simdjson_result<size_t> answer = a.count_elements();
74273
  /* If there was an array, we are now left pointing at its first element. */
74274
  if(answer.error() == SUCCESS) { rewind(); }
74275
  return answer;
74276
}
74277
simdjson_inline simdjson_result<size_t> document::count_fields() & noexcept {
74278
  auto a = get_object();
74279
  simdjson_result<size_t> answer = a.count_fields();
74280
  /* If there was an object, we are now left pointing at its first element. */
74281
  if(answer.error() == SUCCESS) { rewind(); }
74282
  return answer;
74283
}
74284
simdjson_inline simdjson_result<value> document::at(size_t index) & noexcept {
74285
  auto a = get_array();
74286
  return a.at(index);
74287
}
74288
simdjson_inline simdjson_result<array_iterator> document::begin() & noexcept {
74289
  return get_array().begin();
74290
}
74291
simdjson_inline simdjson_result<array_iterator> document::end() & noexcept {
74292
  return {};
74293
}
74294
74295
simdjson_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
74296
  return start_or_resume_object().find_field(key);
74297
}
74298
simdjson_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
74299
  return start_or_resume_object().find_field(key);
74300
}
74301
simdjson_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
74302
  return start_or_resume_object().find_field_unordered(key);
74303
}
74304
simdjson_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
74305
  return start_or_resume_object().find_field_unordered(key);
74306
}
74307
simdjson_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
74308
  return start_or_resume_object()[key];
74309
}
74310
simdjson_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
74311
  return start_or_resume_object()[key];
74312
}
74313
74314
simdjson_inline error_code document::consume() noexcept {
74315
  auto error = iter.skip_child(0);
74316
  if(error) { iter.abandon(); }
74317
  return error;
74318
}
74319
74320
simdjson_inline simdjson_result<std::string_view> document::raw_json() noexcept {
74321
  auto _iter = get_root_value_iterator();
74322
  const uint8_t * starting_point{_iter.peek_start()};
74323
  auto error = consume();
74324
  if(error) { return error; }
74325
  // After 'consume()', we could be left pointing just beyond the document, but that
74326
  // is ok because we are not going to dereference the final pointer position, we just
74327
  // use it to compute the length in bytes.
74328
  const uint8_t * final_point{iter.unsafe_pointer()};
74329
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
74330
}
74331
74332
simdjson_inline simdjson_result<json_type> document::type() noexcept {
74333
  return get_root_value_iterator().type();
74334
}
74335
74336
simdjson_inline simdjson_result<bool> document::is_scalar() noexcept {
74337
  json_type this_type;
74338
  auto error = type().get(this_type);
74339
  if(error) { return error; }
74340
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
74341
}
74342
74343
simdjson_inline simdjson_result<bool> document::is_string() noexcept {
74344
  json_type this_type;
74345
  auto error = type().get(this_type);
74346
  if(error) { return error; }
74347
  return (this_type == json_type::string);
74348
}
74349
74350
simdjson_inline bool document::is_negative() noexcept {
74351
  return get_root_value_iterator().is_root_negative();
74352
}
74353
74354
simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
74355
  return get_root_value_iterator().is_root_integer(true);
74356
}
74357
74358
simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
74359
  return get_root_value_iterator().get_root_number_type(true);
74360
}
74361
74362
simdjson_inline simdjson_result<number> document::get_number() noexcept {
74363
  return get_root_value_iterator().get_root_number(true);
74364
}
74365
74366
74367
simdjson_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
74368
  auto _iter = get_root_value_iterator();
74369
  return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_root_length());
74370
}
74371
74372
simdjson_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
74373
  rewind(); // Rewind the document each time at_pointer is called
74374
  if (json_pointer.empty()) {
74375
    return this->get_value();
74376
  }
74377
  json_type t;
74378
  SIMDJSON_TRY(type().get(t));
74379
  switch (t)
74380
  {
74381
    case json_type::array:
74382
      return (*this).get_array().at_pointer(json_pointer);
74383
    case json_type::object:
74384
      return (*this).get_object().at_pointer(json_pointer);
74385
    default:
74386
      return INVALID_JSON_POINTER;
74387
  }
74388
}
74389
74390
simdjson_inline simdjson_result<value> document::at_path(std::string_view json_path) noexcept {
74391
  rewind(); // Rewind the document each time at_pointer is called
74392
  if (json_path.empty()) {
74393
      return this->get_value();
74394
  }
74395
  json_type t;
74396
  SIMDJSON_TRY(type().get(t));
74397
  switch (t) {
74398
  case json_type::array:
74399
      return (*this).get_array().at_path(json_path);
74400
  case json_type::object:
74401
      return (*this).get_object().at_path(json_path);
74402
  default:
74403
      return INVALID_JSON_POINTER;
74404
  }
74405
}
74406
74407
} // namespace ondemand
74408
} // namespace ppc64
74409
} // namespace simdjson
74410
74411
namespace simdjson {
74412
74413
simdjson_inline simdjson_result<ppc64::ondemand::document>::simdjson_result(
74414
  ppc64::ondemand::document &&value
74415
) noexcept :
74416
    implementation_simdjson_result_base<ppc64::ondemand::document>(
74417
      std::forward<ppc64::ondemand::document>(value)
74418
    )
74419
{
74420
}
74421
simdjson_inline simdjson_result<ppc64::ondemand::document>::simdjson_result(
74422
  error_code error
74423
) noexcept :
74424
    implementation_simdjson_result_base<ppc64::ondemand::document>(
74425
      error
74426
    )
74427
{
74428
}
74429
simdjson_inline simdjson_result<size_t> simdjson_result<ppc64::ondemand::document>::count_elements() & noexcept {
74430
  if (error()) { return error(); }
74431
  return first.count_elements();
74432
}
74433
simdjson_inline simdjson_result<size_t> simdjson_result<ppc64::ondemand::document>::count_fields() & noexcept {
74434
  if (error()) { return error(); }
74435
  return first.count_fields();
74436
}
74437
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::at(size_t index) & noexcept {
74438
  if (error()) { return error(); }
74439
  return first.at(index);
74440
}
74441
simdjson_inline error_code simdjson_result<ppc64::ondemand::document>::rewind() noexcept {
74442
  if (error()) { return error(); }
74443
  first.rewind();
74444
  return SUCCESS;
74445
}
74446
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::document>::begin() & noexcept {
74447
  if (error()) { return error(); }
74448
  return first.begin();
74449
}
74450
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::document>::end() & noexcept {
74451
  return {};
74452
}
74453
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
74454
  if (error()) { return error(); }
74455
  return first.find_field_unordered(key);
74456
}
74457
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::find_field_unordered(const char *key) & noexcept {
74458
  if (error()) { return error(); }
74459
  return first.find_field_unordered(key);
74460
}
74461
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::operator[](std::string_view key) & noexcept {
74462
  if (error()) { return error(); }
74463
  return first[key];
74464
}
74465
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::operator[](const char *key) & noexcept {
74466
  if (error()) { return error(); }
74467
  return first[key];
74468
}
74469
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::find_field(std::string_view key) & noexcept {
74470
  if (error()) { return error(); }
74471
  return first.find_field(key);
74472
}
74473
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::find_field(const char *key) & noexcept {
74474
  if (error()) { return error(); }
74475
  return first.find_field(key);
74476
}
74477
simdjson_inline simdjson_result<ppc64::ondemand::array> simdjson_result<ppc64::ondemand::document>::get_array() & noexcept {
74478
  if (error()) { return error(); }
74479
  return first.get_array();
74480
}
74481
simdjson_inline simdjson_result<ppc64::ondemand::object> simdjson_result<ppc64::ondemand::document>::get_object() & noexcept {
74482
  if (error()) { return error(); }
74483
  return first.get_object();
74484
}
74485
simdjson_inline simdjson_result<uint64_t> simdjson_result<ppc64::ondemand::document>::get_uint64() noexcept {
74486
  if (error()) { return error(); }
74487
  return first.get_uint64();
74488
}
74489
simdjson_inline simdjson_result<uint64_t> simdjson_result<ppc64::ondemand::document>::get_uint64_in_string() noexcept {
74490
  if (error()) { return error(); }
74491
  return first.get_uint64_in_string();
74492
}
74493
simdjson_inline simdjson_result<int64_t> simdjson_result<ppc64::ondemand::document>::get_int64() noexcept {
74494
  if (error()) { return error(); }
74495
  return first.get_int64();
74496
}
74497
simdjson_inline simdjson_result<int64_t> simdjson_result<ppc64::ondemand::document>::get_int64_in_string() noexcept {
74498
  if (error()) { return error(); }
74499
  return first.get_int64_in_string();
74500
}
74501
simdjson_inline simdjson_result<double> simdjson_result<ppc64::ondemand::document>::get_double() noexcept {
74502
  if (error()) { return error(); }
74503
  return first.get_double();
74504
}
74505
simdjson_inline simdjson_result<double> simdjson_result<ppc64::ondemand::document>::get_double_in_string() noexcept {
74506
  if (error()) { return error(); }
74507
  return first.get_double_in_string();
74508
}
74509
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::document>::get_string(bool allow_replacement) noexcept {
74510
  if (error()) { return error(); }
74511
  return first.get_string(allow_replacement);
74512
}
74513
template <typename string_type>
74514
simdjson_inline error_code simdjson_result<ppc64::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
74515
  if (error()) { return error(); }
74516
  return first.get_string(receiver, allow_replacement);
74517
}
74518
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::document>::get_wobbly_string() noexcept {
74519
  if (error()) { return error(); }
74520
  return first.get_wobbly_string();
74521
}
74522
simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> simdjson_result<ppc64::ondemand::document>::get_raw_json_string() noexcept {
74523
  if (error()) { return error(); }
74524
  return first.get_raw_json_string();
74525
}
74526
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document>::get_bool() noexcept {
74527
  if (error()) { return error(); }
74528
  return first.get_bool();
74529
}
74530
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::get_value() noexcept {
74531
  if (error()) { return error(); }
74532
  return first.get_value();
74533
}
74534
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document>::is_null() noexcept {
74535
  if (error()) { return error(); }
74536
  return first.is_null();
74537
}
74538
74539
template<typename T>
74540
simdjson_inline simdjson_result<T> simdjson_result<ppc64::ondemand::document>::get() & noexcept {
74541
  if (error()) { return error(); }
74542
  return first.get<T>();
74543
}
74544
template<typename T>
74545
simdjson_inline simdjson_result<T> simdjson_result<ppc64::ondemand::document>::get() && noexcept {
74546
  if (error()) { return error(); }
74547
  return std::forward<ppc64::ondemand::document>(first).get<T>();
74548
}
74549
template<typename T>
74550
simdjson_inline error_code simdjson_result<ppc64::ondemand::document>::get(T &out) & noexcept {
74551
  if (error()) { return error(); }
74552
  return first.get<T>(out);
74553
}
74554
template<typename T>
74555
simdjson_inline error_code simdjson_result<ppc64::ondemand::document>::get(T &out) && noexcept {
74556
  if (error()) { return error(); }
74557
  return std::forward<ppc64::ondemand::document>(first).get<T>(out);
74558
}
74559
74560
template<> simdjson_inline simdjson_result<ppc64::ondemand::document> simdjson_result<ppc64::ondemand::document>::get<ppc64::ondemand::document>() & noexcept = delete;
74561
template<> simdjson_inline simdjson_result<ppc64::ondemand::document> simdjson_result<ppc64::ondemand::document>::get<ppc64::ondemand::document>() && noexcept {
74562
  if (error()) { return error(); }
74563
  return std::forward<ppc64::ondemand::document>(first);
74564
}
74565
template<> simdjson_inline error_code simdjson_result<ppc64::ondemand::document>::get<ppc64::ondemand::document>(ppc64::ondemand::document &out) & noexcept = delete;
74566
template<> simdjson_inline error_code simdjson_result<ppc64::ondemand::document>::get<ppc64::ondemand::document>(ppc64::ondemand::document &out) && noexcept {
74567
  if (error()) { return error(); }
74568
  out = std::forward<ppc64::ondemand::document>(first);
74569
  return SUCCESS;
74570
}
74571
74572
simdjson_inline simdjson_result<ppc64::ondemand::json_type> simdjson_result<ppc64::ondemand::document>::type() noexcept {
74573
  if (error()) { return error(); }
74574
  return first.type();
74575
}
74576
74577
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document>::is_scalar() noexcept {
74578
  if (error()) { return error(); }
74579
  return first.is_scalar();
74580
}
74581
74582
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document>::is_string() noexcept {
74583
  if (error()) { return error(); }
74584
  return first.is_string();
74585
}
74586
74587
simdjson_inline bool simdjson_result<ppc64::ondemand::document>::is_negative() noexcept {
74588
  if (error()) { return error(); }
74589
  return first.is_negative();
74590
}
74591
74592
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document>::is_integer() noexcept {
74593
  if (error()) { return error(); }
74594
  return first.is_integer();
74595
}
74596
74597
simdjson_inline simdjson_result<ppc64::number_type> simdjson_result<ppc64::ondemand::document>::get_number_type() noexcept {
74598
  if (error()) { return error(); }
74599
  return first.get_number_type();
74600
}
74601
74602
simdjson_inline simdjson_result<ppc64::ondemand::number> simdjson_result<ppc64::ondemand::document>::get_number() noexcept {
74603
  if (error()) { return error(); }
74604
  return first.get_number();
74605
}
74606
74607
74608
#if SIMDJSON_EXCEPTIONS
74609
template <class T, typename std::enable_if<std::is_same<T, ppc64::ondemand::document>::value == false>::type>
74610
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator T() noexcept(false) {
74611
  if (error()) { throw simdjson_error(error()); }
74612
  return first;
74613
}
74614
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator ppc64::ondemand::array() & noexcept(false) {
74615
  if (error()) { throw simdjson_error(error()); }
74616
  return first;
74617
}
74618
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator ppc64::ondemand::object() & noexcept(false) {
74619
  if (error()) { throw simdjson_error(error()); }
74620
  return first;
74621
}
74622
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator uint64_t() noexcept(false) {
74623
  if (error()) { throw simdjson_error(error()); }
74624
  return first;
74625
}
74626
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator int64_t() noexcept(false) {
74627
  if (error()) { throw simdjson_error(error()); }
74628
  return first;
74629
}
74630
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator double() noexcept(false) {
74631
  if (error()) { throw simdjson_error(error()); }
74632
  return first;
74633
}
74634
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator std::string_view() noexcept(false) {
74635
  if (error()) { throw simdjson_error(error()); }
74636
  return first;
74637
}
74638
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator ppc64::ondemand::raw_json_string() noexcept(false) {
74639
  if (error()) { throw simdjson_error(error()); }
74640
  return first;
74641
}
74642
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator bool() noexcept(false) {
74643
  if (error()) { throw simdjson_error(error()); }
74644
  return first;
74645
}
74646
simdjson_inline simdjson_result<ppc64::ondemand::document>::operator ppc64::ondemand::value() noexcept(false) {
74647
  if (error()) { throw simdjson_error(error()); }
74648
  return first;
74649
}
74650
#endif
74651
74652
74653
simdjson_inline simdjson_result<const char *> simdjson_result<ppc64::ondemand::document>::current_location() noexcept {
74654
  if (error()) { return error(); }
74655
  return first.current_location();
74656
}
74657
74658
simdjson_inline bool simdjson_result<ppc64::ondemand::document>::at_end() const noexcept {
74659
  if (error()) { return error(); }
74660
  return first.at_end();
74661
}
74662
74663
74664
simdjson_inline int32_t simdjson_result<ppc64::ondemand::document>::current_depth() const noexcept {
74665
  if (error()) { return error(); }
74666
  return first.current_depth();
74667
}
74668
74669
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::document>::raw_json_token() noexcept {
74670
  if (error()) { return error(); }
74671
  return first.raw_json_token();
74672
}
74673
74674
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::at_pointer(std::string_view json_pointer) noexcept {
74675
  if (error()) { return error(); }
74676
  return first.at_pointer(json_pointer);
74677
}
74678
74679
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document>::at_path(std::string_view json_path) noexcept {
74680
  if (error()) { return error(); }
74681
  return first.at_path(json_path);
74682
}
74683
74684
} // namespace simdjson
74685
74686
74687
namespace simdjson {
74688
namespace ppc64 {
74689
namespace ondemand {
74690
74691
simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {}
74692
simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
74693
simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
74694
simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
74695
simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
74696
/**
74697
 * The document_reference instances are used primarily/solely for streams of JSON
74698
 * documents.
74699
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
74700
 * give an error, so we check for trailing content.
74701
 *
74702
 * However, for streams of JSON documents, we want to be able to start from
74703
 * "321" "321" "321"
74704
 * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
74705
 * successfully each time.
74706
 *
74707
 * To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
74708
 * this indicates that we allow trailing content.
74709
 */
74710
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
74711
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
74712
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
74713
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
74714
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
74715
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
74716
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
74717
template <typename string_type>
74718
simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
74719
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
74720
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
74721
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
74722
simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
74723
simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
74724
template<> simdjson_inline simdjson_result<array> document_reference::get() & noexcept { return get_array(); }
74725
template<> simdjson_inline simdjson_result<object> document_reference::get() & noexcept { return get_object(); }
74726
template<> simdjson_inline simdjson_result<raw_json_string> document_reference::get() & noexcept { return get_raw_json_string(); }
74727
template<> simdjson_inline simdjson_result<std::string_view> document_reference::get() & noexcept { return get_string(false); }
74728
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
74729
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
74730
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
74731
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
74732
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
74733
#if SIMDJSON_EXCEPTIONS
74734
template <class T>
74735
simdjson_inline document_reference::operator T() noexcept(false) { return get<T>(); }
74736
simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
74737
simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
74738
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
74739
simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
74740
simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
74741
simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
74742
simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
74743
simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
74744
simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
74745
#endif
74746
simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
74747
simdjson_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
74748
simdjson_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
74749
simdjson_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
74750
simdjson_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
74751
simdjson_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
74752
simdjson_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
74753
simdjson_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
74754
simdjson_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
74755
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
74756
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
74757
simdjson_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
74758
simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
74759
simdjson_inline simdjson_result<bool> document_reference::is_string() noexcept { return doc->is_string(); }
74760
simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
74761
simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
74762
simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
74763
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
74764
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
74765
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
74766
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
74767
simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
74768
simdjson_inline simdjson_result<value> document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); }
74769
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
74770
simdjson_inline document_reference::operator document&() const noexcept { return *doc; }
74771
74772
} // namespace ondemand
74773
} // namespace ppc64
74774
} // namespace simdjson
74775
74776
74777
74778
namespace simdjson {
74779
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::simdjson_result(ppc64::ondemand::document_reference value, error_code error)
74780
  noexcept : implementation_simdjson_result_base<ppc64::ondemand::document_reference>(std::forward<ppc64::ondemand::document_reference>(value), error) {}
74781
74782
74783
simdjson_inline simdjson_result<size_t> simdjson_result<ppc64::ondemand::document_reference>::count_elements() & noexcept {
74784
  if (error()) { return error(); }
74785
  return first.count_elements();
74786
}
74787
simdjson_inline simdjson_result<size_t> simdjson_result<ppc64::ondemand::document_reference>::count_fields() & noexcept {
74788
  if (error()) { return error(); }
74789
  return first.count_fields();
74790
}
74791
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::at(size_t index) & noexcept {
74792
  if (error()) { return error(); }
74793
  return first.at(index);
74794
}
74795
simdjson_inline error_code simdjson_result<ppc64::ondemand::document_reference>::rewind() noexcept {
74796
  if (error()) { return error(); }
74797
  first.rewind();
74798
  return SUCCESS;
74799
}
74800
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::document_reference>::begin() & noexcept {
74801
  if (error()) { return error(); }
74802
  return first.begin();
74803
}
74804
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::document_reference>::end() & noexcept {
74805
  return {};
74806
}
74807
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
74808
  if (error()) { return error(); }
74809
  return first.find_field_unordered(key);
74810
}
74811
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
74812
  if (error()) { return error(); }
74813
  return first.find_field_unordered(key);
74814
}
74815
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
74816
  if (error()) { return error(); }
74817
  return first[key];
74818
}
74819
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::operator[](const char *key) & noexcept {
74820
  if (error()) { return error(); }
74821
  return first[key];
74822
}
74823
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
74824
  if (error()) { return error(); }
74825
  return first.find_field(key);
74826
}
74827
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::find_field(const char *key) & noexcept {
74828
  if (error()) { return error(); }
74829
  return first.find_field(key);
74830
}
74831
simdjson_inline simdjson_result<ppc64::ondemand::array> simdjson_result<ppc64::ondemand::document_reference>::get_array() & noexcept {
74832
  if (error()) { return error(); }
74833
  return first.get_array();
74834
}
74835
simdjson_inline simdjson_result<ppc64::ondemand::object> simdjson_result<ppc64::ondemand::document_reference>::get_object() & noexcept {
74836
  if (error()) { return error(); }
74837
  return first.get_object();
74838
}
74839
simdjson_inline simdjson_result<uint64_t> simdjson_result<ppc64::ondemand::document_reference>::get_uint64() noexcept {
74840
  if (error()) { return error(); }
74841
  return first.get_uint64();
74842
}
74843
simdjson_inline simdjson_result<uint64_t> simdjson_result<ppc64::ondemand::document_reference>::get_uint64_in_string() noexcept {
74844
  if (error()) { return error(); }
74845
  return first.get_uint64_in_string();
74846
}
74847
simdjson_inline simdjson_result<int64_t> simdjson_result<ppc64::ondemand::document_reference>::get_int64() noexcept {
74848
  if (error()) { return error(); }
74849
  return first.get_int64();
74850
}
74851
simdjson_inline simdjson_result<int64_t> simdjson_result<ppc64::ondemand::document_reference>::get_int64_in_string() noexcept {
74852
  if (error()) { return error(); }
74853
  return first.get_int64_in_string();
74854
}
74855
simdjson_inline simdjson_result<double> simdjson_result<ppc64::ondemand::document_reference>::get_double() noexcept {
74856
  if (error()) { return error(); }
74857
  return first.get_double();
74858
}
74859
simdjson_inline simdjson_result<double> simdjson_result<ppc64::ondemand::document_reference>::get_double_in_string() noexcept {
74860
  if (error()) { return error(); }
74861
  return first.get_double_in_string();
74862
}
74863
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::document_reference>::get_string(bool allow_replacement) noexcept {
74864
  if (error()) { return error(); }
74865
  return first.get_string(allow_replacement);
74866
}
74867
template <typename string_type>
74868
simdjson_inline error_code simdjson_result<ppc64::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
74869
  if (error()) { return error(); }
74870
  return first.get_string(receiver, allow_replacement);
74871
}
74872
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::document_reference>::get_wobbly_string() noexcept {
74873
  if (error()) { return error(); }
74874
  return first.get_wobbly_string();
74875
}
74876
simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> simdjson_result<ppc64::ondemand::document_reference>::get_raw_json_string() noexcept {
74877
  if (error()) { return error(); }
74878
  return first.get_raw_json_string();
74879
}
74880
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document_reference>::get_bool() noexcept {
74881
  if (error()) { return error(); }
74882
  return first.get_bool();
74883
}
74884
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::get_value() noexcept {
74885
  if (error()) { return error(); }
74886
  return first.get_value();
74887
}
74888
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document_reference>::is_null() noexcept {
74889
  if (error()) { return error(); }
74890
  return first.is_null();
74891
}
74892
simdjson_inline simdjson_result<ppc64::ondemand::json_type> simdjson_result<ppc64::ondemand::document_reference>::type() noexcept {
74893
  if (error()) { return error(); }
74894
  return first.type();
74895
}
74896
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document_reference>::is_scalar() noexcept {
74897
  if (error()) { return error(); }
74898
  return first.is_scalar();
74899
}
74900
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document_reference>::is_string() noexcept {
74901
  if (error()) { return error(); }
74902
  return first.is_string();
74903
}
74904
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document_reference>::is_negative() noexcept {
74905
  if (error()) { return error(); }
74906
  return first.is_negative();
74907
}
74908
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::document_reference>::is_integer() noexcept {
74909
  if (error()) { return error(); }
74910
  return first.is_integer();
74911
}
74912
simdjson_inline simdjson_result<ppc64::number_type> simdjson_result<ppc64::ondemand::document_reference>::get_number_type() noexcept {
74913
  if (error()) { return error(); }
74914
  return first.get_number_type();
74915
}
74916
simdjson_inline simdjson_result<ppc64::ondemand::number> simdjson_result<ppc64::ondemand::document_reference>::get_number() noexcept {
74917
  if (error()) { return error(); }
74918
  return first.get_number();
74919
}
74920
#if SIMDJSON_EXCEPTIONS
74921
template <class T, typename std::enable_if<std::is_same<T, ppc64::ondemand::document_reference>::value == false>::type>
74922
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator T() noexcept(false) {
74923
  if (error()) { throw simdjson_error(error()); }
74924
  return first;
74925
}
74926
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator ppc64::ondemand::array() & noexcept(false) {
74927
  if (error()) { throw simdjson_error(error()); }
74928
  return first;
74929
}
74930
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator ppc64::ondemand::object() & noexcept(false) {
74931
  if (error()) { throw simdjson_error(error()); }
74932
  return first;
74933
}
74934
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator uint64_t() noexcept(false) {
74935
  if (error()) { throw simdjson_error(error()); }
74936
  return first;
74937
}
74938
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator int64_t() noexcept(false) {
74939
  if (error()) { throw simdjson_error(error()); }
74940
  return first;
74941
}
74942
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator double() noexcept(false) {
74943
  if (error()) { throw simdjson_error(error()); }
74944
  return first;
74945
}
74946
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator std::string_view() noexcept(false) {
74947
  if (error()) { throw simdjson_error(error()); }
74948
  return first;
74949
}
74950
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator ppc64::ondemand::raw_json_string() noexcept(false) {
74951
  if (error()) { throw simdjson_error(error()); }
74952
  return first;
74953
}
74954
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator bool() noexcept(false) {
74955
  if (error()) { throw simdjson_error(error()); }
74956
  return first;
74957
}
74958
simdjson_inline simdjson_result<ppc64::ondemand::document_reference>::operator ppc64::ondemand::value() noexcept(false) {
74959
  if (error()) { throw simdjson_error(error()); }
74960
  return first;
74961
}
74962
#endif
74963
74964
simdjson_inline simdjson_result<const char *> simdjson_result<ppc64::ondemand::document_reference>::current_location() noexcept {
74965
  if (error()) { return error(); }
74966
  return first.current_location();
74967
}
74968
74969
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::document_reference>::raw_json_token() noexcept {
74970
  if (error()) { return error(); }
74971
  return first.raw_json_token();
74972
}
74973
74974
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
74975
  if (error()) { return error(); }
74976
  return first.at_pointer(json_pointer);
74977
}
74978
74979
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::document_reference>::at_path(std::string_view json_path) noexcept {
74980
  if (error()) {
74981
      return error();
74982
  }
74983
  return first.at_path(json_path);
74984
}
74985
74986
} // namespace simdjson
74987
74988
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
74989
/* end file simdjson/generic/ondemand/document-inl.h for ppc64 */
74990
/* including simdjson/generic/ondemand/document_stream-inl.h for ppc64: #include "simdjson/generic/ondemand/document_stream-inl.h" */
74991
/* begin file simdjson/generic/ondemand/document_stream-inl.h for ppc64 */
74992
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
74993
74994
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
74995
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */
74996
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
74997
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
74998
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
74999
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
75000
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
75001
75002
#include <algorithm>
75003
#include <stdexcept>
75004
75005
namespace simdjson {
75006
namespace ppc64 {
75007
namespace ondemand {
75008
75009
#ifdef SIMDJSON_THREADS_ENABLED
75010
75011
inline void stage1_worker::finish() {
75012
  // After calling "run" someone would call finish() to wait
75013
  // for the end of the processing.
75014
  // This function will wait until either the thread has done
75015
  // the processing or, else, the destructor has been called.
75016
  std::unique_lock<std::mutex> lock(locking_mutex);
75017
  cond_var.wait(lock, [this]{return has_work == false;});
75018
}
75019
75020
inline stage1_worker::~stage1_worker() {
75021
  // The thread may never outlive the stage1_worker instance
75022
  // and will always be stopped/joined before the stage1_worker
75023
  // instance is gone.
75024
  stop_thread();
75025
}
75026
75027
inline void stage1_worker::start_thread() {
75028
  std::unique_lock<std::mutex> lock(locking_mutex);
75029
  if(thread.joinable()) {
75030
    return; // This should never happen but we never want to create more than one thread.
75031
  }
75032
  thread = std::thread([this]{
75033
      while(true) {
75034
        std::unique_lock<std::mutex> thread_lock(locking_mutex);
75035
        // We wait for either "run" or "stop_thread" to be called.
75036
        cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
75037
        // If, for some reason, the stop_thread() method was called (i.e., the
75038
        // destructor of stage1_worker is called, then we want to immediately destroy
75039
        // the thread (and not do any more processing).
75040
        if(!can_work) {
75041
          break;
75042
        }
75043
        this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
75044
              this->_next_batch_start);
75045
        this->has_work = false;
75046
        // The condition variable call should be moved after thread_lock.unlock() for performance
75047
        // reasons but thread sanitizers may report it as a data race if we do.
75048
        // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
75049
        cond_var.notify_one(); // will notify "finish"
75050
        thread_lock.unlock();
75051
      }
75052
    }
75053
  );
75054
}
75055
75056
75057
inline void stage1_worker::stop_thread() {
75058
  std::unique_lock<std::mutex> lock(locking_mutex);
75059
  // We have to make sure that all locks can be released.
75060
  can_work = false;
75061
  has_work = false;
75062
  cond_var.notify_all();
75063
  lock.unlock();
75064
  if(thread.joinable()) {
75065
    thread.join();
75066
  }
75067
}
75068
75069
inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) {
75070
  std::unique_lock<std::mutex> lock(locking_mutex);
75071
  owner = ds;
75072
  _next_batch_start = next_batch_start;
75073
  stage1_thread_parser = stage1;
75074
  has_work = true;
75075
  // The condition variable call should be moved after thread_lock.unlock() for performance
75076
  // reasons but thread sanitizers may report it as a data race if we do.
75077
  // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
75078
  cond_var.notify_one(); // will notify the thread lock that we have work
75079
  lock.unlock();
75080
}
75081
75082
#endif  // SIMDJSON_THREADS_ENABLED
75083
75084
simdjson_inline document_stream::document_stream(
75085
  ondemand::parser &_parser,
75086
  const uint8_t *_buf,
75087
  size_t _len,
75088
  size_t _batch_size,
75089
  bool _allow_comma_separated
75090
) noexcept
75091
  : parser{&_parser},
75092
    buf{_buf},
75093
    len{_len},
75094
    batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
75095
    allow_comma_separated{_allow_comma_separated},
75096
    error{SUCCESS}
75097
    #ifdef SIMDJSON_THREADS_ENABLED
75098
    , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
75099
    #endif
75100
{
75101
#ifdef SIMDJSON_THREADS_ENABLED
75102
  if(worker.get() == nullptr) {
75103
    error = MEMALLOC;
75104
  }
75105
#endif
75106
}
75107
75108
simdjson_inline document_stream::document_stream() noexcept
75109
  : parser{nullptr},
75110
    buf{nullptr},
75111
    len{0},
75112
    batch_size{0},
75113
    allow_comma_separated{false},
75114
    error{UNINITIALIZED}
75115
    #ifdef SIMDJSON_THREADS_ENABLED
75116
    , use_thread(false)
75117
    #endif
75118
{
75119
}
75120
75121
simdjson_inline document_stream::~document_stream() noexcept
75122
{
75123
  #ifdef SIMDJSON_THREADS_ENABLED
75124
  worker.reset();
75125
  #endif
75126
}
75127
75128
inline size_t document_stream::size_in_bytes() const noexcept {
75129
  return len;
75130
}
75131
75132
inline size_t document_stream::truncated_bytes() const noexcept {
75133
  if(error == CAPACITY) { return len - batch_start; }
75134
  return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
75135
}
75136
75137
simdjson_inline document_stream::iterator::iterator() noexcept
75138
  : stream{nullptr}, finished{true} {
75139
}
75140
75141
simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
75142
  : stream{_stream}, finished{is_end} {
75143
}
75144
75145
simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
75146
  //if(stream->error) { return stream->error; }
75147
  return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
75148
}
75149
75150
simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
75151
  // If there is an error, then we want the iterator
75152
  // to be finished, no matter what. (E.g., we do not
75153
  // keep generating documents with errors, or go beyond
75154
  // a document with errors.)
75155
  //
75156
  // Users do not have to call "operator*()" when they use operator++,
75157
  // so we need to end the stream in the operator++ function.
75158
  //
75159
  // Note that setting finished = true is essential otherwise
75160
  // we would enter an infinite loop.
75161
  if (stream->error) { finished = true; }
75162
  // Note that stream->error() is guarded against error conditions
75163
  // (it will immediately return if stream->error casts to false).
75164
  // In effect, this next function does nothing when (stream->error)
75165
  // is true (hence the risk of an infinite loop).
75166
  stream->next();
75167
  // If that was the last document, we're finished.
75168
  // It is the only type of error we do not want to appear
75169
  // in operator*.
75170
  if (stream->error == EMPTY) { finished = true; }
75171
  // If we had any other kind of error (not EMPTY) then we want
75172
  // to pass it along to the operator* and we cannot mark the result
75173
  // as "finished" just yet.
75174
  return *this;
75175
}
75176
75177
simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
75178
  return finished != other.finished;
75179
}
75180
75181
simdjson_inline document_stream::iterator document_stream::begin() noexcept {
75182
  start();
75183
  // If there are no documents, we're finished.
75184
  return iterator(this, error == EMPTY);
75185
}
75186
75187
simdjson_inline document_stream::iterator document_stream::end() noexcept {
75188
  return iterator(this, true);
75189
}
75190
75191
inline void document_stream::start() noexcept {
75192
  if (error) { return; }
75193
  error = parser->allocate(batch_size);
75194
  if (error) { return; }
75195
  // Always run the first stage 1 parse immediately
75196
  batch_start = 0;
75197
  error = run_stage1(*parser, batch_start);
75198
  while(error == EMPTY) {
75199
    // In exceptional cases, we may start with an empty block
75200
    batch_start = next_batch_start();
75201
    if (batch_start >= len) { return; }
75202
    error = run_stage1(*parser, batch_start);
75203
  }
75204
  if (error) { return; }
75205
  doc_index = batch_start;
75206
  doc = document(json_iterator(&buf[batch_start], parser));
75207
  doc.iter._streaming = true;
75208
75209
  #ifdef SIMDJSON_THREADS_ENABLED
75210
  if (use_thread && next_batch_start() < len) {
75211
    // Kick off the first thread on next batch if needed
75212
    error = stage1_thread_parser.allocate(batch_size);
75213
    if (error) { return; }
75214
    worker->start_thread();
75215
    start_stage1_thread();
75216
    if (error) { return; }
75217
  }
75218
  #endif // SIMDJSON_THREADS_ENABLED
75219
}
75220
75221
inline void document_stream::next() noexcept {
75222
  // We always enter at once once in an error condition.
75223
  if (error) { return; }
75224
  next_document();
75225
  if (error) { return; }
75226
  auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get();
75227
  doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index];
75228
75229
  // Check if at end of structural indexes (i.e. at end of batch)
75230
  if(cur_struct_index >= static_cast<int64_t>(parser->implementation->n_structural_indexes)) {
75231
    error = EMPTY;
75232
    // Load another batch (if available)
75233
    while (error == EMPTY) {
75234
      batch_start = next_batch_start();
75235
      if (batch_start >= len) { break; }
75236
      #ifdef SIMDJSON_THREADS_ENABLED
75237
      if(use_thread) {
75238
        load_from_stage1_thread();
75239
      } else {
75240
        error = run_stage1(*parser, batch_start);
75241
      }
75242
      #else
75243
      error = run_stage1(*parser, batch_start);
75244
      #endif
75245
      /**
75246
       * Whenever we move to another window, we need to update all pointers to make
75247
       * it appear as if the input buffer started at the beginning of the window.
75248
       *
75249
       * Take this input:
75250
       *
75251
       * {"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]  [15,  11,   12, 13]  [154,  110,   112, 1311]
75252
       *
75253
       * Say you process the following window...
75254
       *
75255
       * '{"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]'
75256
       *
75257
       * When you do so, the json_iterator has a pointer at the beginning of the memory region
75258
       * (pointing at the beginning of '{"z"...'.
75259
       *
75260
       * When you move to the window that starts at...
75261
       *
75262
       * '[7,  10,   9]  [15,  11,   12, 13] ...
75263
       *
75264
       * then it is not sufficient to just run stage 1. You also need to re-anchor the
75265
       * json_iterator so that it believes we are starting at '[7,  10,   9]...'.
75266
       *
75267
       * Under the DOM front-end, this gets done automatically because the parser owns
75268
       * the pointer the data, and when you call stage1 and then stage2 on the same
75269
       * parser, then stage2 will run on the pointer acquired by stage1.
75270
       *
75271
       * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that
75272
       * we used. But json_iterator has no callback when stage1 is called on the parser.
75273
       * In fact, I think that the parser is unaware of json_iterator.
75274
       *
75275
       *
75276
       * So we need to re-anchor the json_iterator after each call to stage 1 so that
75277
       * all of the pointers are in sync.
75278
       */
75279
      doc.iter = json_iterator(&buf[batch_start], parser);
75280
      doc.iter._streaming = true;
75281
      /**
75282
       * End of resync.
75283
       */
75284
75285
      if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
75286
      doc_index = batch_start;
75287
    }
75288
  }
75289
}
75290
75291
inline void document_stream::next_document() noexcept {
75292
  // Go to next place where depth=0 (document depth)
75293
  error = doc.iter.skip_child(0);
75294
  if (error) { return; }
75295
  // Always set depth=1 at the start of document
75296
  doc.iter._depth = 1;
75297
  // consume comma if comma separated is allowed
75298
  if (allow_comma_separated) { doc.iter.consume_character(','); }
75299
  // Resets the string buffer at the beginning, thus invalidating the strings.
75300
  doc.iter._string_buf_loc = parser->string_buf.get();
75301
  doc.iter._root = doc.iter.position();
75302
}
75303
75304
inline size_t document_stream::next_batch_start() const noexcept {
75305
  return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
75306
}
75307
75308
inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept {
75309
  // This code only updates the structural index in the parser, it does not update any json_iterator
75310
  // instance.
75311
  size_t remaining = len - _batch_start;
75312
  if (remaining <= batch_size) {
75313
    return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
75314
  } else {
75315
    return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
75316
  }
75317
}
75318
75319
simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
75320
  return stream->doc_index;
75321
}
75322
75323
simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
75324
  auto depth = stream->doc.iter.depth();
75325
  auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get();
75326
75327
  // If at root, process the first token to determine if scalar value
75328
  if (stream->doc.iter.at_root()) {
75329
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
75330
      case '{': case '[':   // Depth=1 already at start of document
75331
        break;
75332
      case '}': case ']':
75333
        depth--;
75334
        break;
75335
      default:    // Scalar value document
75336
        // TODO: Remove any trailing whitespaces
75337
        // This returns a string spanning from start of value to the beginning of the next document (excluded)
75338
        return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[++cur_struct_index] - current_index() - 1);
75339
    }
75340
    cur_struct_index++;
75341
  }
75342
75343
  while (cur_struct_index <= static_cast<int64_t>(stream->parser->implementation->n_structural_indexes)) {
75344
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
75345
      case '{': case '[':
75346
        depth++;
75347
        break;
75348
      case '}': case ']':
75349
        depth--;
75350
        break;
75351
    }
75352
    if (depth == 0) { break; }
75353
    cur_struct_index++;
75354
  }
75355
75356
  return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);;
75357
}
75358
75359
inline error_code document_stream::iterator::error() const noexcept {
75360
  return stream->error;
75361
}
75362
75363
#ifdef SIMDJSON_THREADS_ENABLED
75364
75365
inline void document_stream::load_from_stage1_thread() noexcept {
75366
  worker->finish();
75367
  // Swap to the parser that was loaded up in the thread. Make sure the parser has
75368
  // enough memory to swap to, as well.
75369
  std::swap(stage1_thread_parser,*parser);
75370
  error = stage1_thread_error;
75371
  if (error) { return; }
75372
75373
  // If there's anything left, start the stage 1 thread!
75374
  if (next_batch_start() < len) {
75375
    start_stage1_thread();
75376
  }
75377
}
75378
75379
inline void document_stream::start_stage1_thread() noexcept {
75380
  // we call the thread on a lambda that will update
75381
  // this->stage1_thread_error
75382
  // there is only one thread that may write to this value
75383
  // TODO this is NOT exception-safe.
75384
  this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
75385
  size_t _next_batch_start = this->next_batch_start();
75386
75387
  worker->run(this, & this->stage1_thread_parser, _next_batch_start);
75388
}
75389
75390
#endif // SIMDJSON_THREADS_ENABLED
75391
75392
} // namespace ondemand
75393
} // namespace ppc64
75394
} // namespace simdjson
75395
75396
namespace simdjson {
75397
75398
simdjson_inline simdjson_result<ppc64::ondemand::document_stream>::simdjson_result(
75399
  error_code error
75400
) noexcept :
75401
    implementation_simdjson_result_base<ppc64::ondemand::document_stream>(error)
75402
{
75403
}
75404
simdjson_inline simdjson_result<ppc64::ondemand::document_stream>::simdjson_result(
75405
  ppc64::ondemand::document_stream &&value
75406
) noexcept :
75407
    implementation_simdjson_result_base<ppc64::ondemand::document_stream>(
75408
      std::forward<ppc64::ondemand::document_stream>(value)
75409
    )
75410
{
75411
}
75412
75413
}
75414
75415
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
75416
/* end file simdjson/generic/ondemand/document_stream-inl.h for ppc64 */
75417
/* including simdjson/generic/ondemand/field-inl.h for ppc64: #include "simdjson/generic/ondemand/field-inl.h" */
75418
/* begin file simdjson/generic/ondemand/field-inl.h for ppc64 */
75419
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
75420
75421
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
75422
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */
75423
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
75424
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
75425
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
75426
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
75427
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
75428
75429
namespace simdjson {
75430
namespace ppc64 {
75431
namespace ondemand {
75432
75433
// clang 6 does not think the default constructor can be noexcept, so we make it explicit
75434
simdjson_inline field::field() noexcept : std::pair<raw_json_string, ondemand::value>() {}
75435
75436
simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept
75437
  : std::pair<raw_json_string, ondemand::value>(key, std::forward<ondemand::value>(value))
75438
{
75439
}
75440
75441
simdjson_inline simdjson_result<field> field::start(value_iterator &parent_iter) noexcept {
75442
  raw_json_string key;
75443
  SIMDJSON_TRY( parent_iter.field_key().get(key) );
75444
  SIMDJSON_TRY( parent_iter.field_value() );
75445
  return field::start(parent_iter, key);
75446
}
75447
75448
simdjson_inline simdjson_result<field> field::start(const value_iterator &parent_iter, raw_json_string key) noexcept {
75449
    return field(key, parent_iter.child());
75450
}
75451
75452
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> field::unescaped_key(bool allow_replacement) noexcept {
75453
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us.
75454
  simdjson_result<std::string_view> answer = first.unescape(second.iter.json_iter(), allow_replacement);
75455
  first.consume();
75456
  return answer;
75457
}
75458
75459
simdjson_inline raw_json_string field::key() const noexcept {
75460
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
75461
  return first;
75462
}
75463
75464
75465
simdjson_inline std::string_view field::key_raw_json_token() const noexcept {
75466
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
75467
  return std::string_view(reinterpret_cast<const char*>(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1);
75468
}
75469
75470
simdjson_inline value &field::value() & noexcept {
75471
  return second;
75472
}
75473
75474
simdjson_inline value field::value() && noexcept {
75475
  return std::forward<field>(*this).second;
75476
}
75477
75478
} // namespace ondemand
75479
} // namespace ppc64
75480
} // namespace simdjson
75481
75482
namespace simdjson {
75483
75484
simdjson_inline simdjson_result<ppc64::ondemand::field>::simdjson_result(
75485
  ppc64::ondemand::field &&value
75486
) noexcept :
75487
    implementation_simdjson_result_base<ppc64::ondemand::field>(
75488
      std::forward<ppc64::ondemand::field>(value)
75489
    )
75490
{
75491
}
75492
simdjson_inline simdjson_result<ppc64::ondemand::field>::simdjson_result(
75493
  error_code error
75494
) noexcept :
75495
    implementation_simdjson_result_base<ppc64::ondemand::field>(error)
75496
{
75497
}
75498
75499
simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> simdjson_result<ppc64::ondemand::field>::key() noexcept {
75500
  if (error()) { return error(); }
75501
  return first.key();
75502
}
75503
75504
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::field>::key_raw_json_token() noexcept {
75505
  if (error()) { return error(); }
75506
  return first.key_raw_json_token();
75507
}
75508
75509
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::field>::unescaped_key(bool allow_replacement) noexcept {
75510
  if (error()) { return error(); }
75511
  return first.unescaped_key(allow_replacement);
75512
}
75513
75514
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::field>::value() noexcept {
75515
  if (error()) { return error(); }
75516
  return std::move(first.value());
75517
}
75518
75519
} // namespace simdjson
75520
75521
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
75522
/* end file simdjson/generic/ondemand/field-inl.h for ppc64 */
75523
/* including simdjson/generic/ondemand/json_iterator-inl.h for ppc64: #include "simdjson/generic/ondemand/json_iterator-inl.h" */
75524
/* begin file simdjson/generic/ondemand/json_iterator-inl.h for ppc64 */
75525
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
75526
75527
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
75528
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */
75529
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
75530
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
75531
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
75532
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
75533
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
75534
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */
75535
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */
75536
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */
75537
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
75538
75539
namespace simdjson {
75540
namespace ppc64 {
75541
namespace ondemand {
75542
75543
simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
75544
  : token(std::forward<token_iterator>(other.token)),
75545
    parser{other.parser},
75546
    _string_buf_loc{other._string_buf_loc},
75547
    error{other.error},
75548
    _depth{other._depth},
75549
    _root{other._root},
75550
    _streaming{other._streaming}
75551
{
75552
  other.parser = nullptr;
75553
}
75554
simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept {
75555
  token = other.token;
75556
  parser = other.parser;
75557
  _string_buf_loc = other._string_buf_loc;
75558
  error = other.error;
75559
  _depth = other._depth;
75560
  _root = other._root;
75561
  _streaming = other._streaming;
75562
  other.parser = nullptr;
75563
  return *this;
75564
}
75565
75566
simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept
75567
  : token(buf, &_parser->implementation->structural_indexes[0]),
75568
    parser{_parser},
75569
    _string_buf_loc{parser->string_buf.get()},
75570
    _depth{1},
75571
    _root{parser->implementation->structural_indexes.get()},
75572
    _streaming{false}
75573
75574
{
75575
  logger::log_headers();
75576
#if SIMDJSON_CHECK_EOF
75577
  assert_more_tokens();
75578
#endif
75579
}
75580
75581
inline void json_iterator::rewind() noexcept {
75582
  token.set_position( root_position() );
75583
  logger::log_headers(); // We start again
75584
  _string_buf_loc = parser->string_buf.get();
75585
  _depth = 1;
75586
}
75587
75588
inline bool json_iterator::balanced() const noexcept {
75589
  token_iterator ti(token);
75590
  int32_t count{0};
75591
  ti.set_position( root_position() );
75592
  while(ti.peek() <= peek_last()) {
75593
    switch (*ti.return_current_and_advance())
75594
    {
75595
    case '[': case '{':
75596
      count++;
75597
      break;
75598
    case ']': case '}':
75599
      count--;
75600
      break;
75601
    default:
75602
      break;
75603
    }
75604
  }
75605
  return count == 0;
75606
}
75607
75608
75609
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
75610
// relating depth and parent_depth, which is a desired effect. The warning does not show up if the
75611
// skip_child() function is not marked inline).
75612
SIMDJSON_PUSH_DISABLE_WARNINGS
75613
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
75614
simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
75615
  if (depth() <= parent_depth) { return SUCCESS; }
75616
  switch (*return_current_and_advance()) {
75617
    // TODO consider whether matching braces is a requirement: if non-matching braces indicates
75618
    // *missing* braces, then future lookups are not in the object/arrays they think they are,
75619
    // violating the rule "validate enough structure that the user can be confident they are
75620
    // looking at the right values."
75621
    // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
75622
75623
    // For the first open array/object in a value, we've already incremented depth, so keep it the same
75624
    // We never stop at colon, but if we did, it wouldn't affect depth
75625
    case '[': case '{': case ':':
75626
      logger::log_start_value(*this, "skip");
75627
      break;
75628
    // If there is a comma, we have just finished a value in an array/object, and need to get back in
75629
    case ',':
75630
      logger::log_value(*this, "skip");
75631
      break;
75632
    // ] or } means we just finished a value and need to jump out of the array/object
75633
    case ']': case '}':
75634
      logger::log_end_value(*this, "skip");
75635
      _depth--;
75636
      if (depth() <= parent_depth) { return SUCCESS; }
75637
#if SIMDJSON_CHECK_EOF
75638
      // If there are no more tokens, the parent is incomplete.
75639
      if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
75640
#endif // SIMDJSON_CHECK_EOF
75641
      break;
75642
    case '"':
75643
      if(*peek() == ':') {
75644
        // We are at a key!!!
75645
        // This might happen if you just started an object and you skip it immediately.
75646
        // Performance note: it would be nice to get rid of this check as it is somewhat
75647
        // expensive.
75648
        // https://github.com/simdjson/simdjson/issues/1742
75649
        logger::log_value(*this, "key");
75650
        return_current_and_advance(); // eat up the ':'
75651
        break; // important!!!
75652
      }
75653
      simdjson_fallthrough;
75654
    // Anything else must be a scalar value
75655
    default:
75656
      // For the first scalar, we will have incremented depth already, so we decrement it here.
75657
      logger::log_value(*this, "skip");
75658
      _depth--;
75659
      if (depth() <= parent_depth) { return SUCCESS; }
75660
      break;
75661
  }
75662
75663
  // Now that we've considered the first value, we only increment/decrement for arrays/objects
75664
  while (position() < end_position()) {
75665
    switch (*return_current_and_advance()) {
75666
      case '[': case '{':
75667
        logger::log_start_value(*this, "skip");
75668
        _depth++;
75669
        break;
75670
      // TODO consider whether matching braces is a requirement: if non-matching braces indicates
75671
      // *missing* braces, then future lookups are not in the object/arrays they think they are,
75672
      // violating the rule "validate enough structure that the user can be confident they are
75673
      // looking at the right values."
75674
      // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
75675
      case ']': case '}':
75676
        logger::log_end_value(*this, "skip");
75677
        _depth--;
75678
        if (depth() <= parent_depth) { return SUCCESS; }
75679
        break;
75680
      default:
75681
        logger::log_value(*this, "skip", "");
75682
        break;
75683
    }
75684
  }
75685
75686
  return report_error(TAPE_ERROR, "not enough close braces");
75687
}
75688
75689
SIMDJSON_POP_DISABLE_WARNINGS
75690
75691
simdjson_inline bool json_iterator::at_root() const noexcept {
75692
  return position() == root_position();
75693
}
75694
75695
simdjson_inline bool json_iterator::is_single_token() const noexcept {
75696
  return parser->implementation->n_structural_indexes == 1;
75697
}
75698
75699
simdjson_inline bool json_iterator::streaming() const noexcept {
75700
  return _streaming;
75701
}
75702
75703
simdjson_inline token_position json_iterator::root_position() const noexcept {
75704
  return _root;
75705
}
75706
75707
simdjson_inline void json_iterator::assert_at_document_depth() const noexcept {
75708
  SIMDJSON_ASSUME( _depth == 1 );
75709
}
75710
75711
simdjson_inline void json_iterator::assert_at_root() const noexcept {
75712
  SIMDJSON_ASSUME( _depth == 1 );
75713
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
75714
  // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument
75715
  // has side effects that will be discarded.
75716
  SIMDJSON_ASSUME( token.position() == _root );
75717
#endif
75718
}
75719
75720
simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
75721
  assert_valid_position(token._position + required_tokens - 1);
75722
}
75723
75724
simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
75725
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
75726
  SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
75727
  SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
75728
#endif
75729
}
75730
75731
simdjson_inline bool json_iterator::at_end() const noexcept {
75732
  return position() == end_position();
75733
}
75734
simdjson_inline token_position json_iterator::end_position() const noexcept {
75735
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
75736
  return &parser->implementation->structural_indexes[n_structural_indexes];
75737
}
75738
75739
inline std::string json_iterator::to_string() const noexcept {
75740
  if( !is_alive() ) { return "dead json_iterator instance"; }
75741
  const char * current_structural = reinterpret_cast<const char *>(token.peek());
75742
  return std::string("json_iterator [ depth : ") + std::to_string(_depth)
75743
          + std::string(", structural : '") + std::string(current_structural,1)
75744
          + std::string("', offset : ") + std::to_string(token.current_offset())
75745
          + std::string("', error : ") + error_message(error)
75746
          + std::string(" ]");
75747
}
75748
75749
inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
75750
  if (!is_alive()) {    // Unrecoverable error
75751
    if (!at_root()) {
75752
      return reinterpret_cast<const char *>(token.peek(-1));
75753
    } else {
75754
      return reinterpret_cast<const char *>(token.peek());
75755
    }
75756
  }
75757
  if (at_end()) {
75758
    return OUT_OF_BOUNDS;
75759
  }
75760
  return reinterpret_cast<const char *>(token.peek());
75761
}
75762
75763
simdjson_inline bool json_iterator::is_alive() const noexcept {
75764
  return parser;
75765
}
75766
75767
simdjson_inline void json_iterator::abandon() noexcept {
75768
  parser = nullptr;
75769
  _depth = 0;
75770
}
75771
75772
simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
75773
#if SIMDJSON_CHECK_EOF
75774
  assert_more_tokens();
75775
#endif // SIMDJSON_CHECK_EOF
75776
  return token.return_current_and_advance();
75777
}
75778
75779
simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
75780
  // deliberately done without safety guard:
75781
  return token.peek();
75782
}
75783
75784
simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
75785
#if SIMDJSON_CHECK_EOF
75786
  assert_more_tokens(delta+1);
75787
#endif // SIMDJSON_CHECK_EOF
75788
  return token.peek(delta);
75789
}
75790
75791
simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
75792
#if SIMDJSON_CHECK_EOF
75793
  assert_more_tokens(delta+1);
75794
#endif // #if SIMDJSON_CHECK_EOF
75795
  return token.peek_length(delta);
75796
}
75797
75798
simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
75799
  // todo: currently we require end-of-string buffering, but the following
75800
  // assert_valid_position should be turned on if/when we lift that condition.
75801
  // assert_valid_position(position);
75802
  // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
75803
  // is ON by default, we have no choice but to disable it for real with a comment.
75804
  return token.peek(position);
75805
}
75806
75807
simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
75808
#if SIMDJSON_CHECK_EOF
75809
  assert_valid_position(position);
75810
#endif // SIMDJSON_CHECK_EOF
75811
  return token.peek_length(position);
75812
}
75813
simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept {
75814
#if SIMDJSON_CHECK_EOF
75815
  assert_valid_position(position);
75816
#endif // SIMDJSON_CHECK_EOF
75817
  return token.peek_root_length(position);
75818
}
75819
75820
simdjson_inline token_position json_iterator::last_position() const noexcept {
75821
  // The following line fails under some compilers...
75822
  // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0);
75823
  // since it has side-effects.
75824
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
75825
  SIMDJSON_ASSUME(n_structural_indexes > 0);
75826
  return &parser->implementation->structural_indexes[n_structural_indexes - 1];
75827
}
75828
simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept {
75829
  return token.peek(last_position());
75830
}
75831
75832
simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
75833
  SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
75834
  SIMDJSON_ASSUME(_depth == parent_depth + 1);
75835
  _depth = parent_depth;
75836
}
75837
75838
simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
75839
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
75840
  SIMDJSON_ASSUME(_depth == child_depth - 1);
75841
  _depth = child_depth;
75842
}
75843
75844
simdjson_inline depth_t json_iterator::depth() const noexcept {
75845
  return _depth;
75846
}
75847
75848
simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
75849
  return _string_buf_loc;
75850
}
75851
75852
simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept {
75853
  SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD);
75854
  logger::log_error(*this, message);
75855
  error = _error;
75856
  return error;
75857
}
75858
75859
simdjson_inline token_position json_iterator::position() const noexcept {
75860
  return token.position();
75861
}
75862
75863
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept {
75864
  return parser->unescape(in, _string_buf_loc, allow_replacement);
75865
}
75866
75867
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in) noexcept {
75868
  return parser->unescape_wobbly(in, _string_buf_loc);
75869
}
75870
75871
simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
75872
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
75873
  SIMDJSON_ASSUME(_depth == child_depth - 1);
75874
#if SIMDJSON_DEVELOPMENT_CHECKS
75875
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
75876
  SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
75877
  SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
75878
#endif
75879
#endif
75880
  token.set_position(position);
75881
  _depth = child_depth;
75882
}
75883
75884
simdjson_inline error_code json_iterator::consume_character(char c) noexcept {
75885
  if (*peek() == c) {
75886
    return_current_and_advance();
75887
    return SUCCESS;
75888
  }
75889
  return TAPE_ERROR;
75890
}
75891
75892
#if SIMDJSON_DEVELOPMENT_CHECKS
75893
75894
simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
75895
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
75896
  return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
75897
}
75898
75899
simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
75900
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
75901
  if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
75902
}
75903
75904
#endif
75905
75906
75907
simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept {
75908
  SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD);
75909
  logger::log_error(*this, message);
75910
  return _error;
75911
}
75912
75913
75914
simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept {
75915
  // This function is not expected to be called in performance-sensitive settings.
75916
  // Let us guard against silly cases:
75917
  if((N < max_len) || (N == 0)) { return false; }
75918
  // Copy to the buffer.
75919
  std::memcpy(tmpbuf, json, max_len);
75920
  if(N > max_len) { // We pad whatever remains with ' '.
75921
    std::memset(tmpbuf + max_len, ' ', N - max_len);
75922
  }
75923
  return true;
75924
}
75925
75926
} // namespace ondemand
75927
} // namespace ppc64
75928
} // namespace simdjson
75929
75930
namespace simdjson {
75931
75932
simdjson_inline simdjson_result<ppc64::ondemand::json_iterator>::simdjson_result(ppc64::ondemand::json_iterator &&value) noexcept
75933
    : implementation_simdjson_result_base<ppc64::ondemand::json_iterator>(std::forward<ppc64::ondemand::json_iterator>(value)) {}
75934
simdjson_inline simdjson_result<ppc64::ondemand::json_iterator>::simdjson_result(error_code error) noexcept
75935
    : implementation_simdjson_result_base<ppc64::ondemand::json_iterator>(error) {}
75936
75937
} // namespace simdjson
75938
75939
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
75940
/* end file simdjson/generic/ondemand/json_iterator-inl.h for ppc64 */
75941
/* including simdjson/generic/ondemand/json_type-inl.h for ppc64: #include "simdjson/generic/ondemand/json_type-inl.h" */
75942
/* begin file simdjson/generic/ondemand/json_type-inl.h for ppc64 */
75943
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
75944
75945
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
75946
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */
75947
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
75948
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
75949
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
75950
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
75951
75952
namespace simdjson {
75953
namespace ppc64 {
75954
namespace ondemand {
75955
75956
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
75957
    switch (type) {
75958
        case json_type::array: out << "array"; break;
75959
        case json_type::object: out << "object"; break;
75960
        case json_type::number: out << "number"; break;
75961
        case json_type::string: out << "string"; break;
75962
        case json_type::boolean: out << "boolean"; break;
75963
        case json_type::null: out << "null"; break;
75964
        default: SIMDJSON_UNREACHABLE();
75965
    }
75966
    return out;
75967
}
75968
75969
#if SIMDJSON_EXCEPTIONS
75970
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
75971
    return out << type.value();
75972
}
75973
#endif
75974
75975
75976
75977
simdjson_inline number_type number::get_number_type() const noexcept {
75978
  return type;
75979
}
75980
75981
simdjson_inline bool number::is_uint64() const noexcept {
75982
  return get_number_type() == number_type::unsigned_integer;
75983
}
75984
75985
simdjson_inline uint64_t number::get_uint64() const noexcept {
75986
  return payload.unsigned_integer;
75987
}
75988
75989
simdjson_inline number::operator uint64_t() const noexcept {
75990
  return get_uint64();
75991
}
75992
75993
simdjson_inline bool number::is_int64() const noexcept {
75994
  return get_number_type() == number_type::signed_integer;
75995
}
75996
75997
simdjson_inline int64_t number::get_int64() const noexcept {
75998
  return payload.signed_integer;
75999
}
76000
76001
simdjson_inline number::operator int64_t() const noexcept {
76002
  return get_int64();
76003
}
76004
76005
simdjson_inline bool number::is_double() const noexcept {
76006
    return get_number_type() == number_type::floating_point_number;
76007
}
76008
76009
simdjson_inline double number::get_double() const noexcept {
76010
  return payload.floating_point_number;
76011
}
76012
76013
simdjson_inline number::operator double() const noexcept {
76014
  return get_double();
76015
}
76016
76017
simdjson_inline double number::as_double() const noexcept {
76018
  if(is_double()) {
76019
    return payload.floating_point_number;
76020
  }
76021
  if(is_int64()) {
76022
    return double(payload.signed_integer);
76023
  }
76024
  return double(payload.unsigned_integer);
76025
}
76026
76027
simdjson_inline void number::append_s64(int64_t value) noexcept {
76028
  payload.signed_integer = value;
76029
  type = number_type::signed_integer;
76030
}
76031
76032
simdjson_inline void number::append_u64(uint64_t value) noexcept {
76033
  payload.unsigned_integer = value;
76034
  type = number_type::unsigned_integer;
76035
}
76036
76037
simdjson_inline void number::append_double(double value) noexcept {
76038
  payload.floating_point_number = value;
76039
  type = number_type::floating_point_number;
76040
}
76041
76042
simdjson_inline void number::skip_double() noexcept {
76043
  type = number_type::floating_point_number;
76044
}
76045
76046
} // namespace ondemand
76047
} // namespace ppc64
76048
} // namespace simdjson
76049
76050
namespace simdjson {
76051
76052
simdjson_inline simdjson_result<ppc64::ondemand::json_type>::simdjson_result(ppc64::ondemand::json_type &&value) noexcept
76053
    : implementation_simdjson_result_base<ppc64::ondemand::json_type>(std::forward<ppc64::ondemand::json_type>(value)) {}
76054
simdjson_inline simdjson_result<ppc64::ondemand::json_type>::simdjson_result(error_code error) noexcept
76055
    : implementation_simdjson_result_base<ppc64::ondemand::json_type>(error) {}
76056
76057
} // namespace simdjson
76058
76059
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
76060
/* end file simdjson/generic/ondemand/json_type-inl.h for ppc64 */
76061
/* including simdjson/generic/ondemand/logger-inl.h for ppc64: #include "simdjson/generic/ondemand/logger-inl.h" */
76062
/* begin file simdjson/generic/ondemand/logger-inl.h for ppc64 */
76063
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
76064
76065
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
76066
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */
76067
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
76068
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
76069
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
76070
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
76071
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
76072
76073
#include <memory>
76074
#include <cstring>
76075
76076
namespace simdjson {
76077
namespace ppc64 {
76078
namespace ondemand {
76079
namespace logger {
76080
76081
static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
76082
static constexpr const int LOG_EVENT_LEN = 20;
76083
static constexpr const int LOG_BUFFER_LEN = 30;
76084
static constexpr const int LOG_SMALL_BUFFER_LEN = 10;
76085
static int log_depth = 0; // Not threadsafe. Log only.
76086
76087
// Helper to turn unprintable or newline characters into spaces
76088
static inline char printable_char(char c) {
76089
  if (c >= 0x20) {
76090
    return c;
76091
  } else {
76092
    return ' ';
76093
  }
76094
}
76095
76096
template<typename... Args>
76097
static inline std::string string_format(const std::string& format, const Args&... args)
76098
{
76099
  SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
76100
  int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
76101
  auto size = static_cast<size_t>(size_s);
76102
  if (size <= 0) return std::string();
76103
  std::unique_ptr<char[]> buf(new char[size]);
76104
  std::snprintf(buf.get(), size, format.c_str(), args...);
76105
  SIMDJSON_POP_DISABLE_WARNINGS
76106
  return std::string(buf.get(), buf.get() + size - 1);
76107
}
76108
76109
static inline log_level get_log_level_from_env()
76110
{
76111
  SIMDJSON_PUSH_DISABLE_WARNINGS
76112
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
76113
      char *lvl = getenv("SIMDJSON_LOG_LEVEL");
76114
  SIMDJSON_POP_DISABLE_WARNINGS
76115
  if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; }
76116
  return log_level::info;
76117
}
76118
76119
static inline log_level log_threshold()
76120
{
76121
  static log_level threshold = get_log_level_from_env();
76122
  return threshold;
76123
}
76124
76125
static inline bool should_log(log_level level)
76126
{
76127
  return level >= log_threshold();
76128
}
76129
76130
inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
76131
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
76132
}
76133
76134
inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
76135
  log_line(iter, index, depth, "", type, detail, log_level::info);
76136
}
76137
inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
76138
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
76139
}
76140
76141
inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
76142
  log_line(iter, index, depth, "+", type, detail, log_level::info);
76143
  if (LOG_ENABLED) { log_depth++; }
76144
}
76145
inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
76146
  log_line(iter, "+", type, "", delta, depth_delta, log_level::info);
76147
  if (LOG_ENABLED) { log_depth++; }
76148
}
76149
76150
inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
76151
  if (LOG_ENABLED) { log_depth--; }
76152
  log_line(iter, "-", type, "", delta, depth_delta, log_level::info);
76153
}
76154
76155
inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
76156
  log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error);
76157
}
76158
inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept {
76159
  log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error);
76160
}
76161
76162
inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
76163
  log_event(iter.json_iter(), type, detail, delta, depth_delta);
76164
}
76165
76166
inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
76167
  log_value(iter.json_iter(), type, detail, delta, depth_delta);
76168
}
76169
76170
inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
76171
  log_start_value(iter.json_iter(), type, delta, depth_delta);
76172
}
76173
76174
inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
76175
  log_end_value(iter.json_iter(), type, delta, depth_delta);
76176
}
76177
76178
inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
76179
  log_error(iter.json_iter(), error, detail, delta, depth_delta);
76180
}
76181
76182
inline void log_headers() noexcept {
76183
  if (LOG_ENABLED) {
76184
    if (simdjson_unlikely(should_log(log_level::info))) {
76185
      // Technically a static variable is not thread-safe, but if you are using threads and logging... well...
76186
      static bool displayed_hint{false};
76187
      log_depth = 0;
76188
      printf("\n");
76189
      if (!displayed_hint) {
76190
        // We only print this helpful header once.
76191
        printf("# Logging provides the depth and position of the iterator user-visible steps:\n");
76192
        printf("# +array says 'this is where we were when we discovered the start array'\n");
76193
        printf(
76194
            "# -array says 'this is where we were when we ended the array'\n");
76195
        printf("# skip says 'this is a structural or value I am skipping'\n");
76196
        printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
76197
        printf("#\n");
76198
        printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
76199
        printf("# in addition to the depth being displayed.\n");
76200
        printf("#\n");
76201
        printf("# Every token in the document has a single depth determined by the tokens before it,\n");
76202
        printf("# and is not affected by what the token actually is.\n");
76203
        printf("#\n");
76204
        printf("# Not all structural elements are presented as tokens in the logs.\n");
76205
        printf("#\n");
76206
        printf("# We never give control to the user within an empty array or an empty object.\n");
76207
        printf("#\n");
76208
        printf("# Inside an array, having a depth greater than the array's depth means that\n");
76209
        printf("# we are pointing inside a value.\n");
76210
        printf("# Having a depth equal to the array means that we are pointing right before a value.\n");
76211
        printf("# Having a depth smaller than the array means that we have moved beyond the array.\n");
76212
        displayed_hint = true;
76213
      }
76214
      printf("\n");
76215
      printf("| %-*s ", LOG_EVENT_LEN, "Event");
76216
      printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
76217
      printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next");
76218
      // printf("| %-*s ", 5,                    "Next#");
76219
      printf("| %-*s ", 5, "Depth");
76220
      printf("| Detail ");
76221
      printf("|\n");
76222
76223
      printf("|%.*s", LOG_EVENT_LEN + 2, DASHES);
76224
      printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES);
76225
      printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
76226
      // printf("|%.*s", 5+2, DASHES);
76227
      printf("|%.*s", 5 + 2, DASHES);
76228
      printf("|--------");
76229
      printf("|\n");
76230
      fflush(stdout);
76231
    }
76232
  }
76233
}
76234
76235
template <typename... Args>
76236
inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept {
76237
  log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
76238
}
76239
76240
template <typename... Args>
76241
inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
76242
  if (LOG_ENABLED) {
76243
    if (simdjson_unlikely(should_log(level))) {
76244
      const int indent = depth * 2;
76245
      const auto buf = iter.token.buf;
76246
      auto msg = string_format(title, std::forward<Args>(args)...);
76247
      printf("| %*s%s%-*s ", indent, "", title_prefix,
76248
             LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str());
76249
      {
76250
        // Print the current structural.
76251
        printf("| ");
76252
        // Before we begin, the index might point right before the document.
76253
        // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
76254
        if (index < iter._root) {
76255
          printf("%*s", LOG_BUFFER_LEN, "");
76256
        } else {
76257
          auto current_structural = &buf[*index];
76258
          for (int i = 0; i < LOG_BUFFER_LEN; i++) {
76259
            printf("%c", printable_char(current_structural[i]));
76260
          }
76261
        }
76262
        printf(" ");
76263
      }
76264
      {
76265
        // Print the next structural.
76266
        printf("| ");
76267
        auto next_structural = &buf[*(index + 1)];
76268
        for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
76269
          printf("%c", printable_char(next_structural[i]));
76270
        }
76271
        printf(" ");
76272
      }
76273
      // printf("| %5u ", *(index+1));
76274
      printf("| %5i ", depth);
76275
      printf("| %6.*s ", int(detail.size()), detail.data());
76276
      printf("|\n");
76277
      fflush(stdout);
76278
    }
76279
  }
76280
}
76281
76282
} // namespace logger
76283
} // namespace ondemand
76284
} // namespace ppc64
76285
} // namespace simdjson
76286
76287
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
76288
/* end file simdjson/generic/ondemand/logger-inl.h for ppc64 */
76289
/* including simdjson/generic/ondemand/object-inl.h for ppc64: #include "simdjson/generic/ondemand/object-inl.h" */
76290
/* begin file simdjson/generic/ondemand/object-inl.h for ppc64 */
76291
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
76292
76293
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
76294
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */
76295
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
76296
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
76297
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
76298
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
76299
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
76300
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
76301
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
76302
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
76303
76304
namespace simdjson {
76305
namespace ppc64 {
76306
namespace ondemand {
76307
76308
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
76309
  bool has_value;
76310
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
76311
  if (!has_value) {
76312
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
76313
    return NO_SUCH_FIELD;
76314
  }
76315
  return value(iter.child());
76316
}
76317
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
76318
  bool has_value;
76319
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
76320
  if (!has_value) {
76321
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
76322
    return NO_SUCH_FIELD;
76323
  }
76324
  return value(iter.child());
76325
}
76326
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
76327
  return find_field_unordered(key);
76328
}
76329
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
76330
  return std::forward<object>(*this).find_field_unordered(key);
76331
}
76332
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
76333
  bool has_value;
76334
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
76335
  if (!has_value) {
76336
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
76337
    return NO_SUCH_FIELD;
76338
  }
76339
  return value(iter.child());
76340
}
76341
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
76342
  bool has_value;
76343
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
76344
  if (!has_value) {
76345
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
76346
    return NO_SUCH_FIELD;
76347
  }
76348
  return value(iter.child());
76349
}
76350
76351
simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
76352
  SIMDJSON_TRY( iter.start_object().error() );
76353
  return object(iter);
76354
}
76355
simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
76356
  SIMDJSON_TRY( iter.start_root_object().error() );
76357
  return object(iter);
76358
}
76359
simdjson_inline error_code object::consume() noexcept {
76360
  if(iter.is_at_key()) {
76361
    /**
76362
     * whenever you are pointing at a key, calling skip_child() is
76363
     * unsafe because you will hit a string and you will assume that
76364
     * it is string value, and this mistake will lead you to make bad
76365
     * depth computation.
76366
     */
76367
    /**
76368
     * We want to 'consume' the key. We could really
76369
     * just do _json_iter->return_current_and_advance(); at this
76370
     * point, but, for clarity, we will use the high-level API to
76371
     * eat the key. We assume that the compiler optimizes away
76372
     * most of the work.
76373
     */
76374
    simdjson_unused raw_json_string actual_key;
76375
    auto error = iter.field_key().get(actual_key);
76376
    if (error) { iter.abandon(); return error; };
76377
    // Let us move to the value while we are at it.
76378
    if ((error = iter.field_value())) { iter.abandon(); return error; }
76379
  }
76380
  auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
76381
  if(error_skip) { iter.abandon(); }
76382
  return error_skip;
76383
}
76384
76385
simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
76386
  const uint8_t * starting_point{iter.peek_start()};
76387
  auto error = consume();
76388
  if(error) { return error; }
76389
  const uint8_t * final_point{iter._json_iter->peek()};
76390
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
76391
}
76392
76393
simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
76394
  SIMDJSON_TRY( iter.started_object().error() );
76395
  return object(iter);
76396
}
76397
76398
simdjson_inline object object::resume(const value_iterator &iter) noexcept {
76399
  return iter;
76400
}
76401
76402
simdjson_inline object::object(const value_iterator &_iter) noexcept
76403
  : iter{_iter}
76404
{
76405
}
76406
76407
simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
76408
#if SIMDJSON_DEVELOPMENT_CHECKS
76409
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
76410
#endif
76411
  return object_iterator(iter);
76412
}
76413
simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
76414
  return object_iterator(iter);
76415
}
76416
76417
inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
76418
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
76419
  json_pointer = json_pointer.substr(1);
76420
  size_t slash = json_pointer.find('/');
76421
  std::string_view key = json_pointer.substr(0, slash);
76422
  // Grab the child with the given key
76423
  simdjson_result<value> child;
76424
76425
  // If there is an escape character in the key, unescape it and then get the child.
76426
  size_t escape = key.find('~');
76427
  if (escape != std::string_view::npos) {
76428
    // Unescape the key
76429
    std::string unescaped(key);
76430
    do {
76431
      switch (unescaped[escape+1]) {
76432
        case '0':
76433
          unescaped.replace(escape, 2, "~");
76434
          break;
76435
        case '1':
76436
          unescaped.replace(escape, 2, "/");
76437
          break;
76438
        default:
76439
          return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
76440
      }
76441
      escape = unescaped.find('~', escape+1);
76442
    } while (escape != std::string::npos);
76443
    child = find_field(unescaped);  // Take note find_field does not unescape keys when matching
76444
  } else {
76445
    child = find_field(key);
76446
  }
76447
  if(child.error()) {
76448
    return child; // we do not continue if there was an error
76449
  }
76450
  // If there is a /, we have to recurse and look up more of the path
76451
  if (slash != std::string_view::npos) {
76452
    child = child.at_pointer(json_pointer.substr(slash));
76453
  }
76454
  return child;
76455
}
76456
76457
inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
76458
  auto json_pointer = json_path_to_pointer_conversion(json_path);
76459
  if (json_pointer == "-1") {
76460
    return INVALID_JSON_POINTER;
76461
  }
76462
  return at_pointer(json_pointer);
76463
}
76464
76465
simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
76466
  size_t count{0};
76467
  // Important: we do not consume any of the values.
76468
  for(simdjson_unused auto v : *this) { count++; }
76469
  // The above loop will always succeed, but we want to report errors.
76470
  if(iter.error()) { return iter.error(); }
76471
  // We need to move back at the start because we expect users to iterate through
76472
  // the object after counting the number of elements.
76473
  iter.reset_object();
76474
  return count;
76475
}
76476
76477
simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
76478
  bool is_not_empty;
76479
  auto error = iter.reset_object().get(is_not_empty);
76480
  if(error) { return error; }
76481
  return !is_not_empty;
76482
}
76483
76484
simdjson_inline simdjson_result<bool> object::reset() & noexcept {
76485
  return iter.reset_object();
76486
}
76487
76488
} // namespace ondemand
76489
} // namespace ppc64
76490
} // namespace simdjson
76491
76492
namespace simdjson {
76493
76494
simdjson_inline simdjson_result<ppc64::ondemand::object>::simdjson_result(ppc64::ondemand::object &&value) noexcept
76495
    : implementation_simdjson_result_base<ppc64::ondemand::object>(std::forward<ppc64::ondemand::object>(value)) {}
76496
simdjson_inline simdjson_result<ppc64::ondemand::object>::simdjson_result(error_code error) noexcept
76497
    : implementation_simdjson_result_base<ppc64::ondemand::object>(error) {}
76498
76499
simdjson_inline simdjson_result<ppc64::ondemand::object_iterator> simdjson_result<ppc64::ondemand::object>::begin() noexcept {
76500
  if (error()) { return error(); }
76501
  return first.begin();
76502
}
76503
simdjson_inline simdjson_result<ppc64::ondemand::object_iterator> simdjson_result<ppc64::ondemand::object>::end() noexcept {
76504
  if (error()) { return error(); }
76505
  return first.end();
76506
}
76507
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
76508
  if (error()) { return error(); }
76509
  return first.find_field_unordered(key);
76510
}
76511
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
76512
  if (error()) { return error(); }
76513
  return std::forward<ppc64::ondemand::object>(first).find_field_unordered(key);
76514
}
76515
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::operator[](std::string_view key) & noexcept {
76516
  if (error()) { return error(); }
76517
  return first[key];
76518
}
76519
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::operator[](std::string_view key) && noexcept {
76520
  if (error()) { return error(); }
76521
  return std::forward<ppc64::ondemand::object>(first)[key];
76522
}
76523
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::find_field(std::string_view key) & noexcept {
76524
  if (error()) { return error(); }
76525
  return first.find_field(key);
76526
}
76527
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::find_field(std::string_view key) && noexcept {
76528
  if (error()) { return error(); }
76529
  return std::forward<ppc64::ondemand::object>(first).find_field(key);
76530
}
76531
76532
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
76533
  if (error()) { return error(); }
76534
  return first.at_pointer(json_pointer);
76535
}
76536
76537
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::object>::at_path(
76538
    std::string_view json_path) noexcept {
76539
  if (error()) {
76540
    return error();
76541
  }
76542
  return first.at_path(json_path);
76543
}
76544
76545
inline simdjson_result<bool> simdjson_result<ppc64::ondemand::object>::reset() noexcept {
76546
  if (error()) { return error(); }
76547
  return first.reset();
76548
}
76549
76550
inline simdjson_result<bool> simdjson_result<ppc64::ondemand::object>::is_empty() noexcept {
76551
  if (error()) { return error(); }
76552
  return first.is_empty();
76553
}
76554
76555
simdjson_inline  simdjson_result<size_t> simdjson_result<ppc64::ondemand::object>::count_fields() & noexcept {
76556
  if (error()) { return error(); }
76557
  return first.count_fields();
76558
}
76559
76560
simdjson_inline  simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::object>::raw_json() noexcept {
76561
  if (error()) { return error(); }
76562
  return first.raw_json();
76563
}
76564
} // namespace simdjson
76565
76566
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
76567
/* end file simdjson/generic/ondemand/object-inl.h for ppc64 */
76568
/* including simdjson/generic/ondemand/object_iterator-inl.h for ppc64: #include "simdjson/generic/ondemand/object_iterator-inl.h" */
76569
/* begin file simdjson/generic/ondemand/object_iterator-inl.h for ppc64 */
76570
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
76571
76572
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
76573
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */
76574
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
76575
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
76576
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */
76577
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
76578
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
76579
76580
namespace simdjson {
76581
namespace ppc64 {
76582
namespace ondemand {
76583
76584
//
76585
// object_iterator
76586
//
76587
76588
simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
76589
  : iter{_iter}
76590
{}
76591
76592
simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
76593
  error_code error = iter.error();
76594
  if (error) { iter.abandon(); return error; }
76595
  auto result = field::start(iter);
76596
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
76597
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
76598
  if (result.error()) { iter.abandon(); }
76599
  return result;
76600
}
76601
simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
76602
  return !(*this != other);
76603
}
76604
simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
76605
  return iter.is_open();
76606
}
76607
76608
SIMDJSON_PUSH_DISABLE_WARNINGS
76609
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
76610
simdjson_inline object_iterator &object_iterator::operator++() noexcept {
76611
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
76612
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
76613
  if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
76614
76615
  simdjson_unused error_code error;
76616
  if ((error = iter.skip_child() )) { return *this; }
76617
76618
  simdjson_unused bool has_value;
76619
  if ((error = iter.has_next_field().get(has_value) )) { return *this; };
76620
  return *this;
76621
}
76622
SIMDJSON_POP_DISABLE_WARNINGS
76623
76624
//
76625
// ### Live States
76626
//
76627
// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
76628
// always SUCCESS:
76629
//
76630
// - Start: This is the state when the object is first found and the iterator is just past the {.
76631
//   In this state, at_start == true.
76632
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
76633
//   iterate over, the iterator is at the , or } before the next value. In this state,
76634
//   depth == iter.depth, at_start == false, and error == SUCCESS.
76635
// - Unfinished Business: When we hand an array/object to the user which they do not fully
76636
//   iterate over, we need to finish that iteration by skipping child values until we reach the
76637
//   Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
76638
//
76639
// ## Error States
76640
//
76641
// In error states, we will yield exactly one more value before stopping. iter.depth == depth
76642
// and at_start is always false. We decrement after yielding the error, moving to the Finished
76643
// state.
76644
//
76645
// - Chained Error: When the object iterator is part of an error chain--for example, in
76646
//   `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
76647
//   object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
76648
//   iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
76649
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
76650
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
76651
//   error == TAPE_ERROR, iter.depth == depth, and at_start == false.
76652
//
76653
// Errors that occur while reading a field to give to the user (such as when the key is not a
76654
// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
76655
// moving to the Finished state without transitioning through an Error state at all.
76656
//
76657
// ## Terminal State
76658
//
76659
// The terminal state has iter.depth < depth. at_start is always false.
76660
//
76661
// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
76662
//   In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
76663
//
76664
76665
} // namespace ondemand
76666
} // namespace ppc64
76667
} // namespace simdjson
76668
76669
namespace simdjson {
76670
76671
simdjson_inline simdjson_result<ppc64::ondemand::object_iterator>::simdjson_result(
76672
  ppc64::ondemand::object_iterator &&value
76673
) noexcept
76674
  : implementation_simdjson_result_base<ppc64::ondemand::object_iterator>(std::forward<ppc64::ondemand::object_iterator>(value))
76675
{
76676
  first.iter.assert_is_valid();
76677
}
76678
simdjson_inline simdjson_result<ppc64::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
76679
  : implementation_simdjson_result_base<ppc64::ondemand::object_iterator>({}, error)
76680
{
76681
}
76682
76683
simdjson_inline simdjson_result<ppc64::ondemand::field> simdjson_result<ppc64::ondemand::object_iterator>::operator*() noexcept {
76684
  if (error()) { return error(); }
76685
  return *first;
76686
}
76687
// If we're iterating and there is an error, return the error once.
76688
simdjson_inline bool simdjson_result<ppc64::ondemand::object_iterator>::operator==(const simdjson_result<ppc64::ondemand::object_iterator> &other) const noexcept {
76689
  if (!first.iter.is_valid()) { return !error(); }
76690
  return first == other.first;
76691
}
76692
// If we're iterating and there is an error, return the error once.
76693
simdjson_inline bool simdjson_result<ppc64::ondemand::object_iterator>::operator!=(const simdjson_result<ppc64::ondemand::object_iterator> &other) const noexcept {
76694
  if (!first.iter.is_valid()) { return error(); }
76695
  return first != other.first;
76696
}
76697
// Checks for ']' and ','
76698
simdjson_inline simdjson_result<ppc64::ondemand::object_iterator> &simdjson_result<ppc64::ondemand::object_iterator>::operator++() noexcept {
76699
  // Clear the error if there is one, so we don't yield it twice
76700
  if (error()) { second = SUCCESS; return *this; }
76701
  ++first;
76702
  return *this;
76703
}
76704
76705
} // namespace simdjson
76706
76707
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
76708
/* end file simdjson/generic/ondemand/object_iterator-inl.h for ppc64 */
76709
/* including simdjson/generic/ondemand/parser-inl.h for ppc64: #include "simdjson/generic/ondemand/parser-inl.h" */
76710
/* begin file simdjson/generic/ondemand/parser-inl.h for ppc64 */
76711
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
76712
76713
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
76714
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */
76715
/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */
76716
/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */
76717
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
76718
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
76719
/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */
76720
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
76721
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
76722
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
76723
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
76724
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
76725
76726
namespace simdjson {
76727
namespace ppc64 {
76728
namespace ondemand {
76729
76730
simdjson_inline parser::parser(size_t max_capacity) noexcept
76731
  : _max_capacity{max_capacity} {
76732
}
76733
76734
simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept {
76735
  if (new_capacity > max_capacity()) { return CAPACITY; }
76736
  if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; }
76737
76738
  // string_capacity copied from document::allocate
76739
  _capacity = 0;
76740
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64);
76741
  string_buf.reset(new (std::nothrow) uint8_t[string_capacity]);
76742
#if SIMDJSON_DEVELOPMENT_CHECKS
76743
  start_positions.reset(new (std::nothrow) token_position[new_max_depth]);
76744
#endif
76745
  if (implementation) {
76746
    SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
76747
    SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
76748
  } else {
76749
    SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
76750
  }
76751
  _capacity = new_capacity;
76752
  _max_depth = new_max_depth;
76753
  return SUCCESS;
76754
}
76755
76756
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(padded_string_view json) & noexcept {
76757
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
76758
76759
  json.remove_utf8_bom();
76760
76761
  // Allocate if needed
76762
  if (capacity() < json.length() || !string_buf) {
76763
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
76764
  }
76765
76766
  // Run stage 1.
76767
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
76768
  return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this });
76769
}
76770
76771
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const char *json, size_t len, size_t allocated) & noexcept {
76772
  return iterate(padded_string_view(json, len, allocated));
76773
}
76774
76775
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept {
76776
  return iterate(padded_string_view(json, len, allocated));
76777
}
76778
76779
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string_view json, size_t allocated) & noexcept {
76780
  return iterate(padded_string_view(json, allocated));
76781
}
76782
76783
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
76784
  if(json.capacity() - json.size() < SIMDJSON_PADDING) {
76785
    json.reserve(json.size() + SIMDJSON_PADDING);
76786
  }
76787
  return iterate(padded_string_view(json));
76788
}
76789
76790
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
76791
  return iterate(padded_string_view(json));
76792
}
76793
76794
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string_view> &result) & noexcept {
76795
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
76796
  SIMDJSON_TRY( result.error() );
76797
  padded_string_view json = result.value_unsafe();
76798
  return iterate(json);
76799
}
76800
76801
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
76802
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
76803
  SIMDJSON_TRY( result.error() );
76804
  const padded_string &json = result.value_unsafe();
76805
  return iterate(json);
76806
}
76807
76808
simdjson_warn_unused simdjson_inline simdjson_result<json_iterator> parser::iterate_raw(padded_string_view json) & noexcept {
76809
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
76810
76811
  json.remove_utf8_bom();
76812
76813
  // Allocate if needed
76814
  if (capacity() < json.length()) {
76815
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
76816
  }
76817
76818
  // Run stage 1.
76819
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
76820
  return json_iterator(reinterpret_cast<const uint8_t *>(json.data()), this);
76821
}
76822
76823
inline simdjson_result<document_stream> parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
76824
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
76825
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
76826
    buf += 3;
76827
    len -= 3;
76828
  }
76829
  if(allow_comma_separated && batch_size < len) { batch_size = len; }
76830
  return document_stream(*this, buf, len, batch_size, allow_comma_separated);
76831
}
76832
inline simdjson_result<document_stream> parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
76833
  return iterate_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size, allow_comma_separated);
76834
}
76835
inline simdjson_result<document_stream> parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept {
76836
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
76837
}
76838
inline simdjson_result<document_stream> parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept {
76839
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
76840
}
76841
76842
simdjson_inline size_t parser::capacity() const noexcept {
76843
  return _capacity;
76844
}
76845
simdjson_inline size_t parser::max_capacity() const noexcept {
76846
  return _max_capacity;
76847
}
76848
simdjson_inline size_t parser::max_depth() const noexcept {
76849
  return _max_depth;
76850
}
76851
76852
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
76853
  if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
76854
    _max_capacity = max_capacity;
76855
  } else {
76856
    _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
76857
  }
76858
}
76859
76860
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept {
76861
  uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement);
76862
  if (!end) { return STRING_ERROR; }
76863
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
76864
  dst = end;
76865
  return result;
76866
}
76867
76868
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept {
76869
  uint8_t *end = implementation->parse_wobbly_string(in.buf, dst);
76870
  if (!end) { return STRING_ERROR; }
76871
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
76872
  dst = end;
76873
  return result;
76874
}
76875
76876
} // namespace ondemand
76877
} // namespace ppc64
76878
} // namespace simdjson
76879
76880
namespace simdjson {
76881
76882
simdjson_inline simdjson_result<ppc64::ondemand::parser>::simdjson_result(ppc64::ondemand::parser &&value) noexcept
76883
    : implementation_simdjson_result_base<ppc64::ondemand::parser>(std::forward<ppc64::ondemand::parser>(value)) {}
76884
simdjson_inline simdjson_result<ppc64::ondemand::parser>::simdjson_result(error_code error) noexcept
76885
    : implementation_simdjson_result_base<ppc64::ondemand::parser>(error) {}
76886
76887
} // namespace simdjson
76888
76889
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
76890
/* end file simdjson/generic/ondemand/parser-inl.h for ppc64 */
76891
/* including simdjson/generic/ondemand/raw_json_string-inl.h for ppc64: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
76892
/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for ppc64 */
76893
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
76894
76895
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
76896
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */
76897
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
76898
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
76899
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
76900
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
76901
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
76902
76903
namespace simdjson {
76904
76905
namespace ppc64 {
76906
namespace ondemand {
76907
76908
simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
76909
76910
simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
76911
76912
76913
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
76914
  size_t pos{0};
76915
  // if the content has no escape character, just scan through it quickly!
76916
  for(;pos < target.size() && target[pos] != '\\';pos++) {}
76917
  // slow path may begin.
76918
  bool escaping{false};
76919
  for(;pos < target.size();pos++) {
76920
    if((target[pos] == '"') && !escaping) {
76921
      return false;
76922
    } else if(target[pos] == '\\') {
76923
      escaping = !escaping;
76924
    } else {
76925
      escaping = false;
76926
    }
76927
  }
76928
  return true;
76929
}
76930
76931
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
76932
  size_t pos{0};
76933
  // if the content has no escape character, just scan through it quickly!
76934
  for(;target[pos] && target[pos] != '\\';pos++) {}
76935
  // slow path may begin.
76936
  bool escaping{false};
76937
  for(;target[pos];pos++) {
76938
    if((target[pos] == '"') && !escaping) {
76939
      return false;
76940
    } else if(target[pos] == '\\') {
76941
      escaping = !escaping;
76942
    } else {
76943
      escaping = false;
76944
    }
76945
  }
76946
  return true;
76947
}
76948
76949
76950
simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
76951
  // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
76952
  return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
76953
}
76954
76955
simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
76956
  // Assumptions: does not contain unescaped quote characters, and
76957
  // the raw content is quote terminated within a valid JSON string.
76958
  if(target.size() <= SIMDJSON_PADDING) {
76959
    return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
76960
  }
76961
  const char * r{raw()};
76962
  size_t pos{0};
76963
  for(;pos < target.size();pos++) {
76964
    if(r[pos] != target[pos]) { return false; }
76965
  }
76966
  if(r[pos] != '"') { return false; }
76967
  return true;
76968
}
76969
76970
simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
76971
  const char * r{raw()};
76972
  size_t pos{0};
76973
  bool escaping{false};
76974
  for(;pos < target.size();pos++) {
76975
    if(r[pos] != target[pos]) { return false; }
76976
    // if target is a compile-time constant and it is free from
76977
    // quotes, then the next part could get optimized away through
76978
    // inlining.
76979
    if((target[pos] == '"') && !escaping) {
76980
      // We have reached the end of the raw_json_string but
76981
      // the target is not done.
76982
      return false;
76983
    } else if(target[pos] == '\\') {
76984
      escaping = !escaping;
76985
    } else {
76986
      escaping = false;
76987
    }
76988
  }
76989
  if(r[pos] != '"') { return false; }
76990
  return true;
76991
}
76992
76993
76994
simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
76995
  // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
76996
  // the raw content is quote terminated within a valid JSON string.
76997
  const char * r{raw()};
76998
  size_t pos{0};
76999
  for(;target[pos];pos++) {
77000
    if(r[pos] != target[pos]) { return false; }
77001
  }
77002
  if(r[pos] != '"') { return false; }
77003
  return true;
77004
}
77005
77006
simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
77007
  // Assumptions: does not contain unescaped quote characters, and
77008
  // the raw content is quote terminated within a valid JSON string.
77009
  const char * r{raw()};
77010
  size_t pos{0};
77011
  bool escaping{false};
77012
  for(;target[pos];pos++) {
77013
    if(r[pos] != target[pos]) { return false; }
77014
    // if target is a compile-time constant and it is free from
77015
    // quotes, then the next part could get optimized away through
77016
    // inlining.
77017
    if((target[pos] == '"') && !escaping) {
77018
      // We have reached the end of the raw_json_string but
77019
      // the target is not done.
77020
      return false;
77021
    } else if(target[pos] == '\\') {
77022
      escaping = !escaping;
77023
    } else {
77024
      escaping = false;
77025
    }
77026
  }
77027
  if(r[pos] != '"') { return false; }
77028
  return true;
77029
}
77030
77031
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
77032
  return a.unsafe_is_equal(c);
77033
}
77034
77035
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
77036
  return a == c;
77037
}
77038
77039
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
77040
  return !(a == c);
77041
}
77042
77043
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
77044
  return !(a == c);
77045
}
77046
77047
77048
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
77049
  return iter.unescape(*this, allow_replacement);
77050
}
77051
77052
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
77053
  return iter.unescape_wobbly(*this);
77054
}
77055
77056
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
77057
  bool in_escape = false;
77058
  const char *s = str.raw();
77059
  while (true) {
77060
    switch (*s) {
77061
      case '\\': in_escape = !in_escape; break;
77062
      case '"': if (in_escape) { in_escape = false; } else { return out; } break;
77063
      default: if (in_escape) { in_escape = false; }
77064
    }
77065
    out << *s;
77066
    s++;
77067
  }
77068
}
77069
77070
} // namespace ondemand
77071
} // namespace ppc64
77072
} // namespace simdjson
77073
77074
namespace simdjson {
77075
77076
simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string>::simdjson_result(ppc64::ondemand::raw_json_string &&value) noexcept
77077
    : implementation_simdjson_result_base<ppc64::ondemand::raw_json_string>(std::forward<ppc64::ondemand::raw_json_string>(value)) {}
77078
simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
77079
    : implementation_simdjson_result_base<ppc64::ondemand::raw_json_string>(error) {}
77080
77081
simdjson_inline simdjson_result<const char *> simdjson_result<ppc64::ondemand::raw_json_string>::raw() const noexcept {
77082
  if (error()) { return error(); }
77083
  return first.raw();
77084
}
77085
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::raw_json_string>::unescape(ppc64::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
77086
  if (error()) { return error(); }
77087
  return first.unescape(iter, allow_replacement);
77088
}
77089
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::raw_json_string>::unescape_wobbly(ppc64::ondemand::json_iterator &iter) const noexcept {
77090
  if (error()) { return error(); }
77091
  return first.unescape_wobbly(iter);
77092
}
77093
} // namespace simdjson
77094
77095
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
77096
/* end file simdjson/generic/ondemand/raw_json_string-inl.h for ppc64 */
77097
/* including simdjson/generic/ondemand/serialization-inl.h for ppc64: #include "simdjson/generic/ondemand/serialization-inl.h" */
77098
/* begin file simdjson/generic/ondemand/serialization-inl.h for ppc64 */
77099
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
77100
77101
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
77102
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */
77103
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
77104
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
77105
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
77106
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
77107
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
77108
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */
77109
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
77110
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
77111
77112
namespace simdjson {
77113
77114
inline std::string_view trim(const std::string_view str) noexcept {
77115
  // We can almost surely do better by rolling our own find_first_not_of function.
77116
  size_t first = str.find_first_not_of(" \t\n\r");
77117
  // If we have the empty string (just white space), then no trimming is possible, and
77118
  // we return the empty string_view.
77119
  if (std::string_view::npos == first) { return std::string_view(); }
77120
  size_t last = str.find_last_not_of(" \t\n\r");
77121
  return str.substr(first, (last - first + 1));
77122
}
77123
77124
77125
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::document& x) noexcept {
77126
  std::string_view v;
77127
  auto error = x.raw_json().get(v);
77128
  if(error) {return error; }
77129
  return trim(v);
77130
}
77131
77132
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::document_reference& x) noexcept {
77133
  std::string_view v;
77134
  auto error = x.raw_json().get(v);
77135
  if(error) {return error; }
77136
  return trim(v);
77137
}
77138
77139
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::value& x) noexcept {
77140
  /**
77141
   * If we somehow receive a value that has already been consumed,
77142
   * then the following code could be in trouble. E.g., we create
77143
   * an array as needed, but if an array was already created, then
77144
   * it could be bad.
77145
   */
77146
  using namespace ppc64::ondemand;
77147
  ppc64::ondemand::json_type t;
77148
  auto error = x.type().get(t);
77149
  if(error != SUCCESS) { return error; }
77150
  switch (t)
77151
  {
77152
    case json_type::array:
77153
    {
77154
      ppc64::ondemand::array array;
77155
      error = x.get_array().get(array);
77156
      if(error) { return error; }
77157
      return to_json_string(array);
77158
    }
77159
    case json_type::object:
77160
    {
77161
      ppc64::ondemand::object object;
77162
      error = x.get_object().get(object);
77163
      if(error) { return error; }
77164
      return to_json_string(object);
77165
    }
77166
    default:
77167
      return trim(x.raw_json_token());
77168
  }
77169
}
77170
77171
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::object& x) noexcept {
77172
  std::string_view v;
77173
  auto error = x.raw_json().get(v);
77174
  if(error) {return error; }
77175
  return trim(v);
77176
}
77177
77178
inline simdjson_result<std::string_view> to_json_string(ppc64::ondemand::array& x) noexcept {
77179
  std::string_view v;
77180
  auto error = x.raw_json().get(v);
77181
  if(error) {return error; }
77182
  return trim(v);
77183
}
77184
77185
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::document> x) {
77186
  if (x.error()) { return x.error(); }
77187
  return to_json_string(x.value_unsafe());
77188
}
77189
77190
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::document_reference> x) {
77191
  if (x.error()) { return x.error(); }
77192
  return to_json_string(x.value_unsafe());
77193
}
77194
77195
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::value> x) {
77196
  if (x.error()) { return x.error(); }
77197
  return to_json_string(x.value_unsafe());
77198
}
77199
77200
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::object> x) {
77201
  if (x.error()) { return x.error(); }
77202
  return to_json_string(x.value_unsafe());
77203
}
77204
77205
inline simdjson_result<std::string_view> to_json_string(simdjson_result<ppc64::ondemand::array> x) {
77206
  if (x.error()) { return x.error(); }
77207
  return to_json_string(x.value_unsafe());
77208
}
77209
} // namespace simdjson
77210
77211
namespace simdjson { namespace ppc64 { namespace ondemand {
77212
77213
#if SIMDJSON_EXCEPTIONS
77214
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::value x) {
77215
  std::string_view v;
77216
  auto error = simdjson::to_json_string(x).get(v);
77217
  if(error == simdjson::SUCCESS) {
77218
    return (out << v);
77219
  } else {
77220
    throw simdjson::simdjson_error(error);
77221
  }
77222
}
77223
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::value> x) {
77224
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
77225
  return (out << x.value());
77226
}
77227
#else
77228
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::value x) {
77229
  std::string_view v;
77230
  auto error = simdjson::to_json_string(x).get(v);
77231
  if(error == simdjson::SUCCESS) {
77232
    return (out << v);
77233
  } else {
77234
    return (out << error);
77235
  }
77236
}
77237
#endif
77238
77239
#if SIMDJSON_EXCEPTIONS
77240
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::array value) {
77241
  std::string_view v;
77242
  auto error = simdjson::to_json_string(value).get(v);
77243
  if(error == simdjson::SUCCESS) {
77244
    return (out << v);
77245
  } else {
77246
    throw simdjson::simdjson_error(error);
77247
  }
77248
}
77249
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::array> x) {
77250
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
77251
  return (out << x.value());
77252
}
77253
#else
77254
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::array value) {
77255
  std::string_view v;
77256
  auto error = simdjson::to_json_string(value).get(v);
77257
  if(error == simdjson::SUCCESS) {
77258
    return (out << v);
77259
  } else {
77260
    return (out << error);
77261
  }
77262
}
77263
#endif
77264
77265
#if SIMDJSON_EXCEPTIONS
77266
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::document& value)  {
77267
  std::string_view v;
77268
  auto error = simdjson::to_json_string(value).get(v);
77269
  if(error == simdjson::SUCCESS) {
77270
    return (out << v);
77271
  } else {
77272
    throw simdjson::simdjson_error(error);
77273
  }
77274
}
77275
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::document_reference& value)  {
77276
  std::string_view v;
77277
  auto error = simdjson::to_json_string(value).get(v);
77278
  if(error == simdjson::SUCCESS) {
77279
    return (out << v);
77280
  } else {
77281
    throw simdjson::simdjson_error(error);
77282
  }
77283
}
77284
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::document>&& x) {
77285
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
77286
  return (out << x.value());
77287
}
77288
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::ppc64::ondemand::document_reference>&& x) {
77289
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
77290
  return (out << x.value());
77291
}
77292
#else
77293
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::document& value)  {
77294
  std::string_view v;
77295
  auto error = simdjson::to_json_string(value).get(v);
77296
  if(error == simdjson::SUCCESS) {
77297
    return (out << v);
77298
  } else {
77299
    return (out << error);
77300
  }
77301
}
77302
#endif
77303
77304
#if SIMDJSON_EXCEPTIONS
77305
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::object value) {
77306
  std::string_view v;
77307
  auto error = simdjson::to_json_string(value).get(v);
77308
  if(error == simdjson::SUCCESS) {
77309
    return (out << v);
77310
  } else {
77311
    throw simdjson::simdjson_error(error);
77312
  }
77313
}
77314
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::ppc64::ondemand::object> x) {
77315
  if (x.error()) { throw  simdjson::simdjson_error(x.error()); }
77316
  return (out << x.value());
77317
}
77318
#else
77319
inline std::ostream& operator<<(std::ostream& out, simdjson::ppc64::ondemand::object value) {
77320
  std::string_view v;
77321
  auto error = simdjson::to_json_string(value).get(v);
77322
  if(error == simdjson::SUCCESS) {
77323
    return (out << v);
77324
  } else {
77325
    return (out << error);
77326
  }
77327
}
77328
#endif
77329
}}} // namespace simdjson::ppc64::ondemand
77330
77331
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
77332
/* end file simdjson/generic/ondemand/serialization-inl.h for ppc64 */
77333
/* including simdjson/generic/ondemand/token_iterator-inl.h for ppc64: #include "simdjson/generic/ondemand/token_iterator-inl.h" */
77334
/* begin file simdjson/generic/ondemand/token_iterator-inl.h for ppc64 */
77335
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
77336
77337
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
77338
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */
77339
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
77340
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
77341
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
77342
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
77343
77344
namespace simdjson {
77345
namespace ppc64 {
77346
namespace ondemand {
77347
77348
simdjson_inline token_iterator::token_iterator(
77349
  const uint8_t *_buf,
77350
  token_position position
77351
) noexcept : buf{_buf}, _position{position}
77352
{
77353
}
77354
77355
simdjson_inline uint32_t token_iterator::current_offset() const noexcept {
77356
  return *(_position);
77357
}
77358
77359
77360
simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept {
77361
  return &buf[*(_position++)];
77362
}
77363
77364
simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept {
77365
  return &buf[*position];
77366
}
77367
simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept {
77368
  return *position;
77369
}
77370
simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept {
77371
  return *(position+1) - *position;
77372
}
77373
77374
simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept {
77375
  return *(position+2) - *(position) > *(position+1) - *(position) ?
77376
      *(position+1) - *(position)
77377
      : *(position+2) - *(position);
77378
}
77379
simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept {
77380
  return &buf[*(_position+delta)];
77381
}
77382
simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept {
77383
  return *(_position+delta);
77384
}
77385
simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept {
77386
  return *(_position+delta+1) - *(_position+delta);
77387
}
77388
77389
simdjson_inline token_position token_iterator::position() const noexcept {
77390
  return _position;
77391
}
77392
simdjson_inline void token_iterator::set_position(token_position target_position) noexcept {
77393
  _position = target_position;
77394
}
77395
77396
simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept {
77397
  return _position == other._position;
77398
}
77399
simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept {
77400
  return _position != other._position;
77401
}
77402
simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept {
77403
  return _position > other._position;
77404
}
77405
simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept {
77406
  return _position >= other._position;
77407
}
77408
simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept {
77409
  return _position < other._position;
77410
}
77411
simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept {
77412
  return _position <= other._position;
77413
}
77414
77415
} // namespace ondemand
77416
} // namespace ppc64
77417
} // namespace simdjson
77418
77419
namespace simdjson {
77420
77421
simdjson_inline simdjson_result<ppc64::ondemand::token_iterator>::simdjson_result(ppc64::ondemand::token_iterator &&value) noexcept
77422
    : implementation_simdjson_result_base<ppc64::ondemand::token_iterator>(std::forward<ppc64::ondemand::token_iterator>(value)) {}
77423
simdjson_inline simdjson_result<ppc64::ondemand::token_iterator>::simdjson_result(error_code error) noexcept
77424
    : implementation_simdjson_result_base<ppc64::ondemand::token_iterator>(error) {}
77425
77426
} // namespace simdjson
77427
77428
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
77429
/* end file simdjson/generic/ondemand/token_iterator-inl.h for ppc64 */
77430
/* including simdjson/generic/ondemand/value-inl.h for ppc64: #include "simdjson/generic/ondemand/value-inl.h" */
77431
/* begin file simdjson/generic/ondemand/value-inl.h for ppc64 */
77432
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
77433
77434
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
77435
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */
77436
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
77437
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
77438
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
77439
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
77440
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
77441
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
77442
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
77443
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
77444
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
77445
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
77446
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
77447
77448
namespace simdjson {
77449
namespace ppc64 {
77450
namespace ondemand {
77451
77452
simdjson_inline value::value(const value_iterator &_iter) noexcept
77453
  : iter{_iter}
77454
{
77455
}
77456
simdjson_inline value value::start(const value_iterator &iter) noexcept {
77457
  return iter;
77458
}
77459
simdjson_inline value value::resume(const value_iterator &iter) noexcept {
77460
  return iter;
77461
}
77462
77463
simdjson_inline simdjson_result<array> value::get_array() noexcept {
77464
  return array::start(iter);
77465
}
77466
simdjson_inline simdjson_result<object> value::get_object() noexcept {
77467
  return object::start(iter);
77468
}
77469
simdjson_inline simdjson_result<object> value::start_or_resume_object() noexcept {
77470
  if (iter.at_start()) {
77471
    return get_object();
77472
  } else {
77473
    return object::resume(iter);
77474
  }
77475
}
77476
77477
simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
77478
  return iter.get_raw_json_string();
77479
}
77480
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
77481
  return iter.get_string(allow_replacement);
77482
}
77483
template <typename string_type>
77484
simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
77485
  return iter.get_string(receiver, allow_replacement);
77486
}
77487
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
77488
  return iter.get_wobbly_string();
77489
}
77490
simdjson_inline simdjson_result<double> value::get_double() noexcept {
77491
  return iter.get_double();
77492
}
77493
simdjson_inline simdjson_result<double> value::get_double_in_string() noexcept {
77494
  return iter.get_double_in_string();
77495
}
77496
simdjson_inline simdjson_result<uint64_t> value::get_uint64() noexcept {
77497
  return iter.get_uint64();
77498
}
77499
simdjson_inline simdjson_result<uint64_t> value::get_uint64_in_string() noexcept {
77500
  return iter.get_uint64_in_string();
77501
}
77502
simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
77503
  return iter.get_int64();
77504
}
77505
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
77506
  return iter.get_int64_in_string();
77507
}
77508
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
77509
  return iter.get_bool();
77510
}
77511
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
77512
  return iter.is_null();
77513
}
77514
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
77515
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
77516
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
77517
template<> simdjson_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(false); }
77518
template<> simdjson_inline simdjson_result<number> value::get() noexcept { return get_number(); }
77519
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
77520
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
77521
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
77522
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
77523
77524
template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
77525
  return get<T>().get(out);
77526
}
77527
77528
#if SIMDJSON_EXCEPTIONS
77529
template <class T>
77530
simdjson_inline value::operator T() noexcept(false) {
77531
  return get<T>();
77532
}
77533
simdjson_inline value::operator array() noexcept(false) {
77534
  return get_array();
77535
}
77536
simdjson_inline value::operator object() noexcept(false) {
77537
  return get_object();
77538
}
77539
simdjson_inline value::operator uint64_t() noexcept(false) {
77540
  return get_uint64();
77541
}
77542
simdjson_inline value::operator int64_t() noexcept(false) {
77543
  return get_int64();
77544
}
77545
simdjson_inline value::operator double() noexcept(false) {
77546
  return get_double();
77547
}
77548
simdjson_inline value::operator std::string_view() noexcept(false) {
77549
  return get_string(false);
77550
}
77551
simdjson_inline value::operator raw_json_string() noexcept(false) {
77552
  return get_raw_json_string();
77553
}
77554
simdjson_inline value::operator bool() noexcept(false) {
77555
  return get_bool();
77556
}
77557
#endif
77558
77559
simdjson_inline simdjson_result<array_iterator> value::begin() & noexcept {
77560
  return get_array().begin();
77561
}
77562
simdjson_inline simdjson_result<array_iterator> value::end() & noexcept {
77563
  return {};
77564
}
77565
simdjson_inline simdjson_result<size_t> value::count_elements() & noexcept {
77566
  simdjson_result<size_t> answer;
77567
  auto a = get_array();
77568
  answer = a.count_elements();
77569
  // count_elements leaves you pointing inside the array, at the first element.
77570
  // We need to move back so that the user can create a new array (which requires that
77571
  // we point at '[').
77572
  iter.move_at_start();
77573
  return answer;
77574
}
77575
simdjson_inline simdjson_result<size_t> value::count_fields() & noexcept {
77576
  simdjson_result<size_t> answer;
77577
  auto a = get_object();
77578
  answer = a.count_fields();
77579
  iter.move_at_start();
77580
  return answer;
77581
}
77582
simdjson_inline simdjson_result<value> value::at(size_t index) noexcept {
77583
  auto a = get_array();
77584
  return a.at(index);
77585
}
77586
77587
simdjson_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
77588
  return start_or_resume_object().find_field(key);
77589
}
77590
simdjson_inline simdjson_result<value> value::find_field(const char *key) noexcept {
77591
  return start_or_resume_object().find_field(key);
77592
}
77593
77594
simdjson_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
77595
  return start_or_resume_object().find_field_unordered(key);
77596
}
77597
simdjson_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
77598
  return start_or_resume_object().find_field_unordered(key);
77599
}
77600
77601
simdjson_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
77602
  return start_or_resume_object()[key];
77603
}
77604
simdjson_inline simdjson_result<value> value::operator[](const char *key) noexcept {
77605
  return start_or_resume_object()[key];
77606
}
77607
77608
simdjson_inline simdjson_result<json_type> value::type() noexcept {
77609
  return iter.type();
77610
}
77611
77612
simdjson_inline simdjson_result<bool> value::is_scalar() noexcept {
77613
  json_type this_type;
77614
  auto error = type().get(this_type);
77615
  if(error) { return error; }
77616
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
77617
}
77618
77619
simdjson_inline simdjson_result<bool> value::is_string() noexcept {
77620
  json_type this_type;
77621
  auto error = type().get(this_type);
77622
  if(error) { return error; }
77623
  return (this_type == json_type::string);
77624
}
77625
77626
77627
simdjson_inline bool value::is_negative() noexcept {
77628
  return iter.is_negative();
77629
}
77630
77631
simdjson_inline simdjson_result<bool> value::is_integer() noexcept {
77632
  return iter.is_integer();
77633
}
77634
simdjson_warn_unused simdjson_inline simdjson_result<number_type> value::get_number_type() noexcept {
77635
  return iter.get_number_type();
77636
}
77637
simdjson_warn_unused simdjson_inline simdjson_result<number> value::get_number() noexcept {
77638
  return iter.get_number();
77639
}
77640
77641
simdjson_inline std::string_view value::raw_json_token() noexcept {
77642
  return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
77643
}
77644
77645
simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
77646
  json_type t;
77647
  SIMDJSON_TRY(type().get(t));
77648
  switch (t)
77649
  {
77650
    case json_type::array: {
77651
      ondemand::array array;
77652
      SIMDJSON_TRY(get_array().get(array));
77653
      return array.raw_json();
77654
    }
77655
    case json_type::object: {
77656
      ondemand::object object;
77657
      SIMDJSON_TRY(get_object().get(object));
77658
      return object.raw_json();
77659
    }
77660
    default:
77661
      return raw_json_token();
77662
  }
77663
}
77664
77665
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
77666
  return iter.json_iter().current_location();
77667
}
77668
77669
simdjson_inline int32_t value::current_depth() const noexcept{
77670
  return iter.json_iter().depth();
77671
}
77672
77673
simdjson_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
77674
  json_type t;
77675
  SIMDJSON_TRY(type().get(t));
77676
  switch (t)
77677
  {
77678
    case json_type::array:
77679
      return (*this).get_array().at_pointer(json_pointer);
77680
    case json_type::object:
77681
      return (*this).get_object().at_pointer(json_pointer);
77682
    default:
77683
      return INVALID_JSON_POINTER;
77684
  }
77685
}
77686
77687
simdjson_inline simdjson_result<value> value::at_path(std::string_view json_path) noexcept {
77688
  json_type t;
77689
  SIMDJSON_TRY(type().get(t));
77690
  switch (t) {
77691
  case json_type::array:
77692
      return (*this).get_array().at_path(json_path);
77693
  case json_type::object:
77694
      return (*this).get_object().at_path(json_path);
77695
  default:
77696
      return INVALID_JSON_POINTER;
77697
  }
77698
}
77699
77700
} // namespace ondemand
77701
} // namespace ppc64
77702
} // namespace simdjson
77703
77704
namespace simdjson {
77705
77706
simdjson_inline simdjson_result<ppc64::ondemand::value>::simdjson_result(
77707
  ppc64::ondemand::value &&value
77708
) noexcept :
77709
    implementation_simdjson_result_base<ppc64::ondemand::value>(
77710
      std::forward<ppc64::ondemand::value>(value)
77711
    )
77712
{
77713
}
77714
simdjson_inline simdjson_result<ppc64::ondemand::value>::simdjson_result(
77715
  error_code error
77716
) noexcept :
77717
    implementation_simdjson_result_base<ppc64::ondemand::value>(error)
77718
{
77719
}
77720
simdjson_inline simdjson_result<size_t> simdjson_result<ppc64::ondemand::value>::count_elements() & noexcept {
77721
  if (error()) { return error(); }
77722
  return first.count_elements();
77723
}
77724
simdjson_inline simdjson_result<size_t> simdjson_result<ppc64::ondemand::value>::count_fields() & noexcept {
77725
  if (error()) { return error(); }
77726
  return first.count_fields();
77727
}
77728
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::at(size_t index) noexcept {
77729
  if (error()) { return error(); }
77730
  return first.at(index);
77731
}
77732
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::value>::begin() & noexcept {
77733
  if (error()) { return error(); }
77734
  return first.begin();
77735
}
77736
simdjson_inline simdjson_result<ppc64::ondemand::array_iterator> simdjson_result<ppc64::ondemand::value>::end() & noexcept {
77737
  if (error()) { return error(); }
77738
  return {};
77739
}
77740
77741
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::find_field(std::string_view key) noexcept {
77742
  if (error()) { return error(); }
77743
  return first.find_field(key);
77744
}
77745
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::find_field(const char *key) noexcept {
77746
  if (error()) { return error(); }
77747
  return first.find_field(key);
77748
}
77749
77750
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
77751
  if (error()) { return error(); }
77752
  return first.find_field_unordered(key);
77753
}
77754
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::find_field_unordered(const char *key) noexcept {
77755
  if (error()) { return error(); }
77756
  return first.find_field_unordered(key);
77757
}
77758
77759
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::operator[](std::string_view key) noexcept {
77760
  if (error()) { return error(); }
77761
  return first[key];
77762
}
77763
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::operator[](const char *key) noexcept {
77764
  if (error()) { return error(); }
77765
  return first[key];
77766
}
77767
77768
simdjson_inline simdjson_result<ppc64::ondemand::array> simdjson_result<ppc64::ondemand::value>::get_array() noexcept {
77769
  if (error()) { return error(); }
77770
  return first.get_array();
77771
}
77772
simdjson_inline simdjson_result<ppc64::ondemand::object> simdjson_result<ppc64::ondemand::value>::get_object() noexcept {
77773
  if (error()) { return error(); }
77774
  return first.get_object();
77775
}
77776
simdjson_inline simdjson_result<uint64_t> simdjson_result<ppc64::ondemand::value>::get_uint64() noexcept {
77777
  if (error()) { return error(); }
77778
  return first.get_uint64();
77779
}
77780
simdjson_inline simdjson_result<uint64_t> simdjson_result<ppc64::ondemand::value>::get_uint64_in_string() noexcept {
77781
  if (error()) { return error(); }
77782
  return first.get_uint64_in_string();
77783
}
77784
simdjson_inline simdjson_result<int64_t> simdjson_result<ppc64::ondemand::value>::get_int64() noexcept {
77785
  if (error()) { return error(); }
77786
  return first.get_int64();
77787
}
77788
simdjson_inline simdjson_result<int64_t> simdjson_result<ppc64::ondemand::value>::get_int64_in_string() noexcept {
77789
  if (error()) { return error(); }
77790
  return first.get_int64_in_string();
77791
}
77792
simdjson_inline simdjson_result<double> simdjson_result<ppc64::ondemand::value>::get_double() noexcept {
77793
  if (error()) { return error(); }
77794
  return first.get_double();
77795
}
77796
simdjson_inline simdjson_result<double> simdjson_result<ppc64::ondemand::value>::get_double_in_string() noexcept {
77797
  if (error()) { return error(); }
77798
  return first.get_double_in_string();
77799
}
77800
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::value>::get_string(bool allow_replacement) noexcept {
77801
  if (error()) { return error(); }
77802
  return first.get_string(allow_replacement);
77803
}
77804
template <typename string_type>
77805
simdjson_inline error_code simdjson_result<ppc64::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
77806
  if (error()) { return error(); }
77807
  return first.get_string(receiver, allow_replacement);
77808
}
77809
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::value>::get_wobbly_string() noexcept {
77810
  if (error()) { return error(); }
77811
  return first.get_wobbly_string();
77812
}
77813
simdjson_inline simdjson_result<ppc64::ondemand::raw_json_string> simdjson_result<ppc64::ondemand::value>::get_raw_json_string() noexcept {
77814
  if (error()) { return error(); }
77815
  return first.get_raw_json_string();
77816
}
77817
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::value>::get_bool() noexcept {
77818
  if (error()) { return error(); }
77819
  return first.get_bool();
77820
}
77821
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::value>::is_null() noexcept {
77822
  if (error()) { return error(); }
77823
  return first.is_null();
77824
}
77825
77826
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<ppc64::ondemand::value>::get() noexcept {
77827
  if (error()) { return error(); }
77828
  return first.get<T>();
77829
}
77830
template<typename T> simdjson_inline error_code simdjson_result<ppc64::ondemand::value>::get(T &out) noexcept {
77831
  if (error()) { return error(); }
77832
  return first.get<T>(out);
77833
}
77834
77835
template<> simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::get<ppc64::ondemand::value>() noexcept  {
77836
  if (error()) { return error(); }
77837
  return std::move(first);
77838
}
77839
template<> simdjson_inline error_code simdjson_result<ppc64::ondemand::value>::get<ppc64::ondemand::value>(ppc64::ondemand::value &out) noexcept {
77840
  if (error()) { return error(); }
77841
  out = first;
77842
  return SUCCESS;
77843
}
77844
77845
simdjson_inline simdjson_result<ppc64::ondemand::json_type> simdjson_result<ppc64::ondemand::value>::type() noexcept {
77846
  if (error()) { return error(); }
77847
  return first.type();
77848
}
77849
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::value>::is_scalar() noexcept {
77850
  if (error()) { return error(); }
77851
  return first.is_scalar();
77852
}
77853
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::value>::is_string() noexcept {
77854
  if (error()) { return error(); }
77855
  return first.is_string();
77856
}
77857
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::value>::is_negative() noexcept {
77858
  if (error()) { return error(); }
77859
  return first.is_negative();
77860
}
77861
simdjson_inline simdjson_result<bool> simdjson_result<ppc64::ondemand::value>::is_integer() noexcept {
77862
  if (error()) { return error(); }
77863
  return first.is_integer();
77864
}
77865
simdjson_inline simdjson_result<ppc64::number_type> simdjson_result<ppc64::ondemand::value>::get_number_type() noexcept {
77866
  if (error()) { return error(); }
77867
  return first.get_number_type();
77868
}
77869
simdjson_inline simdjson_result<ppc64::ondemand::number> simdjson_result<ppc64::ondemand::value>::get_number() noexcept {
77870
  if (error()) { return error(); }
77871
  return first.get_number();
77872
}
77873
#if SIMDJSON_EXCEPTIONS
77874
template <class T>
77875
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator T() noexcept(false) {
77876
  if (error()) { throw simdjson_error(error()); }
77877
  return static_cast<T>(first);
77878
}
77879
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator ppc64::ondemand::array() noexcept(false) {
77880
  if (error()) { throw simdjson_error(error()); }
77881
  return first;
77882
}
77883
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator ppc64::ondemand::object() noexcept(false) {
77884
  if (error()) { throw simdjson_error(error()); }
77885
  return first;
77886
}
77887
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator uint64_t() noexcept(false) {
77888
  if (error()) { throw simdjson_error(error()); }
77889
  return first;
77890
}
77891
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator int64_t() noexcept(false) {
77892
  if (error()) { throw simdjson_error(error()); }
77893
  return first;
77894
}
77895
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator double() noexcept(false) {
77896
  if (error()) { throw simdjson_error(error()); }
77897
  return first;
77898
}
77899
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator std::string_view() noexcept(false) {
77900
  if (error()) { throw simdjson_error(error()); }
77901
  return first;
77902
}
77903
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator ppc64::ondemand::raw_json_string() noexcept(false) {
77904
  if (error()) { throw simdjson_error(error()); }
77905
  return first;
77906
}
77907
simdjson_inline simdjson_result<ppc64::ondemand::value>::operator bool() noexcept(false) {
77908
  if (error()) { throw simdjson_error(error()); }
77909
  return first;
77910
}
77911
#endif
77912
77913
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::value>::raw_json_token() noexcept {
77914
  if (error()) { return error(); }
77915
  return first.raw_json_token();
77916
}
77917
77918
simdjson_inline simdjson_result<std::string_view> simdjson_result<ppc64::ondemand::value>::raw_json() noexcept {
77919
  if (error()) { return error(); }
77920
  return first.raw_json();
77921
}
77922
77923
simdjson_inline simdjson_result<const char *> simdjson_result<ppc64::ondemand::value>::current_location() noexcept {
77924
  if (error()) { return error(); }
77925
  return first.current_location();
77926
}
77927
77928
simdjson_inline simdjson_result<int32_t> simdjson_result<ppc64::ondemand::value>::current_depth() const noexcept {
77929
  if (error()) { return error(); }
77930
  return first.current_depth();
77931
}
77932
77933
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::at_pointer(
77934
    std::string_view json_pointer) noexcept {
77935
  if (error()) {
77936
      return error();
77937
  }
77938
  return first.at_pointer(json_pointer);
77939
}
77940
77941
simdjson_inline simdjson_result<ppc64::ondemand::value> simdjson_result<ppc64::ondemand::value>::at_path(
77942
      std::string_view json_path) noexcept {
77943
  if (error()) {
77944
    return error();
77945
  }
77946
  return first.at_path(json_path);
77947
}
77948
77949
} // namespace simdjson
77950
77951
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
77952
/* end file simdjson/generic/ondemand/value-inl.h for ppc64 */
77953
/* including simdjson/generic/ondemand/value_iterator-inl.h for ppc64: #include "simdjson/generic/ondemand/value_iterator-inl.h" */
77954
/* begin file simdjson/generic/ondemand/value_iterator-inl.h for ppc64 */
77955
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
77956
77957
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
77958
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */
77959
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
77960
/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */
77961
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
77962
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
77963
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */
77964
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
77965
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
77966
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
77967
77968
namespace simdjson {
77969
namespace ppc64 {
77970
namespace ondemand {
77971
77972
simdjson_inline value_iterator::value_iterator(
77973
  json_iterator *json_iter,
77974
  depth_t depth,
77975
  token_position start_position
77976
) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
77977
{
77978
}
77979
77980
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
77981
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
77982
  return started_object();
77983
}
77984
77985
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
77986
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
77987
  return started_root_object();
77988
}
77989
77990
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
77991
  assert_at_container_start();
77992
#if SIMDJSON_DEVELOPMENT_CHECKS
77993
  _json_iter->set_start_position(_depth, start_position());
77994
#endif
77995
  if (*_json_iter->peek() == '}') {
77996
    logger::log_value(*_json_iter, "empty object");
77997
    _json_iter->return_current_and_advance();
77998
    end_container();
77999
    return false;
78000
  }
78001
  return true;
78002
}
78003
78004
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
78005
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
78006
  // current document. It only works in the normal mode where we have indexed a single document.
78007
  // Note that adding a check for 'streaming' is not expensive since we only have at most
78008
  // one root element.
78009
  if ( ! _json_iter->streaming() ) {
78010
    // The following lines do not fully protect against garbage content within the
78011
    // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
78012
    // call `at_end()` on the document instance at the end of the processing to
78013
    // ensure that the processing has finished at the end.
78014
    //
78015
    if (*_json_iter->peek_last() != '}') {
78016
      _json_iter->abandon();
78017
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
78018
    }
78019
    // If the last character is } *and* the first gibberish character is also '}'
78020
    // then on-demand could accidentally go over. So we need additional checks.
78021
    // https://github.com/simdjson/simdjson/issues/1834
78022
    // Checking that the document is balanced requires a full scan which is potentially
78023
    // expensive, but it only happens in edge cases where the first padding character is
78024
    // a closing bracket.
78025
    if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
78026
      _json_iter->abandon();
78027
      // The exact error would require more work. It will typically be an unclosed object.
78028
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
78029
    }
78030
  }
78031
  return SUCCESS;
78032
}
78033
78034
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
78035
  auto error = check_root_object();
78036
  if(error) { return error; }
78037
  return started_object();
78038
}
78039
78040
simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
78041
#if SIMDJSON_CHECK_EOF
78042
    if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
78043
    // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
78044
#endif // SIMDJSON_CHECK_EOF
78045
    _json_iter->ascend_to(depth()-1);
78046
    return SUCCESS;
78047
}
78048
78049
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
78050
  assert_at_next();
78051
78052
  // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
78053
  // obligated to verify there are more tokens if they are not the top level.
78054
  switch (*_json_iter->return_current_and_advance()) {
78055
    case '}':
78056
      logger::log_end_value(*_json_iter, "object");
78057
      SIMDJSON_TRY( end_container() );
78058
      return false;
78059
    case ',':
78060
      return true;
78061
    default:
78062
      return report_error(TAPE_ERROR, "Missing comma between object fields");
78063
  }
78064
}
78065
78066
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
78067
  error_code error;
78068
  bool has_value;
78069
  //
78070
  // Initially, the object can be in one of a few different places:
78071
  //
78072
  // 1. The start of the object, at the first field:
78073
  //
78074
  //    ```
78075
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78076
  //      ^ (depth 2, index 1)
78077
  //    ```
78078
  if (at_first_field()) {
78079
    has_value = true;
78080
78081
  //
78082
  // 2. When a previous search did not yield a value or the object is empty:
78083
  //
78084
  //    ```
78085
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78086
  //                                     ^ (depth 0)
78087
  //    { }
78088
  //        ^ (depth 0, index 2)
78089
  //    ```
78090
  //
78091
  } else if (!is_open()) {
78092
#if SIMDJSON_DEVELOPMENT_CHECKS
78093
    // If we're past the end of the object, we're being iterated out of order.
78094
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
78095
    // this object iterator will blithely scan that object for fields.
78096
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
78097
#endif
78098
    return false;
78099
78100
  // 3. When a previous search found a field or an iterator yielded a value:
78101
  //
78102
  //    ```
78103
  //    // When a field was not fully consumed (or not even touched at all)
78104
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78105
  //           ^ (depth 2)
78106
  //    // When a field was fully consumed
78107
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78108
  //                   ^ (depth 1)
78109
  //    // When the last field was fully consumed
78110
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78111
  //                                   ^ (depth 1)
78112
  //    ```
78113
  //
78114
  } else {
78115
    if ((error = skip_child() )) { abandon(); return error; }
78116
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
78117
#if SIMDJSON_DEVELOPMENT_CHECKS
78118
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
78119
#endif
78120
  }
78121
  while (has_value) {
78122
    // Get the key and colon, stopping at the value.
78123
    raw_json_string actual_key;
78124
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
78125
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
78126
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
78127
    // The depth is left unchanged by field_key().
78128
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
78129
    // field_value() will advance and check that we find a ':' separating the
78130
    // key and the value. It will also increment the depth by one.
78131
    if ((error = field_value() )) { abandon(); return error; }
78132
    // If it matches, stop and return
78133
    // We could do it this way if we wanted to allow arbitrary
78134
    // key content (including escaped quotes).
78135
    //if (actual_key.unsafe_is_equal(max_key_length, key)) {
78136
    // Instead we do the following which may trigger buffer overruns if the
78137
    // user provides an adversarial key (containing a well placed unescaped quote
78138
    // character and being longer than the number of bytes remaining in the JSON
78139
    // input).
78140
    if (actual_key.unsafe_is_equal(key)) {
78141
      logger::log_event(*this, "match", key, -2);
78142
      // If we return here, then we return while pointing at the ':' that we just checked.
78143
      return true;
78144
    }
78145
78146
    // No match: skip the value and see if , or } is next
78147
    logger::log_event(*this, "no match", key, -2);
78148
    // The call to skip_child is meant to skip over the value corresponding to the key.
78149
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
78150
    SIMDJSON_TRY( skip_child() ); // Skip the value entirely
78151
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
78152
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
78153
    // then we are in error and we abort.
78154
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
78155
  }
78156
78157
  // If the loop ended, we're out of fields to look at.
78158
  return false;
78159
}
78160
78161
SIMDJSON_PUSH_DISABLE_WARNINGS
78162
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
78163
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
78164
  /**
78165
   * When find_field_unordered_raw is called, we can either be pointing at the
78166
   * first key, pointing outside (at the closing brace) or if a key was matched
78167
   * we can be either pointing right afterthe ':' right before the value (that we need skip),
78168
   * or we may have consumed the value and we might be at a comma or at the
78169
   * final brace (ready for a call to has_next_field()).
78170
   */
78171
  error_code error;
78172
  bool has_value;
78173
78174
  // First, we scan from that point to the end.
78175
  // If we don't find a match, we may loop back around, and scan from the beginning to that point.
78176
  token_position search_start = _json_iter->position();
78177
78178
  // We want to know whether we need to go back to the beginning.
78179
  bool at_first = at_first_field();
78180
  ///////////////
78181
  // Initially, the object can be in one of a few different places:
78182
  //
78183
  // 1. At the first key:
78184
  //
78185
  //    ```
78186
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78187
  //      ^ (depth 2, index 1)
78188
  //    ```
78189
  //
78190
  if (at_first) {
78191
    has_value = true;
78192
78193
  // 2. When a previous search did not yield a value or the object is empty:
78194
  //
78195
  //    ```
78196
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78197
  //                                     ^ (depth 0)
78198
  //    { }
78199
  //        ^ (depth 0, index 2)
78200
  //    ```
78201
  //
78202
  } else if (!is_open()) {
78203
78204
#if SIMDJSON_DEVELOPMENT_CHECKS
78205
    // If we're past the end of the object, we're being iterated out of order.
78206
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
78207
    // this object iterator will blithely scan that object for fields.
78208
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
78209
#endif
78210
    SIMDJSON_TRY(reset_object().get(has_value));
78211
    at_first = true;
78212
  // 3. When a previous search found a field or an iterator yielded a value:
78213
  //
78214
  //    ```
78215
  //    // When a field was not fully consumed (or not even touched at all)
78216
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78217
  //           ^ (depth 2)
78218
  //    // When a field was fully consumed
78219
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78220
  //                   ^ (depth 1)
78221
  //    // When the last field was fully consumed
78222
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78223
  //                                   ^ (depth 1)
78224
  //    ```
78225
  //
78226
  } else {
78227
    // If someone queried a key but they not did access the value, then we are left pointing
78228
    // at the ':' and we need to move forward through the value... If the value was
78229
    // processed then skip_child() does not move the iterator (but may adjust the depth).
78230
    if ((error = skip_child() )) { abandon(); return error; }
78231
    search_start = _json_iter->position();
78232
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
78233
#if SIMDJSON_DEVELOPMENT_CHECKS
78234
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
78235
#endif
78236
  }
78237
78238
  // After initial processing, we will be in one of two states:
78239
  //
78240
  // ```
78241
  // // At the beginning of a field
78242
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78243
  //   ^ (depth 1)
78244
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78245
  //                  ^ (depth 1)
78246
  // // At the end of the object
78247
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
78248
  //                                  ^ (depth 0)
78249
  // ```
78250
  //
78251
  // Next, we find a match starting from the current position.
78252
  while (has_value) {
78253
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
78254
78255
    // Get the key and colon, stopping at the value.
78256
    raw_json_string actual_key;
78257
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
78258
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
78259
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
78260
    // The depth is left unchanged by field_key().
78261
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
78262
    // field_value() will advance and check that we find a ':' separating the
78263
    // key and the value. It will also increment the depth by one.
78264
    if ((error = field_value() )) { abandon(); return error; }
78265
78266
    // If it matches, stop and return
78267
    // We could do it this way if we wanted to allow arbitrary
78268
    // key content (including escaped quotes).
78269
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
78270
    // Instead we do the following which may trigger buffer overruns if the
78271
    // user provides an adversarial key (containing a well placed unescaped quote
78272
    // character and being longer than the number of bytes remaining in the JSON
78273
    // input).
78274
    if (actual_key.unsafe_is_equal(key)) {
78275
      logger::log_event(*this, "match", key, -2);
78276
      // If we return here, then we return while pointing at the ':' that we just checked.
78277
      return true;
78278
    }
78279
78280
    // No match: skip the value and see if , or } is next
78281
    logger::log_event(*this, "no match", key, -2);
78282
    // The call to skip_child is meant to skip over the value corresponding to the key.
78283
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
78284
    SIMDJSON_TRY( skip_child() );
78285
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
78286
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
78287
    // then we are in error and we abort.
78288
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
78289
  }
78290
  // Performance note: it maybe wasteful to rewind to the beginning when there might be
78291
  // no other query following. Indeed, it would require reskipping the whole object.
78292
  // Instead, you can just stay where you are. If there is a new query, there is always time
78293
  // to rewind.
78294
  if(at_first) { return false; }
78295
78296
  // If we reach the end without finding a match, search the rest of the fields starting at the
78297
  // beginning of the object.
78298
  // (We have already run through the object before, so we've already validated its structure. We
78299
  // don't check errors in this bit.)
78300
  SIMDJSON_TRY(reset_object().get(has_value));
78301
  while (true) {
78302
    SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
78303
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
78304
78305
    // Get the key and colon, stopping at the value.
78306
    raw_json_string actual_key;
78307
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
78308
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
78309
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
78310
    // The depth is left unchanged by field_key().
78311
    error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
78312
    // field_value() will advance and check that we find a ':' separating the
78313
    // key and the value.  It will also increment the depth by one.
78314
    error = field_value(); SIMDJSON_ASSUME(!error);
78315
78316
    // If it matches, stop and return
78317
    // We could do it this way if we wanted to allow arbitrary
78318
    // key content (including escaped quotes).
78319
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
78320
    // Instead we do the following which may trigger buffer overruns if the
78321
    // user provides an adversarial key (containing a well placed unescaped quote
78322
    // character and being longer than the number of bytes remaining in the JSON
78323
    // input).
78324
    if (actual_key.unsafe_is_equal(key)) {
78325
      logger::log_event(*this, "match", key, -2);
78326
      // If we return here, then we return while pointing at the ':' that we just checked.
78327
      return true;
78328
    }
78329
78330
    // No match: skip the value and see if , or } is next
78331
    logger::log_event(*this, "no match", key, -2);
78332
    // The call to skip_child is meant to skip over the value corresponding to the key.
78333
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
78334
    SIMDJSON_TRY( skip_child() );
78335
    // If we reached the end of the key-value pair we started from, then we know
78336
    // that the key is not there so we return false. We are either right before
78337
    // the next comma or the final brace.
78338
    if(_json_iter->position() == search_start) { return false; }
78339
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
78340
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
78341
    // then we are in error and we abort.
78342
    error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
78343
    // If we make the mistake of exiting here, then we could be left pointing at a key
78344
    // in the middle of an object. That's not an allowable state.
78345
  }
78346
  // If the loop ended, we're out of fields to look at. The program should
78347
  // never reach this point.
78348
  return false;
78349
}
78350
SIMDJSON_POP_DISABLE_WARNINGS
78351
78352
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
78353
  assert_at_next();
78354
78355
  const uint8_t *key = _json_iter->return_current_and_advance();
78356
  if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
78357
  return raw_json_string(key);
78358
}
78359
78360
simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
78361
  assert_at_next();
78362
78363
  if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
78364
  _json_iter->descend_to(depth()+1);
78365
  return SUCCESS;
78366
}
78367
78368
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
78369
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
78370
  return started_array();
78371
}
78372
78373
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
78374
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
78375
  return started_root_array();
78376
}
78377
78378
inline std::string value_iterator::to_string() const noexcept {
78379
  auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
78380
  if(_json_iter != nullptr) { answer +=  _json_iter->to_string(); }
78381
  answer += std::string(" ]");
78382
  return answer;
78383
}
78384
78385
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
78386
  assert_at_container_start();
78387
  if (*_json_iter->peek() == ']') {
78388
    logger::log_value(*_json_iter, "empty array");
78389
    _json_iter->return_current_and_advance();
78390
    SIMDJSON_TRY( end_container() );
78391
    return false;
78392
  }
78393
  _json_iter->descend_to(depth()+1);
78394
#if SIMDJSON_DEVELOPMENT_CHECKS
78395
  _json_iter->set_start_position(_depth, start_position());
78396
#endif
78397
  return true;
78398
}
78399
78400
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
78401
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
78402
  // current document. It only works in the normal mode where we have indexed a single document.
78403
  // Note that adding a check for 'streaming' is not expensive since we only have at most
78404
  // one root element.
78405
  if ( ! _json_iter->streaming() ) {
78406
    // The following lines do not fully protect against garbage content within the
78407
    // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
78408
    // also call `at_end()` on the document instance at the end of the processing to
78409
    // ensure that the processing has finished at the end.
78410
    //
78411
    if (*_json_iter->peek_last() != ']') {
78412
      _json_iter->abandon();
78413
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
78414
    }
78415
    // If the last character is ] *and* the first gibberish character is also ']'
78416
    // then on-demand could accidentally go over. So we need additional checks.
78417
    // https://github.com/simdjson/simdjson/issues/1834
78418
    // Checking that the document is balanced requires a full scan which is potentially
78419
    // expensive, but it only happens in edge cases where the first padding character is
78420
    // a closing bracket.
78421
    if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
78422
      _json_iter->abandon();
78423
      // The exact error would require more work. It will typically be an unclosed array.
78424
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
78425
    }
78426
  }
78427
  return SUCCESS;
78428
}
78429
78430
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
78431
  auto error = check_root_array();
78432
  if (error) { return error; }
78433
  return started_array();
78434
}
78435
78436
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
78437
  assert_at_next();
78438
78439
  logger::log_event(*this, "has_next_element");
78440
  switch (*_json_iter->return_current_and_advance()) {
78441
    case ']':
78442
      logger::log_end_value(*_json_iter, "array");
78443
      SIMDJSON_TRY( end_container() );
78444
      return false;
78445
    case ',':
78446
      _json_iter->descend_to(depth()+1);
78447
      return true;
78448
    default:
78449
      return report_error(TAPE_ERROR, "Missing comma between array elements");
78450
  }
78451
}
78452
78453
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
78454
  auto not_true = atomparsing::str4ncmp(json, "true");
78455
  auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
78456
  bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
78457
  if (error) { return incorrect_type_error("Not a boolean"); }
78458
  return simdjson_result<bool>(!not_true);
78459
}
78460
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
78461
  bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
78462
  // if we start with 'n', we must be a null
78463
  if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
78464
  return is_null_string;
78465
}
78466
78467
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
78468
  return get_raw_json_string().unescape(json_iter(), allow_replacement);
78469
}
78470
template <typename string_type>
78471
simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
78472
  std::string_view content;
78473
  auto err = get_string(allow_replacement).get(content);
78474
  if (err) { return err; }
78475
  receiver = content;
78476
  return SUCCESS;
78477
}
78478
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
78479
  return get_raw_json_string().unescape_wobbly(json_iter());
78480
}
78481
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
78482
  auto json = peek_scalar("string");
78483
  if (*json != '"') { return incorrect_type_error("Not a string"); }
78484
  advance_scalar("string");
78485
  return raw_json_string(json+1);
78486
}
78487
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
78488
  auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
78489
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
78490
  return result;
78491
}
78492
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
78493
  auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
78494
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
78495
  return result;
78496
}
78497
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
78498
  auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
78499
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
78500
  return result;
78501
}
78502
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
78503
  auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
78504
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
78505
  return result;
78506
}
78507
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
78508
  auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
78509
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
78510
  return result;
78511
}
78512
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
78513
  auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
78514
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
78515
  return result;
78516
}
78517
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
78518
  auto result = parse_bool(peek_non_root_scalar("bool"));
78519
  if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
78520
  return result;
78521
}
78522
simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
78523
  bool is_null_value;
78524
  SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
78525
  if(is_null_value) { advance_non_root_scalar("null"); }
78526
  return is_null_value;
78527
}
78528
simdjson_inline bool value_iterator::is_negative() noexcept {
78529
  return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
78530
}
78531
simdjson_inline bool value_iterator::is_root_negative() noexcept {
78532
  return numberparsing::is_negative(peek_root_scalar("numbersign"));
78533
}
78534
simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
78535
  return numberparsing::is_integer(peek_non_root_scalar("integer"));
78536
}
78537
simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
78538
  return numberparsing::get_number_type(peek_non_root_scalar("integer"));
78539
}
78540
simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
78541
  number num;
78542
  error_code error =  numberparsing::parse_number(peek_non_root_scalar("number"), num);
78543
  if(error) { return error; }
78544
  return num;
78545
}
78546
78547
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
78548
  auto max_len = peek_root_length();
78549
  auto json = peek_root_scalar("is_root_integer");
78550
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
78551
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
78552
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
78553
    return false; // if there are more than 20 characters, it cannot be represented as an integer.
78554
  }
78555
  auto answer = numberparsing::is_integer(tmpbuf);
78556
  // If the parsing was a success, we must still check that it is
78557
  // a single scalar. Note that we parse first because of cases like '[]' where
78558
  // getting TRAILING_CONTENT is wrong.
78559
  if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
78560
  return answer;
78561
}
78562
78563
simdjson_inline simdjson_result<ppc64::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
78564
  auto max_len = peek_root_length();
78565
  auto json = peek_root_scalar("number");
78566
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
78567
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
78568
  // number: -0.<fraction>e-308.
78569
  uint8_t tmpbuf[1074+8+1+1];
78570
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
78571
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
78572
    if(numberparsing::check_if_integer(json, max_len)) {
78573
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78574
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
78575
      return number_type::big_integer;
78576
    }
78577
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
78578
    return NUMBER_ERROR;
78579
  }
78580
  auto answer = numberparsing::get_number_type(tmpbuf);
78581
  if (check_trailing && (answer.error() == SUCCESS)  && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78582
  return answer;
78583
}
78584
simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
78585
  auto max_len = peek_root_length();
78586
  auto json = peek_root_scalar("number");
78587
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
78588
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
78589
  // number: -0.<fraction>e-308.
78590
  // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
78591
  uint8_t tmpbuf[1074+8+1+1];
78592
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
78593
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
78594
    if(numberparsing::check_if_integer(json, max_len)) {
78595
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78596
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
78597
      return BIGINT_ERROR;
78598
    }
78599
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
78600
    return NUMBER_ERROR;
78601
  }
78602
  number num;
78603
  error_code error =  numberparsing::parse_number(tmpbuf, num);
78604
  if(error) { return error; }
78605
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78606
  advance_root_scalar("number");
78607
  return num;
78608
}
78609
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
78610
  return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
78611
}
78612
template <typename string_type>
78613
simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
78614
  std::string_view content;
78615
  auto err = get_root_string(check_trailing, allow_replacement).get(content);
78616
  if (err) { return err; }
78617
  receiver = content;
78618
  return SUCCESS;
78619
}
78620
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
78621
  return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
78622
}
78623
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
78624
  auto json = peek_scalar("string");
78625
  if (*json != '"') { return incorrect_type_error("Not a string"); }
78626
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78627
  advance_scalar("string");
78628
  return raw_json_string(json+1);
78629
}
78630
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
78631
  auto max_len = peek_root_length();
78632
  auto json = peek_root_scalar("uint64");
78633
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
78634
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
78635
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
78636
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
78637
    return NUMBER_ERROR;
78638
  }
78639
  auto result = numberparsing::parse_unsigned(tmpbuf);
78640
  if(result.error() == SUCCESS) {
78641
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78642
    advance_root_scalar("uint64");
78643
  }
78644
  return result;
78645
}
78646
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
78647
  auto max_len = peek_root_length();
78648
  auto json = peek_root_scalar("uint64");
78649
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
78650
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
78651
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
78652
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
78653
    return NUMBER_ERROR;
78654
  }
78655
  auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
78656
  if(result.error() == SUCCESS) {
78657
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78658
    advance_root_scalar("uint64");
78659
  }
78660
  return result;
78661
}
78662
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
78663
  auto max_len = peek_root_length();
78664
  auto json = peek_root_scalar("int64");
78665
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
78666
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
78667
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
78668
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
78669
    return NUMBER_ERROR;
78670
  }
78671
78672
  auto result = numberparsing::parse_integer(tmpbuf);
78673
  if(result.error() == SUCCESS) {
78674
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78675
    advance_root_scalar("int64");
78676
  }
78677
  return result;
78678
}
78679
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
78680
  auto max_len = peek_root_length();
78681
  auto json = peek_root_scalar("int64");
78682
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
78683
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
78684
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
78685
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
78686
    return NUMBER_ERROR;
78687
  }
78688
78689
  auto result = numberparsing::parse_integer_in_string(tmpbuf);
78690
  if(result.error() == SUCCESS) {
78691
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78692
    advance_root_scalar("int64");
78693
  }
78694
  return result;
78695
}
78696
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
78697
  auto max_len = peek_root_length();
78698
  auto json = peek_root_scalar("double");
78699
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
78700
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
78701
  // number: -0.<fraction>e-308.
78702
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
78703
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
78704
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
78705
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
78706
    return NUMBER_ERROR;
78707
  }
78708
  auto result = numberparsing::parse_double(tmpbuf);
78709
  if(result.error() == SUCCESS) {
78710
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78711
    advance_root_scalar("double");
78712
  }
78713
  return result;
78714
}
78715
78716
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
78717
  auto max_len = peek_root_length();
78718
  auto json = peek_root_scalar("double");
78719
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
78720
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
78721
  // number: -0.<fraction>e-308.
78722
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
78723
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
78724
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
78725
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
78726
    return NUMBER_ERROR;
78727
  }
78728
  auto result = numberparsing::parse_double_in_string(tmpbuf);
78729
  if(result.error() == SUCCESS) {
78730
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78731
    advance_root_scalar("double");
78732
  }
78733
  return result;
78734
}
78735
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
78736
  auto max_len = peek_root_length();
78737
  auto json = peek_root_scalar("bool");
78738
  uint8_t tmpbuf[5+1+1]; // +1 for null termination
78739
  tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
78740
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
78741
  auto result = parse_bool(tmpbuf);
78742
  if(result.error() == SUCCESS) {
78743
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78744
    advance_root_scalar("bool");
78745
  }
78746
  return result;
78747
}
78748
simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
78749
  auto max_len = peek_root_length();
78750
  auto json = peek_root_scalar("null");
78751
  bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
78752
         (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
78753
  if(result) { // we have something that looks like a null.
78754
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
78755
    advance_root_scalar("null");
78756
  }
78757
  return result;
78758
}
78759
78760
simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
78761
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
78762
  SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
78763
78764
  return _json_iter->skip_child(depth());
78765
}
78766
78767
simdjson_inline value_iterator value_iterator::child() const noexcept {
78768
  assert_at_child();
78769
  return { _json_iter, depth()+1, _json_iter->token.position() };
78770
}
78771
78772
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
78773
// relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
78774
// marked non-inline.
78775
SIMDJSON_PUSH_DISABLE_WARNINGS
78776
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
78777
simdjson_inline bool value_iterator::is_open() const noexcept {
78778
  return _json_iter->depth() >= depth();
78779
}
78780
SIMDJSON_POP_DISABLE_WARNINGS
78781
78782
simdjson_inline bool value_iterator::at_end() const noexcept {
78783
  return _json_iter->at_end();
78784
}
78785
78786
simdjson_inline bool value_iterator::at_start() const noexcept {
78787
  return _json_iter->token.position() == start_position();
78788
}
78789
78790
simdjson_inline bool value_iterator::at_first_field() const noexcept {
78791
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
78792
  return _json_iter->token.position() == start_position() + 1;
78793
}
78794
78795
simdjson_inline void value_iterator::abandon() noexcept {
78796
  _json_iter->abandon();
78797
}
78798
78799
simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
78800
  return _depth;
78801
}
78802
simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
78803
  return _json_iter->error;
78804
}
78805
simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
78806
  return _json_iter->string_buf_loc();
78807
}
78808
simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
78809
  return *_json_iter;
78810
}
78811
simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
78812
  return *_json_iter;
78813
}
78814
78815
simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
78816
  return _json_iter->peek(start_position());
78817
}
78818
simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
78819
  return _json_iter->peek_length(start_position());
78820
}
78821
simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
78822
  return _json_iter->peek_root_length(start_position());
78823
}
78824
78825
simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
78826
  logger::log_value(*_json_iter, start_position(), depth(), type);
78827
  // If we're not at the position anymore, we don't want to advance the cursor.
78828
  if (!is_at_start()) { return peek_start(); }
78829
78830
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
78831
  assert_at_start();
78832
  return _json_iter->peek();
78833
}
78834
78835
simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
78836
  logger::log_value(*_json_iter, start_position(), depth(), type);
78837
  // If we're not at the position anymore, we don't want to advance the cursor.
78838
  if (!is_at_start()) { return; }
78839
78840
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
78841
  assert_at_start();
78842
  _json_iter->return_current_and_advance();
78843
  _json_iter->ascend_to(depth()-1);
78844
}
78845
78846
simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
78847
  logger::log_start_value(*_json_iter, start_position(), depth(), type);
78848
  // If we're not at the position anymore, we don't want to advance the cursor.
78849
  const uint8_t *json;
78850
  if (!is_at_start()) {
78851
#if SIMDJSON_DEVELOPMENT_CHECKS
78852
    if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
78853
#endif
78854
    json = peek_start();
78855
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
78856
  } else {
78857
    assert_at_start();
78858
    /**
78859
     * We should be prudent. Let us peek. If it is not the right type, we
78860
     * return an error. Only once we have determined that we have the right
78861
     * type are we allowed to advance!
78862
     */
78863
    json = _json_iter->peek();
78864
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
78865
    _json_iter->return_current_and_advance();
78866
  }
78867
78868
78869
  return SUCCESS;
78870
}
78871
78872
78873
simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
78874
  logger::log_value(*_json_iter, start_position(), depth(), type);
78875
  if (!is_at_start()) { return peek_start(); }
78876
78877
  assert_at_root();
78878
  return _json_iter->peek();
78879
}
78880
simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
78881
  logger::log_value(*_json_iter, start_position(), depth(), type);
78882
  if (!is_at_start()) { return peek_start(); }
78883
78884
  assert_at_non_root_start();
78885
  return _json_iter->peek();
78886
}
78887
78888
simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
78889
  logger::log_value(*_json_iter, start_position(), depth(), type);
78890
  if (!is_at_start()) { return; }
78891
78892
  assert_at_root();
78893
  _json_iter->return_current_and_advance();
78894
  _json_iter->ascend_to(depth()-1);
78895
}
78896
simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
78897
  logger::log_value(*_json_iter, start_position(), depth(), type);
78898
  if (!is_at_start()) { return; }
78899
78900
  assert_at_non_root_start();
78901
  _json_iter->return_current_and_advance();
78902
  _json_iter->ascend_to(depth()-1);
78903
}
78904
78905
simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
78906
  logger::log_error(*_json_iter, start_position(), depth(), message);
78907
  return INCORRECT_TYPE;
78908
}
78909
78910
simdjson_inline bool value_iterator::is_at_start() const noexcept {
78911
  return position() == start_position();
78912
}
78913
78914
simdjson_inline bool value_iterator::is_at_key() const noexcept {
78915
  // Keys are at the same depth as the object.
78916
  // Note here that we could be safer and check that we are within an object,
78917
  // but we do not.
78918
  return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
78919
}
78920
78921
simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
78922
  // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
78923
  auto delta = position() - start_position();
78924
  return delta == 1 || delta == 2;
78925
}
78926
78927
inline void value_iterator::assert_at_start() const noexcept {
78928
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
78929
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
78930
  SIMDJSON_ASSUME( _depth > 0 );
78931
}
78932
78933
inline void value_iterator::assert_at_container_start() const noexcept {
78934
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
78935
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
78936
  SIMDJSON_ASSUME( _depth > 0 );
78937
}
78938
78939
inline void value_iterator::assert_at_next() const noexcept {
78940
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
78941
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
78942
  SIMDJSON_ASSUME( _depth > 0 );
78943
}
78944
78945
simdjson_inline void value_iterator::move_at_start() noexcept {
78946
  _json_iter->_depth = _depth;
78947
  _json_iter->token.set_position(_start_position);
78948
}
78949
78950
simdjson_inline void value_iterator::move_at_container_start() noexcept {
78951
  _json_iter->_depth = _depth;
78952
  _json_iter->token.set_position(_start_position + 1);
78953
}
78954
78955
simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
78956
  if(error()) { return error(); }
78957
  move_at_container_start();
78958
  return started_array();
78959
}
78960
78961
simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
78962
  if(error()) { return error(); }
78963
  move_at_container_start();
78964
  return started_object();
78965
}
78966
78967
inline void value_iterator::assert_at_child() const noexcept {
78968
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
78969
  SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
78970
  SIMDJSON_ASSUME( _depth > 0 );
78971
}
78972
78973
inline void value_iterator::assert_at_root() const noexcept {
78974
  assert_at_start();
78975
  SIMDJSON_ASSUME( _depth == 1 );
78976
}
78977
78978
inline void value_iterator::assert_at_non_root_start() const noexcept {
78979
  assert_at_start();
78980
  SIMDJSON_ASSUME( _depth > 1 );
78981
}
78982
78983
inline void value_iterator::assert_is_valid() const noexcept {
78984
  SIMDJSON_ASSUME( _json_iter != nullptr );
78985
}
78986
78987
simdjson_inline bool value_iterator::is_valid() const noexcept {
78988
  return _json_iter != nullptr;
78989
}
78990
78991
simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
78992
  switch (*peek_start()) {
78993
    case '{':
78994
      return json_type::object;
78995
    case '[':
78996
      return json_type::array;
78997
    case '"':
78998
      return json_type::string;
78999
    case 'n':
79000
      return json_type::null;
79001
    case 't': case 'f':
79002
      return json_type::boolean;
79003
    case '-':
79004
    case '0': case '1': case '2': case '3': case '4':
79005
    case '5': case '6': case '7': case '8': case '9':
79006
      return json_type::number;
79007
    default:
79008
      return TAPE_ERROR;
79009
  }
79010
}
79011
79012
simdjson_inline token_position value_iterator::start_position() const noexcept {
79013
  return _start_position;
79014
}
79015
79016
simdjson_inline token_position value_iterator::position() const noexcept {
79017
  return _json_iter->position();
79018
}
79019
79020
simdjson_inline token_position value_iterator::end_position() const noexcept {
79021
  return _json_iter->end_position();
79022
}
79023
79024
simdjson_inline token_position value_iterator::last_position() const noexcept {
79025
  return _json_iter->last_position();
79026
}
79027
79028
simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
79029
  return _json_iter->report_error(error, message);
79030
}
79031
79032
} // namespace ondemand
79033
} // namespace ppc64
79034
} // namespace simdjson
79035
79036
namespace simdjson {
79037
79038
simdjson_inline simdjson_result<ppc64::ondemand::value_iterator>::simdjson_result(ppc64::ondemand::value_iterator &&value) noexcept
79039
    : implementation_simdjson_result_base<ppc64::ondemand::value_iterator>(std::forward<ppc64::ondemand::value_iterator>(value)) {}
79040
simdjson_inline simdjson_result<ppc64::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
79041
    : implementation_simdjson_result_base<ppc64::ondemand::value_iterator>(error) {}
79042
79043
} // namespace simdjson
79044
79045
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
79046
/* end file simdjson/generic/ondemand/value_iterator-inl.h for ppc64 */
79047
/* end file simdjson/generic/ondemand/amalgamated.h for ppc64 */
79048
/* including simdjson/ppc64/end.h: #include "simdjson/ppc64/end.h" */
79049
/* begin file simdjson/ppc64/end.h */
79050
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79051
/* amalgamation skipped (editor-only): #include "simdjson/ppc64/base.h" */
79052
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79053
79054
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
79055
/* undefining SIMDJSON_IMPLEMENTATION from "ppc64" */
79056
#undef SIMDJSON_IMPLEMENTATION
79057
/* end file simdjson/ppc64/end.h */
79058
79059
#endif // SIMDJSON_PPC64_ONDEMAND_H
79060
/* end file simdjson/ppc64/ondemand.h */
79061
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
79062
/* including simdjson/westmere/ondemand.h: #include "simdjson/westmere/ondemand.h" */
79063
/* begin file simdjson/westmere/ondemand.h */
79064
#ifndef SIMDJSON_WESTMERE_ONDEMAND_H
79065
#define SIMDJSON_WESTMERE_ONDEMAND_H
79066
79067
/* including simdjson/westmere/begin.h: #include "simdjson/westmere/begin.h" */
79068
/* begin file simdjson/westmere/begin.h */
79069
/* defining SIMDJSON_IMPLEMENTATION to "westmere" */
79070
#define SIMDJSON_IMPLEMENTATION westmere
79071
/* including simdjson/westmere/base.h: #include "simdjson/westmere/base.h" */
79072
/* begin file simdjson/westmere/base.h */
79073
#ifndef SIMDJSON_WESTMERE_BASE_H
79074
#define SIMDJSON_WESTMERE_BASE_H
79075
79076
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79077
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
79078
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79079
79080
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_WESTMERE
79081
namespace simdjson {
79082
/**
79083
 * Implementation for Westmere (Intel SSE4.2).
79084
 */
79085
namespace westmere {
79086
79087
class implementation;
79088
79089
namespace {
79090
namespace simd {
79091
79092
template <typename T> struct simd8;
79093
template <typename T> struct simd8x64;
79094
79095
} // namespace simd
79096
} // unnamed namespace
79097
79098
} // namespace westmere
79099
} // namespace simdjson
79100
79101
#endif // SIMDJSON_WESTMERE_BASE_H
79102
/* end file simdjson/westmere/base.h */
79103
/* including simdjson/westmere/intrinsics.h: #include "simdjson/westmere/intrinsics.h" */
79104
/* begin file simdjson/westmere/intrinsics.h */
79105
#ifndef SIMDJSON_WESTMERE_INTRINSICS_H
79106
#define SIMDJSON_WESTMERE_INTRINSICS_H
79107
79108
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79109
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
79110
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79111
79112
#if SIMDJSON_VISUAL_STUDIO
79113
// under clang within visual studio, this will include <x86intrin.h>
79114
#include <intrin.h> // visual studio or clang
79115
#else
79116
#include <x86intrin.h> // elsewhere
79117
#endif // SIMDJSON_VISUAL_STUDIO
79118
79119
79120
#if SIMDJSON_CLANG_VISUAL_STUDIO
79121
/**
79122
 * You are not supposed, normally, to include these
79123
 * headers directly. Instead you should either include intrin.h
79124
 * or x86intrin.h. However, when compiling with clang
79125
 * under Windows (i.e., when _MSC_VER is set), these headers
79126
 * only get included *if* the corresponding features are detected
79127
 * from macros:
79128
 */
79129
#include <smmintrin.h>  // for _mm_alignr_epi8
79130
#include <wmmintrin.h>  // for  _mm_clmulepi64_si128
79131
#endif
79132
79133
static_assert(sizeof(__m128i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for westmere");
79134
79135
#endif // SIMDJSON_WESTMERE_INTRINSICS_H
79136
/* end file simdjson/westmere/intrinsics.h */
79137
79138
#if !SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
79139
SIMDJSON_TARGET_REGION("sse4.2,pclmul,popcnt")
79140
#endif
79141
79142
/* including simdjson/westmere/bitmanipulation.h: #include "simdjson/westmere/bitmanipulation.h" */
79143
/* begin file simdjson/westmere/bitmanipulation.h */
79144
#ifndef SIMDJSON_WESTMERE_BITMANIPULATION_H
79145
#define SIMDJSON_WESTMERE_BITMANIPULATION_H
79146
79147
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79148
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
79149
/* amalgamation skipped (editor-only): #include "simdjson/westmere/intrinsics.h" */
79150
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79151
79152
namespace simdjson {
79153
namespace westmere {
79154
namespace {
79155
79156
// We sometimes call trailing_zero on inputs that are zero,
79157
// but the algorithms do not end up using the returned value.
79158
// Sadly, sanitizers are not smart enough to figure it out.
79159
SIMDJSON_NO_SANITIZE_UNDEFINED
79160
// This function can be used safely even if not all bytes have been
79161
// initialized.
79162
// See issue https://github.com/simdjson/simdjson/issues/1965
79163
SIMDJSON_NO_SANITIZE_MEMORY
79164
simdjson_inline int trailing_zeroes(uint64_t input_num) {
79165
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79166
  unsigned long ret;
79167
  // Search the mask data from least significant bit (LSB)
79168
  // to the most significant bit (MSB) for a set bit (1).
79169
  _BitScanForward64(&ret, input_num);
79170
  return (int)ret;
79171
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
79172
  return __builtin_ctzll(input_num);
79173
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
79174
}
79175
79176
/* result might be undefined when input_num is zero */
79177
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
79178
  return input_num & (input_num-1);
79179
}
79180
79181
/* result might be undefined when input_num is zero */
79182
simdjson_inline int leading_zeroes(uint64_t input_num) {
79183
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79184
  unsigned long leading_zero = 0;
79185
  // Search the mask data from most significant bit (MSB)
79186
  // to least significant bit (LSB) for a set bit (1).
79187
  if (_BitScanReverse64(&leading_zero, input_num))
79188
    return (int)(63 - leading_zero);
79189
  else
79190
    return 64;
79191
#else
79192
  return __builtin_clzll(input_num);
79193
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
79194
}
79195
79196
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79197
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
79198
  // note: we do not support legacy 32-bit Windows in this kernel
79199
  return __popcnt64(input_num);// Visual Studio wants two underscores
79200
}
79201
#else
79202
simdjson_inline long long int count_ones(uint64_t input_num) {
79203
  return _popcnt64(input_num);
79204
}
79205
#endif
79206
79207
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
79208
                                uint64_t *result) {
79209
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79210
  return _addcarry_u64(0, value1, value2,
79211
                       reinterpret_cast<unsigned __int64 *>(result));
79212
#else
79213
  return __builtin_uaddll_overflow(value1, value2,
79214
                                   reinterpret_cast<unsigned long long *>(result));
79215
#endif
79216
}
79217
79218
} // unnamed namespace
79219
} // namespace westmere
79220
} // namespace simdjson
79221
79222
#endif // SIMDJSON_WESTMERE_BITMANIPULATION_H
79223
/* end file simdjson/westmere/bitmanipulation.h */
79224
/* including simdjson/westmere/bitmask.h: #include "simdjson/westmere/bitmask.h" */
79225
/* begin file simdjson/westmere/bitmask.h */
79226
#ifndef SIMDJSON_WESTMERE_BITMASK_H
79227
#define SIMDJSON_WESTMERE_BITMASK_H
79228
79229
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79230
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
79231
/* amalgamation skipped (editor-only): #include "simdjson/westmere/intrinsics.h" */
79232
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79233
79234
namespace simdjson {
79235
namespace westmere {
79236
namespace {
79237
79238
//
79239
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
79240
//
79241
// For example, prefix_xor(00100100) == 00011100
79242
//
79243
simdjson_inline uint64_t prefix_xor(const uint64_t bitmask) {
79244
  // There should be no such thing with a processing supporting avx2
79245
  // but not clmul.
79246
  __m128i all_ones = _mm_set1_epi8('\xFF');
79247
  __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, bitmask), all_ones, 0);
79248
  return _mm_cvtsi128_si64(result);
79249
}
79250
79251
} // unnamed namespace
79252
} // namespace westmere
79253
} // namespace simdjson
79254
79255
#endif // SIMDJSON_WESTMERE_BITMASK_H
79256
/* end file simdjson/westmere/bitmask.h */
79257
/* including simdjson/westmere/numberparsing_defs.h: #include "simdjson/westmere/numberparsing_defs.h" */
79258
/* begin file simdjson/westmere/numberparsing_defs.h */
79259
#ifndef SIMDJSON_WESTMERE_NUMBERPARSING_DEFS_H
79260
#define SIMDJSON_WESTMERE_NUMBERPARSING_DEFS_H
79261
79262
/* including simdjson/westmere/base.h: #include "simdjson/westmere/base.h" */
79263
/* begin file simdjson/westmere/base.h */
79264
#ifndef SIMDJSON_WESTMERE_BASE_H
79265
#define SIMDJSON_WESTMERE_BASE_H
79266
79267
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79268
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
79269
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79270
79271
// The constructor may be executed on any host, so we take care not to use SIMDJSON_TARGET_WESTMERE
79272
namespace simdjson {
79273
/**
79274
 * Implementation for Westmere (Intel SSE4.2).
79275
 */
79276
namespace westmere {
79277
79278
class implementation;
79279
79280
namespace {
79281
namespace simd {
79282
79283
template <typename T> struct simd8;
79284
template <typename T> struct simd8x64;
79285
79286
} // namespace simd
79287
} // unnamed namespace
79288
79289
} // namespace westmere
79290
} // namespace simdjson
79291
79292
#endif // SIMDJSON_WESTMERE_BASE_H
79293
/* end file simdjson/westmere/base.h */
79294
/* including simdjson/westmere/intrinsics.h: #include "simdjson/westmere/intrinsics.h" */
79295
/* begin file simdjson/westmere/intrinsics.h */
79296
#ifndef SIMDJSON_WESTMERE_INTRINSICS_H
79297
#define SIMDJSON_WESTMERE_INTRINSICS_H
79298
79299
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79300
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
79301
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79302
79303
#if SIMDJSON_VISUAL_STUDIO
79304
// under clang within visual studio, this will include <x86intrin.h>
79305
#include <intrin.h> // visual studio or clang
79306
#else
79307
#include <x86intrin.h> // elsewhere
79308
#endif // SIMDJSON_VISUAL_STUDIO
79309
79310
79311
#if SIMDJSON_CLANG_VISUAL_STUDIO
79312
/**
79313
 * You are not supposed, normally, to include these
79314
 * headers directly. Instead you should either include intrin.h
79315
 * or x86intrin.h. However, when compiling with clang
79316
 * under Windows (i.e., when _MSC_VER is set), these headers
79317
 * only get included *if* the corresponding features are detected
79318
 * from macros:
79319
 */
79320
#include <smmintrin.h>  // for _mm_alignr_epi8
79321
#include <wmmintrin.h>  // for  _mm_clmulepi64_si128
79322
#endif
79323
79324
static_assert(sizeof(__m128i) <= simdjson::SIMDJSON_PADDING, "insufficient padding for westmere");
79325
79326
#endif // SIMDJSON_WESTMERE_INTRINSICS_H
79327
/* end file simdjson/westmere/intrinsics.h */
79328
79329
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79330
/* amalgamation skipped (editor-only): #include "simdjson/internal/numberparsing_tables.h" */
79331
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79332
79333
namespace simdjson {
79334
namespace westmere {
79335
namespace numberparsing {
79336
79337
/** @private */
79338
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
79339
  // this actually computes *16* values so we are being wasteful.
79340
  const __m128i ascii0 = _mm_set1_epi8('0');
79341
  const __m128i mul_1_10 =
79342
      _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1);
79343
  const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1);
79344
  const __m128i mul_1_10000 =
79345
      _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1);
79346
  const __m128i input = _mm_sub_epi8(
79347
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0);
79348
  const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10);
79349
  const __m128i t2 = _mm_madd_epi16(t1, mul_1_100);
79350
  const __m128i t3 = _mm_packus_epi32(t2, t2);
79351
  const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000);
79352
  return _mm_cvtsi128_si32(
79353
      t4); // only captures the sum of the first 8 digits, drop the rest
79354
}
79355
79356
/** @private */
79357
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
79358
  internal::value128 answer;
79359
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
79360
#ifdef _M_ARM64
79361
  // ARM64 has native support for 64-bit multiplications, no need to emultate
79362
  answer.high = __umulh(value1, value2);
79363
  answer.low = value1 * value2;
79364
#else
79365
  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
79366
#endif // _M_ARM64
79367
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
79368
  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
79369
  answer.low = uint64_t(r);
79370
  answer.high = uint64_t(r >> 64);
79371
#endif
79372
  return answer;
79373
}
79374
79375
} // namespace numberparsing
79376
} // namespace westmere
79377
} // namespace simdjson
79378
79379
#define SIMDJSON_SWAR_NUMBER_PARSING 1
79380
79381
#endif //  SIMDJSON_WESTMERE_NUMBERPARSING_DEFS_H
79382
/* end file simdjson/westmere/numberparsing_defs.h */
79383
/* including simdjson/westmere/simd.h: #include "simdjson/westmere/simd.h" */
79384
/* begin file simdjson/westmere/simd.h */
79385
#ifndef SIMDJSON_WESTMERE_SIMD_H
79386
#define SIMDJSON_WESTMERE_SIMD_H
79387
79388
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79389
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
79390
/* amalgamation skipped (editor-only): #include "simdjson/westmere/bitmanipulation.h" */
79391
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
79392
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79393
79394
namespace simdjson {
79395
namespace westmere {
79396
namespace {
79397
namespace simd {
79398
79399
  template<typename Child>
79400
  struct base {
79401
    __m128i value;
79402
79403
    // Zero constructor
79404
    simdjson_inline base() : value{__m128i()} {}
79405
79406
    // Conversion from SIMD register
79407
    simdjson_inline base(const __m128i _value) : value(_value) {}
79408
79409
    // Conversion to SIMD register
79410
    simdjson_inline operator const __m128i&() const { return this->value; }
79411
    simdjson_inline operator __m128i&() { return this->value; }
79412
79413
    // Bit operations
79414
    simdjson_inline Child operator|(const Child other) const { return _mm_or_si128(*this, other); }
79415
    simdjson_inline Child operator&(const Child other) const { return _mm_and_si128(*this, other); }
79416
    simdjson_inline Child operator^(const Child other) const { return _mm_xor_si128(*this, other); }
79417
    simdjson_inline Child bit_andnot(const Child other) const { return _mm_andnot_si128(other, *this); }
79418
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
79419
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
79420
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
79421
  };
79422
79423
  template<typename T, typename Mask=simd8<bool>>
79424
  struct base8: base<simd8<T>> {
79425
    typedef uint16_t bitmask_t;
79426
    typedef uint32_t bitmask2_t;
79427
79428
    simdjson_inline base8() : base<simd8<T>>() {}
79429
    simdjson_inline base8(const __m128i _value) : base<simd8<T>>(_value) {}
79430
79431
    friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return _mm_cmpeq_epi8(lhs, rhs); }
79432
79433
    static const int SIZE = sizeof(base<simd8<T>>::value);
79434
79435
    template<int N=1>
79436
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
79437
      return _mm_alignr_epi8(*this, prev_chunk, 16 - N);
79438
    }
79439
  };
79440
79441
  // SIMD byte mask type (returned by things like eq and gt)
79442
  template<>
79443
  struct simd8<bool>: base8<bool> {
79444
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm_set1_epi8(uint8_t(-(!!_value))); }
79445
79446
    simdjson_inline simd8<bool>() : base8() {}
79447
    simdjson_inline simd8<bool>(const __m128i _value) : base8<bool>(_value) {}
79448
    // Splat constructor
79449
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
79450
79451
    simdjson_inline int to_bitmask() const { return _mm_movemask_epi8(*this); }
79452
    simdjson_inline bool any() const { return !_mm_testz_si128(*this, *this); }
79453
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
79454
  };
79455
79456
  template<typename T>
79457
  struct base8_numeric: base8<T> {
79458
    static simdjson_inline simd8<T> splat(T _value) { return _mm_set1_epi8(_value); }
79459
    static simdjson_inline simd8<T> zero() { return _mm_setzero_si128(); }
79460
    static simdjson_inline simd8<T> load(const T values[16]) {
79461
      return _mm_loadu_si128(reinterpret_cast<const __m128i *>(values));
79462
    }
79463
    // Repeat 16 values as many times as necessary (usually for lookup tables)
79464
    static simdjson_inline simd8<T> repeat_16(
79465
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
79466
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
79467
    ) {
79468
      return simd8<T>(
79469
        v0, v1, v2, v3, v4, v5, v6, v7,
79470
        v8, v9, v10,v11,v12,v13,v14,v15
79471
      );
79472
    }
79473
79474
    simdjson_inline base8_numeric() : base8<T>() {}
79475
    simdjson_inline base8_numeric(const __m128i _value) : base8<T>(_value) {}
79476
79477
    // Store to array
79478
    simdjson_inline void store(T dst[16]) const { return _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), *this); }
79479
79480
    // Override to distinguish from bool version
79481
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
79482
79483
    // Addition/subtraction are the same for signed and unsigned
79484
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm_add_epi8(*this, other); }
79485
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm_sub_epi8(*this, other); }
79486
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
79487
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
79488
79489
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
79490
    template<typename L>
79491
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
79492
      return _mm_shuffle_epi8(lookup_table, *this);
79493
    }
79494
79495
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
79496
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
79497
    // Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
79498
    // get written.
79499
    // Design consideration: it seems like a function with the
79500
    // signature simd8<L> compress(uint32_t mask) would be
79501
    // sensible, but the AVX ISA makes this kind of approach difficult.
79502
    template<typename L>
79503
    simdjson_inline void compress(uint16_t mask, L * output) const {
79504
      using internal::thintable_epi8;
79505
      using internal::BitsSetTable256mul2;
79506
      using internal::pshufb_combine_table;
79507
      // this particular implementation was inspired by work done by @animetosho
79508
      // we do it in two steps, first 8 bytes and then second 8 bytes
79509
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
79510
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
79511
      // next line just loads the 64-bit values thintable_epi8[mask1] and
79512
      // thintable_epi8[mask2] into a 128-bit register, using only
79513
      // two instructions on most compilers.
79514
      __m128i shufmask =  _mm_set_epi64x(thintable_epi8[mask2], thintable_epi8[mask1]);
79515
      // we increment by 0x08 the second half of the mask
79516
      shufmask =
79517
      _mm_add_epi8(shufmask, _mm_set_epi32(0x08080808, 0x08080808, 0, 0));
79518
      // this is the version "nearly pruned"
79519
      __m128i pruned = _mm_shuffle_epi8(*this, shufmask);
79520
      // we still need to put the two halves together.
79521
      // we compute the popcount of the first half:
79522
      int pop1 = BitsSetTable256mul2[mask1];
79523
      // then load the corresponding mask, what it does is to write
79524
      // only the first pop1 bytes from the first 8 bytes, and then
79525
      // it fills in with the bytes from the second 8 bytes + some filling
79526
      // at the end.
79527
      __m128i compactmask =
79528
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop1 * 8));
79529
      __m128i answer = _mm_shuffle_epi8(pruned, compactmask);
79530
      _mm_storeu_si128(reinterpret_cast<__m128i *>(output), answer);
79531
    }
79532
79533
    template<typename L>
79534
    simdjson_inline simd8<L> lookup_16(
79535
        L replace0,  L replace1,  L replace2,  L replace3,
79536
        L replace4,  L replace5,  L replace6,  L replace7,
79537
        L replace8,  L replace9,  L replace10, L replace11,
79538
        L replace12, L replace13, L replace14, L replace15) const {
79539
      return lookup_16(simd8<L>::repeat_16(
79540
        replace0,  replace1,  replace2,  replace3,
79541
        replace4,  replace5,  replace6,  replace7,
79542
        replace8,  replace9,  replace10, replace11,
79543
        replace12, replace13, replace14, replace15
79544
      ));
79545
    }
79546
  };
79547
79548
  // Signed bytes
79549
  template<>
79550
  struct simd8<int8_t> : base8_numeric<int8_t> {
79551
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
79552
    simdjson_inline simd8(const __m128i _value) : base8_numeric<int8_t>(_value) {}
79553
    // Splat constructor
79554
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
79555
    // Array constructor
79556
    simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {}
79557
    // Member-by-member initialization
79558
    simdjson_inline simd8(
79559
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
79560
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
79561
    ) : simd8(_mm_setr_epi8(
79562
      v0, v1, v2, v3, v4, v5, v6, v7,
79563
      v8, v9, v10,v11,v12,v13,v14,v15
79564
    )) {}
79565
    // Repeat 16 values as many times as necessary (usually for lookup tables)
79566
    simdjson_inline static simd8<int8_t> repeat_16(
79567
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
79568
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
79569
    ) {
79570
      return simd8<int8_t>(
79571
        v0, v1, v2, v3, v4, v5, v6, v7,
79572
        v8, v9, v10,v11,v12,v13,v14,v15
79573
      );
79574
    }
79575
79576
    // Order-sensitive comparisons
79577
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm_max_epi8(*this, other); }
79578
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm_min_epi8(*this, other); }
79579
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(*this, other); }
79580
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(other, *this); }
79581
  };
79582
79583
  // Unsigned bytes
79584
  template<>
79585
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
79586
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
79587
    simdjson_inline simd8(const __m128i _value) : base8_numeric<uint8_t>(_value) {}
79588
    // Splat constructor
79589
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
79590
    // Array constructor
79591
    simdjson_inline simd8(const uint8_t* values) : simd8(load(values)) {}
79592
    // Member-by-member initialization
79593
    simdjson_inline simd8(
79594
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
79595
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
79596
    ) : simd8(_mm_setr_epi8(
79597
      v0, v1, v2, v3, v4, v5, v6, v7,
79598
      v8, v9, v10,v11,v12,v13,v14,v15
79599
    )) {}
79600
    // Repeat 16 values as many times as necessary (usually for lookup tables)
79601
    simdjson_inline static simd8<uint8_t> repeat_16(
79602
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
79603
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
79604
    ) {
79605
      return simd8<uint8_t>(
79606
        v0, v1, v2, v3, v4, v5, v6, v7,
79607
        v8, v9, v10,v11,v12,v13,v14,v15
79608
      );
79609
    }
79610
79611
    // Saturated math
79612
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm_adds_epu8(*this, other); }
79613
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm_subs_epu8(*this, other); }
79614
79615
    // Order-specific operations
79616
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm_max_epu8(*this, other); }
79617
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm_min_epu8(*this, other); }
79618
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
79619
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
79620
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
79621
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
79622
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
79623
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
79624
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
79625
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
79626
79627
    // Bit-specific operations
79628
    simdjson_inline simd8<bool> bits_not_set() const { return *this == uint8_t(0); }
79629
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
79630
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
79631
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
79632
    simdjson_inline bool is_ascii() const { return _mm_movemask_epi8(*this) == 0; }
79633
    simdjson_inline bool bits_not_set_anywhere() const { return _mm_testz_si128(*this, *this); }
79634
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
79635
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return _mm_testz_si128(*this, bits); }
79636
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
79637
    template<int N>
79638
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
79639
    template<int N>
79640
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
79641
    // Get one of the bits and make a bitmask out of it.
79642
    // e.g. value.get_bit<7>() gets the high bit
79643
    template<int N>
79644
    simdjson_inline int get_bit() const { return _mm_movemask_epi8(_mm_slli_epi16(*this, 7-N)); }
79645
  };
79646
79647
  template<typename T>
79648
  struct simd8x64 {
79649
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
79650
    static_assert(NUM_CHUNKS == 4, "Westmere kernel should use four registers per 64-byte block.");
79651
    const simd8<T> chunks[NUM_CHUNKS];
79652
79653
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
79654
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
79655
    simd8x64() = delete; // no default constructor allowed
79656
79657
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
79658
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
79659
79660
    simdjson_inline void store(T ptr[64]) const {
79661
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
79662
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
79663
      this->chunks[2].store(ptr+sizeof(simd8<T>)*2);
79664
      this->chunks[3].store(ptr+sizeof(simd8<T>)*3);
79665
    }
79666
79667
    simdjson_inline simd8<T> reduce_or() const {
79668
      return (this->chunks[0] | this->chunks[1]) | (this->chunks[2] | this->chunks[3]);
79669
    }
79670
79671
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
79672
      this->chunks[0].compress(uint16_t(mask), output);
79673
      this->chunks[1].compress(uint16_t(mask >> 16), output + 16 - count_ones(mask & 0xFFFF));
79674
      this->chunks[2].compress(uint16_t(mask >> 32), output + 32 - count_ones(mask & 0xFFFFFFFF));
79675
      this->chunks[3].compress(uint16_t(mask >> 48), output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
79676
      return 64 - count_ones(mask);
79677
    }
79678
79679
    simdjson_inline uint64_t to_bitmask() const {
79680
      uint64_t r0 = uint32_t(this->chunks[0].to_bitmask() );
79681
      uint64_t r1 =          this->chunks[1].to_bitmask() ;
79682
      uint64_t r2 =          this->chunks[2].to_bitmask() ;
79683
      uint64_t r3 =          this->chunks[3].to_bitmask() ;
79684
      return r0 | (r1 << 16) | (r2 << 32) | (r3 << 48);
79685
    }
79686
79687
    simdjson_inline uint64_t eq(const T m) const {
79688
      const simd8<T> mask = simd8<T>::splat(m);
79689
      return  simd8x64<bool>(
79690
        this->chunks[0] == mask,
79691
        this->chunks[1] == mask,
79692
        this->chunks[2] == mask,
79693
        this->chunks[3] == mask
79694
      ).to_bitmask();
79695
    }
79696
79697
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
79698
      return  simd8x64<bool>(
79699
        this->chunks[0] == other.chunks[0],
79700
        this->chunks[1] == other.chunks[1],
79701
        this->chunks[2] == other.chunks[2],
79702
        this->chunks[3] == other.chunks[3]
79703
      ).to_bitmask();
79704
    }
79705
79706
    simdjson_inline uint64_t lteq(const T m) const {
79707
      const simd8<T> mask = simd8<T>::splat(m);
79708
      return  simd8x64<bool>(
79709
        this->chunks[0] <= mask,
79710
        this->chunks[1] <= mask,
79711
        this->chunks[2] <= mask,
79712
        this->chunks[3] <= mask
79713
      ).to_bitmask();
79714
    }
79715
  }; // struct simd8x64<T>
79716
79717
} // namespace simd
79718
} // unnamed namespace
79719
} // namespace westmere
79720
} // namespace simdjson
79721
79722
#endif // SIMDJSON_WESTMERE_SIMD_INPUT_H
79723
/* end file simdjson/westmere/simd.h */
79724
/* including simdjson/westmere/stringparsing_defs.h: #include "simdjson/westmere/stringparsing_defs.h" */
79725
/* begin file simdjson/westmere/stringparsing_defs.h */
79726
#ifndef SIMDJSON_WESTMERE_STRINGPARSING_DEFS_H
79727
#define SIMDJSON_WESTMERE_STRINGPARSING_DEFS_H
79728
79729
/* including simdjson/westmere/bitmanipulation.h: #include "simdjson/westmere/bitmanipulation.h" */
79730
/* begin file simdjson/westmere/bitmanipulation.h */
79731
#ifndef SIMDJSON_WESTMERE_BITMANIPULATION_H
79732
#define SIMDJSON_WESTMERE_BITMANIPULATION_H
79733
79734
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79735
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
79736
/* amalgamation skipped (editor-only): #include "simdjson/westmere/intrinsics.h" */
79737
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79738
79739
namespace simdjson {
79740
namespace westmere {
79741
namespace {
79742
79743
// We sometimes call trailing_zero on inputs that are zero,
79744
// but the algorithms do not end up using the returned value.
79745
// Sadly, sanitizers are not smart enough to figure it out.
79746
SIMDJSON_NO_SANITIZE_UNDEFINED
79747
// This function can be used safely even if not all bytes have been
79748
// initialized.
79749
// See issue https://github.com/simdjson/simdjson/issues/1965
79750
SIMDJSON_NO_SANITIZE_MEMORY
79751
simdjson_inline int trailing_zeroes(uint64_t input_num) {
79752
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79753
  unsigned long ret;
79754
  // Search the mask data from least significant bit (LSB)
79755
  // to the most significant bit (MSB) for a set bit (1).
79756
  _BitScanForward64(&ret, input_num);
79757
  return (int)ret;
79758
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
79759
  return __builtin_ctzll(input_num);
79760
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
79761
}
79762
79763
/* result might be undefined when input_num is zero */
79764
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
79765
  return input_num & (input_num-1);
79766
}
79767
79768
/* result might be undefined when input_num is zero */
79769
simdjson_inline int leading_zeroes(uint64_t input_num) {
79770
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79771
  unsigned long leading_zero = 0;
79772
  // Search the mask data from most significant bit (MSB)
79773
  // to least significant bit (LSB) for a set bit (1).
79774
  if (_BitScanReverse64(&leading_zero, input_num))
79775
    return (int)(63 - leading_zero);
79776
  else
79777
    return 64;
79778
#else
79779
  return __builtin_clzll(input_num);
79780
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
79781
}
79782
79783
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79784
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
79785
  // note: we do not support legacy 32-bit Windows in this kernel
79786
  return __popcnt64(input_num);// Visual Studio wants two underscores
79787
}
79788
#else
79789
simdjson_inline long long int count_ones(uint64_t input_num) {
79790
  return _popcnt64(input_num);
79791
}
79792
#endif
79793
79794
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
79795
                                uint64_t *result) {
79796
#if SIMDJSON_REGULAR_VISUAL_STUDIO
79797
  return _addcarry_u64(0, value1, value2,
79798
                       reinterpret_cast<unsigned __int64 *>(result));
79799
#else
79800
  return __builtin_uaddll_overflow(value1, value2,
79801
                                   reinterpret_cast<unsigned long long *>(result));
79802
#endif
79803
}
79804
79805
} // unnamed namespace
79806
} // namespace westmere
79807
} // namespace simdjson
79808
79809
#endif // SIMDJSON_WESTMERE_BITMANIPULATION_H
79810
/* end file simdjson/westmere/bitmanipulation.h */
79811
/* including simdjson/westmere/simd.h: #include "simdjson/westmere/simd.h" */
79812
/* begin file simdjson/westmere/simd.h */
79813
#ifndef SIMDJSON_WESTMERE_SIMD_H
79814
#define SIMDJSON_WESTMERE_SIMD_H
79815
79816
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
79817
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
79818
/* amalgamation skipped (editor-only): #include "simdjson/westmere/bitmanipulation.h" */
79819
/* amalgamation skipped (editor-only): #include "simdjson/internal/simdprune_tables.h" */
79820
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
79821
79822
namespace simdjson {
79823
namespace westmere {
79824
namespace {
79825
namespace simd {
79826
79827
  template<typename Child>
79828
  struct base {
79829
    __m128i value;
79830
79831
    // Zero constructor
79832
    simdjson_inline base() : value{__m128i()} {}
79833
79834
    // Conversion from SIMD register
79835
    simdjson_inline base(const __m128i _value) : value(_value) {}
79836
79837
    // Conversion to SIMD register
79838
    simdjson_inline operator const __m128i&() const { return this->value; }
79839
    simdjson_inline operator __m128i&() { return this->value; }
79840
79841
    // Bit operations
79842
    simdjson_inline Child operator|(const Child other) const { return _mm_or_si128(*this, other); }
79843
    simdjson_inline Child operator&(const Child other) const { return _mm_and_si128(*this, other); }
79844
    simdjson_inline Child operator^(const Child other) const { return _mm_xor_si128(*this, other); }
79845
    simdjson_inline Child bit_andnot(const Child other) const { return _mm_andnot_si128(other, *this); }
79846
    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
79847
    simdjson_inline Child& operator&=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast & other; return *this_cast; }
79848
    simdjson_inline Child& operator^=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
79849
  };
79850
79851
  template<typename T, typename Mask=simd8<bool>>
79852
  struct base8: base<simd8<T>> {
79853
    typedef uint16_t bitmask_t;
79854
    typedef uint32_t bitmask2_t;
79855
79856
    simdjson_inline base8() : base<simd8<T>>() {}
79857
    simdjson_inline base8(const __m128i _value) : base<simd8<T>>(_value) {}
79858
79859
    friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return _mm_cmpeq_epi8(lhs, rhs); }
79860
79861
    static const int SIZE = sizeof(base<simd8<T>>::value);
79862
79863
    template<int N=1>
79864
    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
79865
      return _mm_alignr_epi8(*this, prev_chunk, 16 - N);
79866
    }
79867
  };
79868
79869
  // SIMD byte mask type (returned by things like eq and gt)
79870
  template<>
79871
  struct simd8<bool>: base8<bool> {
79872
    static simdjson_inline simd8<bool> splat(bool _value) { return _mm_set1_epi8(uint8_t(-(!!_value))); }
79873
79874
    simdjson_inline simd8<bool>() : base8() {}
79875
    simdjson_inline simd8<bool>(const __m128i _value) : base8<bool>(_value) {}
79876
    // Splat constructor
79877
    simdjson_inline simd8<bool>(bool _value) : base8<bool>(splat(_value)) {}
79878
79879
    simdjson_inline int to_bitmask() const { return _mm_movemask_epi8(*this); }
79880
    simdjson_inline bool any() const { return !_mm_testz_si128(*this, *this); }
79881
    simdjson_inline simd8<bool> operator~() const { return *this ^ true; }
79882
  };
79883
79884
  template<typename T>
79885
  struct base8_numeric: base8<T> {
79886
    static simdjson_inline simd8<T> splat(T _value) { return _mm_set1_epi8(_value); }
79887
    static simdjson_inline simd8<T> zero() { return _mm_setzero_si128(); }
79888
    static simdjson_inline simd8<T> load(const T values[16]) {
79889
      return _mm_loadu_si128(reinterpret_cast<const __m128i *>(values));
79890
    }
79891
    // Repeat 16 values as many times as necessary (usually for lookup tables)
79892
    static simdjson_inline simd8<T> repeat_16(
79893
      T v0,  T v1,  T v2,  T v3,  T v4,  T v5,  T v6,  T v7,
79894
      T v8,  T v9,  T v10, T v11, T v12, T v13, T v14, T v15
79895
    ) {
79896
      return simd8<T>(
79897
        v0, v1, v2, v3, v4, v5, v6, v7,
79898
        v8, v9, v10,v11,v12,v13,v14,v15
79899
      );
79900
    }
79901
79902
    simdjson_inline base8_numeric() : base8<T>() {}
79903
    simdjson_inline base8_numeric(const __m128i _value) : base8<T>(_value) {}
79904
79905
    // Store to array
79906
    simdjson_inline void store(T dst[16]) const { return _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), *this); }
79907
79908
    // Override to distinguish from bool version
79909
    simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
79910
79911
    // Addition/subtraction are the same for signed and unsigned
79912
    simdjson_inline simd8<T> operator+(const simd8<T> other) const { return _mm_add_epi8(*this, other); }
79913
    simdjson_inline simd8<T> operator-(const simd8<T> other) const { return _mm_sub_epi8(*this, other); }
79914
    simdjson_inline simd8<T>& operator+=(const simd8<T> other) { *this = *this + other; return *static_cast<simd8<T>*>(this); }
79915
    simdjson_inline simd8<T>& operator-=(const simd8<T> other) { *this = *this - other; return *static_cast<simd8<T>*>(this); }
79916
79917
    // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
79918
    template<typename L>
79919
    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
79920
      return _mm_shuffle_epi8(lookup_table, *this);
79921
    }
79922
79923
    // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
79924
    // Passing a 0 value for mask would be equivalent to writing out every byte to output.
79925
    // Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
79926
    // get written.
79927
    // Design consideration: it seems like a function with the
79928
    // signature simd8<L> compress(uint32_t mask) would be
79929
    // sensible, but the AVX ISA makes this kind of approach difficult.
79930
    template<typename L>
79931
    simdjson_inline void compress(uint16_t mask, L * output) const {
79932
      using internal::thintable_epi8;
79933
      using internal::BitsSetTable256mul2;
79934
      using internal::pshufb_combine_table;
79935
      // this particular implementation was inspired by work done by @animetosho
79936
      // we do it in two steps, first 8 bytes and then second 8 bytes
79937
      uint8_t mask1 = uint8_t(mask); // least significant 8 bits
79938
      uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
79939
      // next line just loads the 64-bit values thintable_epi8[mask1] and
79940
      // thintable_epi8[mask2] into a 128-bit register, using only
79941
      // two instructions on most compilers.
79942
      __m128i shufmask =  _mm_set_epi64x(thintable_epi8[mask2], thintable_epi8[mask1]);
79943
      // we increment by 0x08 the second half of the mask
79944
      shufmask =
79945
      _mm_add_epi8(shufmask, _mm_set_epi32(0x08080808, 0x08080808, 0, 0));
79946
      // this is the version "nearly pruned"
79947
      __m128i pruned = _mm_shuffle_epi8(*this, shufmask);
79948
      // we still need to put the two halves together.
79949
      // we compute the popcount of the first half:
79950
      int pop1 = BitsSetTable256mul2[mask1];
79951
      // then load the corresponding mask, what it does is to write
79952
      // only the first pop1 bytes from the first 8 bytes, and then
79953
      // it fills in with the bytes from the second 8 bytes + some filling
79954
      // at the end.
79955
      __m128i compactmask =
79956
      _mm_loadu_si128(reinterpret_cast<const __m128i *>(pshufb_combine_table + pop1 * 8));
79957
      __m128i answer = _mm_shuffle_epi8(pruned, compactmask);
79958
      _mm_storeu_si128(reinterpret_cast<__m128i *>(output), answer);
79959
    }
79960
79961
    template<typename L>
79962
    simdjson_inline simd8<L> lookup_16(
79963
        L replace0,  L replace1,  L replace2,  L replace3,
79964
        L replace4,  L replace5,  L replace6,  L replace7,
79965
        L replace8,  L replace9,  L replace10, L replace11,
79966
        L replace12, L replace13, L replace14, L replace15) const {
79967
      return lookup_16(simd8<L>::repeat_16(
79968
        replace0,  replace1,  replace2,  replace3,
79969
        replace4,  replace5,  replace6,  replace7,
79970
        replace8,  replace9,  replace10, replace11,
79971
        replace12, replace13, replace14, replace15
79972
      ));
79973
    }
79974
  };
79975
79976
  // Signed bytes
79977
  template<>
79978
  struct simd8<int8_t> : base8_numeric<int8_t> {
79979
    simdjson_inline simd8() : base8_numeric<int8_t>() {}
79980
    simdjson_inline simd8(const __m128i _value) : base8_numeric<int8_t>(_value) {}
79981
    // Splat constructor
79982
    simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
79983
    // Array constructor
79984
    simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {}
79985
    // Member-by-member initialization
79986
    simdjson_inline simd8(
79987
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
79988
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
79989
    ) : simd8(_mm_setr_epi8(
79990
      v0, v1, v2, v3, v4, v5, v6, v7,
79991
      v8, v9, v10,v11,v12,v13,v14,v15
79992
    )) {}
79993
    // Repeat 16 values as many times as necessary (usually for lookup tables)
79994
    simdjson_inline static simd8<int8_t> repeat_16(
79995
      int8_t v0,  int8_t v1,  int8_t v2,  int8_t v3,  int8_t v4,  int8_t v5,  int8_t v6,  int8_t v7,
79996
      int8_t v8,  int8_t v9,  int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
79997
    ) {
79998
      return simd8<int8_t>(
79999
        v0, v1, v2, v3, v4, v5, v6, v7,
80000
        v8, v9, v10,v11,v12,v13,v14,v15
80001
      );
80002
    }
80003
80004
    // Order-sensitive comparisons
80005
    simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> other) const { return _mm_max_epi8(*this, other); }
80006
    simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> other) const { return _mm_min_epi8(*this, other); }
80007
    simdjson_inline simd8<bool> operator>(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(*this, other); }
80008
    simdjson_inline simd8<bool> operator<(const simd8<int8_t> other) const { return _mm_cmpgt_epi8(other, *this); }
80009
  };
80010
80011
  // Unsigned bytes
80012
  template<>
80013
  struct simd8<uint8_t>: base8_numeric<uint8_t> {
80014
    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
80015
    simdjson_inline simd8(const __m128i _value) : base8_numeric<uint8_t>(_value) {}
80016
    // Splat constructor
80017
    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
80018
    // Array constructor
80019
    simdjson_inline simd8(const uint8_t* values) : simd8(load(values)) {}
80020
    // Member-by-member initialization
80021
    simdjson_inline simd8(
80022
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
80023
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
80024
    ) : simd8(_mm_setr_epi8(
80025
      v0, v1, v2, v3, v4, v5, v6, v7,
80026
      v8, v9, v10,v11,v12,v13,v14,v15
80027
    )) {}
80028
    // Repeat 16 values as many times as necessary (usually for lookup tables)
80029
    simdjson_inline static simd8<uint8_t> repeat_16(
80030
      uint8_t v0,  uint8_t v1,  uint8_t v2,  uint8_t v3,  uint8_t v4,  uint8_t v5,  uint8_t v6,  uint8_t v7,
80031
      uint8_t v8,  uint8_t v9,  uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
80032
    ) {
80033
      return simd8<uint8_t>(
80034
        v0, v1, v2, v3, v4, v5, v6, v7,
80035
        v8, v9, v10,v11,v12,v13,v14,v15
80036
      );
80037
    }
80038
80039
    // Saturated math
80040
    simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return _mm_adds_epu8(*this, other); }
80041
    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm_subs_epu8(*this, other); }
80042
80043
    // Order-specific operations
80044
    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm_max_epu8(*this, other); }
80045
    simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> other) const { return _mm_min_epu8(*this, other); }
80046
    // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
80047
    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
80048
    // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
80049
    simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return other.saturating_sub(*this); }
80050
    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
80051
    simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return other.min_val(*this) == other; }
80052
    simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
80053
    simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return this->gt_bits(other).any_bits_set(); }
80054
80055
    // Bit-specific operations
80056
    simdjson_inline simd8<bool> bits_not_set() const { return *this == uint8_t(0); }
80057
    simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const { return (*this & bits).bits_not_set(); }
80058
    simdjson_inline simd8<bool> any_bits_set() const { return ~this->bits_not_set(); }
80059
    simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const { return ~this->bits_not_set(bits); }
80060
    simdjson_inline bool is_ascii() const { return _mm_movemask_epi8(*this) == 0; }
80061
    simdjson_inline bool bits_not_set_anywhere() const { return _mm_testz_si128(*this, *this); }
80062
    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
80063
    simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const { return _mm_testz_si128(*this, bits); }
80064
    simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return !bits_not_set_anywhere(bits); }
80065
    template<int N>
80066
    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
80067
    template<int N>
80068
    simdjson_inline simd8<uint8_t> shl() const { return simd8<uint8_t>(_mm_slli_epi16(*this, N)) & uint8_t(0xFFu << N); }
80069
    // Get one of the bits and make a bitmask out of it.
80070
    // e.g. value.get_bit<7>() gets the high bit
80071
    template<int N>
80072
    simdjson_inline int get_bit() const { return _mm_movemask_epi8(_mm_slli_epi16(*this, 7-N)); }
80073
  };
80074
80075
  template<typename T>
80076
  struct simd8x64 {
80077
    static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
80078
    static_assert(NUM_CHUNKS == 4, "Westmere kernel should use four registers per 64-byte block.");
80079
    const simd8<T> chunks[NUM_CHUNKS];
80080
80081
    simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
80082
    simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
80083
    simd8x64() = delete; // no default constructor allowed
80084
80085
    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
80086
    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
80087
80088
    simdjson_inline void store(T ptr[64]) const {
80089
      this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
80090
      this->chunks[1].store(ptr+sizeof(simd8<T>)*1);
80091
      this->chunks[2].store(ptr+sizeof(simd8<T>)*2);
80092
      this->chunks[3].store(ptr+sizeof(simd8<T>)*3);
80093
    }
80094
80095
    simdjson_inline simd8<T> reduce_or() const {
80096
      return (this->chunks[0] | this->chunks[1]) | (this->chunks[2] | this->chunks[3]);
80097
    }
80098
80099
    simdjson_inline uint64_t compress(uint64_t mask, T * output) const {
80100
      this->chunks[0].compress(uint16_t(mask), output);
80101
      this->chunks[1].compress(uint16_t(mask >> 16), output + 16 - count_ones(mask & 0xFFFF));
80102
      this->chunks[2].compress(uint16_t(mask >> 32), output + 32 - count_ones(mask & 0xFFFFFFFF));
80103
      this->chunks[3].compress(uint16_t(mask >> 48), output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
80104
      return 64 - count_ones(mask);
80105
    }
80106
80107
    simdjson_inline uint64_t to_bitmask() const {
80108
      uint64_t r0 = uint32_t(this->chunks[0].to_bitmask() );
80109
      uint64_t r1 =          this->chunks[1].to_bitmask() ;
80110
      uint64_t r2 =          this->chunks[2].to_bitmask() ;
80111
      uint64_t r3 =          this->chunks[3].to_bitmask() ;
80112
      return r0 | (r1 << 16) | (r2 << 32) | (r3 << 48);
80113
    }
80114
80115
    simdjson_inline uint64_t eq(const T m) const {
80116
      const simd8<T> mask = simd8<T>::splat(m);
80117
      return  simd8x64<bool>(
80118
        this->chunks[0] == mask,
80119
        this->chunks[1] == mask,
80120
        this->chunks[2] == mask,
80121
        this->chunks[3] == mask
80122
      ).to_bitmask();
80123
    }
80124
80125
    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
80126
      return  simd8x64<bool>(
80127
        this->chunks[0] == other.chunks[0],
80128
        this->chunks[1] == other.chunks[1],
80129
        this->chunks[2] == other.chunks[2],
80130
        this->chunks[3] == other.chunks[3]
80131
      ).to_bitmask();
80132
    }
80133
80134
    simdjson_inline uint64_t lteq(const T m) const {
80135
      const simd8<T> mask = simd8<T>::splat(m);
80136
      return  simd8x64<bool>(
80137
        this->chunks[0] <= mask,
80138
        this->chunks[1] <= mask,
80139
        this->chunks[2] <= mask,
80140
        this->chunks[3] <= mask
80141
      ).to_bitmask();
80142
    }
80143
  }; // struct simd8x64<T>
80144
80145
} // namespace simd
80146
} // unnamed namespace
80147
} // namespace westmere
80148
} // namespace simdjson
80149
80150
#endif // SIMDJSON_WESTMERE_SIMD_INPUT_H
80151
/* end file simdjson/westmere/simd.h */
80152
80153
namespace simdjson {
80154
namespace westmere {
80155
namespace {
80156
80157
using namespace simd;
80158
80159
// Holds backslashes and quotes locations.
80160
struct backslash_and_quote {
80161
public:
80162
  static constexpr uint32_t BYTES_PROCESSED = 32;
80163
  simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
80164
80165
  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
80166
  simdjson_inline bool has_backslash() { return bs_bits != 0; }
80167
  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
80168
  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
80169
80170
  uint32_t bs_bits;
80171
  uint32_t quote_bits;
80172
}; // struct backslash_and_quote
80173
80174
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
80175
  // this can read up to 31 bytes beyond the buffer size, but we require
80176
  // SIMDJSON_PADDING of padding
80177
  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
80178
  simd8<uint8_t> v0(src);
80179
  simd8<uint8_t> v1(src + 16);
80180
  v0.store(dst);
80181
  v1.store(dst + 16);
80182
  uint64_t bs_and_quote = simd8x64<bool>(v0 == '\\', v1 == '\\', v0 == '"', v1 == '"').to_bitmask();
80183
  return {
80184
    uint32_t(bs_and_quote),      // bs_bits
80185
    uint32_t(bs_and_quote >> 32) // quote_bits
80186
  };
80187
}
80188
80189
} // unnamed namespace
80190
} // namespace westmere
80191
} // namespace simdjson
80192
80193
#endif // SIMDJSON_WESTMERE_STRINGPARSING_DEFS_H
80194
/* end file simdjson/westmere/stringparsing_defs.h */
80195
/* end file simdjson/westmere/begin.h */
80196
/* including simdjson/generic/ondemand/amalgamated.h for westmere: #include "simdjson/generic/ondemand/amalgamated.h" */
80197
/* begin file simdjson/generic/ondemand/amalgamated.h for westmere */
80198
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
80199
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
80200
#endif
80201
80202
// Stuff other things depend on
80203
/* including simdjson/generic/ondemand/base.h for westmere: #include "simdjson/generic/ondemand/base.h" */
80204
/* begin file simdjson/generic/ondemand/base.h for westmere */
80205
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
80206
80207
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
80208
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_BASE_H */
80209
/* amalgamation skipped (editor-only): #include "simdjson/generic/base.h" */
80210
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
80211
80212
namespace simdjson {
80213
namespace westmere {
80214
/**
80215
 * A fast, simple, DOM-like interface that parses JSON as you use it.
80216
 *
80217
 * Designed for maximum speed and a lower memory profile.
80218
 */
80219
namespace ondemand {
80220
80221
/** Represents the depth of a JSON value (number of nested arrays/objects). */
80222
using depth_t = int32_t;
80223
80224
/** @copydoc simdjson::westmere::number_type */
80225
using number_type = simdjson::westmere::number_type;
80226
80227
/** @private Position in the JSON buffer indexes */
80228
using token_position = const uint32_t *;
80229
80230
class array;
80231
class array_iterator;
80232
class document;
80233
class document_reference;
80234
class document_stream;
80235
class field;
80236
class json_iterator;
80237
enum class json_type;
80238
struct number;
80239
class object;
80240
class object_iterator;
80241
class parser;
80242
class raw_json_string;
80243
class token_iterator;
80244
class value;
80245
class value_iterator;
80246
80247
} // namespace ondemand
80248
} // namespace westmere
80249
} // namespace simdjson
80250
80251
#endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H
80252
/* end file simdjson/generic/ondemand/base.h for westmere */
80253
/* including simdjson/generic/ondemand/value_iterator.h for westmere: #include "simdjson/generic/ondemand/value_iterator.h" */
80254
/* begin file simdjson/generic/ondemand/value_iterator.h for westmere */
80255
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
80256
80257
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
80258
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H */
80259
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
80260
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
80261
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
80262
80263
namespace simdjson {
80264
namespace westmere {
80265
namespace ondemand {
80266
80267
/**
80268
 * Iterates through a single JSON value at a particular depth.
80269
 *
80270
 * Does not keep track of the type of value: provides methods for objects, arrays and scalars and expects
80271
 * the caller to call the right ones.
80272
 *
80273
 * @private This is not intended for external use.
80274
 */
80275
class value_iterator {
80276
protected:
80277
  /** The underlying JSON iterator */
80278
  json_iterator *_json_iter{};
80279
  /** The depth of this value */
80280
  depth_t _depth{};
80281
  /**
80282
   * The starting token index for this value
80283
   */
80284
  token_position _start_position{};
80285
80286
public:
80287
  simdjson_inline value_iterator() noexcept = default;
80288
80289
  /**
80290
   * Denote that we're starting a document.
80291
   */
80292
  simdjson_inline void start_document() noexcept;
80293
80294
  /**
80295
   * Skips a non-iterated or partially-iterated JSON value, whether it is a scalar, array or object.
80296
   *
80297
   * Optimized for scalars.
80298
   */
80299
  simdjson_warn_unused simdjson_inline error_code skip_child() noexcept;
80300
80301
  /**
80302
   * Tell whether the iterator is at the EOF mark
80303
   */
80304
  simdjson_inline bool at_end() const noexcept;
80305
80306
  /**
80307
   * Tell whether the iterator is at the start of the value
80308
   */
80309
  simdjson_inline bool at_start() const noexcept;
80310
80311
  /**
80312
   * Tell whether the value is open--if the value has not been used, or the array/object is still open.
80313
   */
80314
  simdjson_inline bool is_open() const noexcept;
80315
80316
  /**
80317
   * Tell whether the value is at an object's first field (just after the {).
80318
   */
80319
  simdjson_inline bool at_first_field() const noexcept;
80320
80321
  /**
80322
   * Abandon all iteration.
80323
   */
80324
  simdjson_inline void abandon() noexcept;
80325
80326
  /**
80327
   * Get the child value as a value_iterator.
80328
   */
80329
  simdjson_inline value_iterator child_value() const noexcept;
80330
80331
  /**
80332
   * Get the depth of this value.
80333
   */
80334
  simdjson_inline int32_t depth() const noexcept;
80335
80336
  /**
80337
   * Get the JSON type of this value.
80338
   *
80339
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
80340
   */
80341
  simdjson_inline simdjson_result<json_type> type() const noexcept;
80342
80343
  /**
80344
   * @addtogroup object Object iteration
80345
   *
80346
   * Methods to iterate and find object fields. These methods generally *assume* the value is
80347
   * actually an object; the caller is responsible for keeping track of that fact.
80348
   *
80349
   * @{
80350
   */
80351
80352
  /**
80353
   * Start an object iteration.
80354
   *
80355
   * @returns Whether the object had any fields (returns false for empty).
80356
   * @error INCORRECT_TYPE if there is no opening {
80357
   */
80358
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_object() noexcept;
80359
  /**
80360
   * Start an object iteration from the root.
80361
   *
80362
   * @returns Whether the object had any fields (returns false for empty).
80363
   * @error INCORRECT_TYPE if there is no opening {
80364
   * @error TAPE_ERROR if there is no matching } at end of document
80365
   */
80366
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_object() noexcept;
80367
  /**
80368
   * Checks whether an object could be started from the root. May be called by start_root_object.
80369
   *
80370
   * @returns SUCCESS if it is possible to safely start an object from the root (document level).
80371
   * @error INCORRECT_TYPE if there is no opening {
80372
   * @error TAPE_ERROR if there is no matching } at end of document
80373
   */
80374
  simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept;
80375
  /**
80376
   * Start an object iteration after the user has already checked and moved past the {.
80377
   *
80378
   * Does not move the iterator unless the object is empty ({}).
80379
   *
80380
   * @returns Whether the object had any fields (returns false for empty).
80381
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
80382
   *        array or object is incomplete).
80383
   */
80384
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_object() noexcept;
80385
  /**
80386
   * Start an object iteration from the root, after the user has already checked and moved past the {.
80387
   *
80388
   * Does not move the iterator unless the object is empty ({}).
80389
   *
80390
   * @returns Whether the object had any fields (returns false for empty).
80391
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
80392
   *        array or object is incomplete).
80393
   */
80394
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_object() noexcept;
80395
80396
  /**
80397
   * Moves to the next field in an object.
80398
   *
80399
   * Looks for , and }. If } is found, the object is finished and the iterator advances past it.
80400
   * Otherwise, it advances to the next value.
80401
   *
80402
   * @return whether there is another field in the object.
80403
   * @error TAPE_ERROR If there is a comma missing between fields.
80404
   * @error TAPE_ERROR If there is a comma, but not enough tokens remaining to have a key, :, and value.
80405
   */
80406
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_field() noexcept;
80407
80408
  /**
80409
   * Get the current field's key.
80410
   */
80411
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> field_key() noexcept;
80412
80413
  /**
80414
   * Pass the : in the field and move to its value.
80415
   */
80416
  simdjson_warn_unused simdjson_inline error_code field_value() noexcept;
80417
80418
  /**
80419
   * Find the next field with the given key.
80420
   *
80421
   * Assumes you have called next_field() or otherwise matched the previous value.
80422
   *
80423
   * This means the iterator must be sitting at the next key:
80424
   *
80425
   * ```
80426
   * { "a": 1, "b": 2 }
80427
   *           ^
80428
   * ```
80429
   *
80430
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
80431
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
80432
   * fail to match some keys with escapes (\u, \n, etc.).
80433
   */
80434
  simdjson_warn_unused simdjson_inline error_code find_field(const std::string_view key) noexcept;
80435
80436
  /**
80437
   * Find the next field with the given key, *without* unescaping. This assumes object order: it
80438
   * will not find the field if it was already passed when looking for some *other* field.
80439
   *
80440
   * Assumes you have called next_field() or otherwise matched the previous value.
80441
   *
80442
   * This means the iterator must be sitting at the next key:
80443
   *
80444
   * ```
80445
   * { "a": 1, "b": 2 }
80446
   *           ^
80447
   * ```
80448
   *
80449
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
80450
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
80451
   * fail to match some keys with escapes (\u, \n, etc.).
80452
   */
80453
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
80454
80455
  /**
80456
   * Find the field with the given key without regard to order, and *without* unescaping.
80457
   *
80458
   * This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
80459
   *
80460
   * Assumes you have called next_field() or otherwise matched the previous value.
80461
   *
80462
   * This means the iterator must be sitting at the next key:
80463
   *
80464
   * ```
80465
   * { "a": 1, "b": 2 }
80466
   *           ^
80467
   * ```
80468
   *
80469
   * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
80470
   * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
80471
   * fail to match some keys with escapes (\u, \n, etc.).
80472
   */
80473
  simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
80474
80475
  /** @} */
80476
80477
  /**
80478
   * @addtogroup array Array iteration
80479
   * Methods to iterate over array elements. These methods generally *assume* the value is actually
80480
   * an object; the caller is responsible for keeping track of that fact.
80481
   * @{
80482
   */
80483
80484
  /**
80485
   * Check for an opening [ and start an array iteration.
80486
   *
80487
   * @returns Whether the array had any elements (returns false for empty).
80488
   * @error INCORRECT_TYPE If there is no [.
80489
   */
80490
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_array() noexcept;
80491
  /**
80492
   * Check for an opening [ and start an array iteration while at the root.
80493
   *
80494
   * @returns Whether the array had any elements (returns false for empty).
80495
   * @error INCORRECT_TYPE If there is no [.
80496
   * @error TAPE_ERROR if there is no matching ] at end of document
80497
   */
80498
  simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_array() noexcept;
80499
  /**
80500
   * Checks whether an array could be started from the root. May be called by start_root_array.
80501
   *
80502
   * @returns SUCCESS if it is possible to safely start an array from the root (document level).
80503
   * @error INCORRECT_TYPE If there is no [.
80504
   * @error TAPE_ERROR if there is no matching ] at end of document
80505
   */
80506
  simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept;
80507
  /**
80508
   * Start an array iteration, after the user has already checked and moved past the [.
80509
   *
80510
   * Does not move the iterator unless the array is empty ([]).
80511
   *
80512
   * @returns Whether the array had any elements (returns false for empty).
80513
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
80514
   *        array or object is incomplete).
80515
   */
80516
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_array() noexcept;
80517
  /**
80518
   * Start an array iteration from the root, after the user has already checked and moved past the [.
80519
   *
80520
   * Does not move the iterator unless the array is empty ([]).
80521
   *
80522
   * @returns Whether the array had any elements (returns false for empty).
80523
   * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
80524
   *        array or object is incomplete).
80525
   */
80526
  simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_array() noexcept;
80527
80528
  /**
80529
   * Moves to the next element in an array.
80530
   *
80531
   * Looks for , and ]. If ] is found, the array is finished and the iterator advances past it.
80532
   * Otherwise, it advances to the next value.
80533
   *
80534
   * @return Whether there is another element in the array.
80535
   * @error TAPE_ERROR If there is a comma missing between elements.
80536
   */
80537
  simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_element() noexcept;
80538
80539
  /**
80540
   * Get a child value iterator.
80541
   */
80542
  simdjson_warn_unused simdjson_inline value_iterator child() const noexcept;
80543
80544
  /** @} */
80545
80546
  /**
80547
   * @defgroup scalar Scalar values
80548
   * @addtogroup scalar
80549
   * @{
80550
   */
80551
80552
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
80553
  template <typename string_type>
80554
  simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
80555
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
80556
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
80557
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
80558
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
80559
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
80560
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
80561
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
80562
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
80563
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
80564
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
80565
  simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
80566
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
80567
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
80568
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
80569
80570
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
80571
  template <typename string_type>
80572
  simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
80573
  simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
80574
  simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
80575
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
80576
  simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
80577
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
80578
  simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
80579
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
80580
  simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
80581
  simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
80582
  simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
80583
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
80584
  simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
80585
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
80586
  simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
80587
80588
  simdjson_inline error_code error() const noexcept;
80589
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
80590
  simdjson_inline const json_iterator &json_iter() const noexcept;
80591
  simdjson_inline json_iterator &json_iter() noexcept;
80592
80593
  simdjson_inline void assert_is_valid() const noexcept;
80594
  simdjson_inline bool is_valid() const noexcept;
80595
80596
  /** @} */
80597
protected:
80598
  /**
80599
   * Restarts an array iteration.
80600
   * @returns Whether the array has any elements (returns false for empty).
80601
   */
80602
  simdjson_inline simdjson_result<bool> reset_array() noexcept;
80603
  /**
80604
   * Restarts an object iteration.
80605
   * @returns Whether the object has any fields (returns false for empty).
80606
   */
80607
  simdjson_inline simdjson_result<bool> reset_object() noexcept;
80608
  /**
80609
   * move_at_start(): moves us so that we are pointing at the beginning of
80610
   * the container. It updates the index so that at_start() is true and it
80611
   * syncs the depth. The user can then create a new container instance.
80612
   *
80613
   * Usage: used with value::count_elements().
80614
   **/
80615
  simdjson_inline void move_at_start() noexcept;
80616
80617
  /**
80618
   * move_at_container_start(): moves us so that we are pointing at the beginning of
80619
   * the container so that assert_at_container_start() passes.
80620
   *
80621
   * Usage: used with reset_array() and reset_object().
80622
   **/
80623
   simdjson_inline void move_at_container_start() noexcept;
80624
  /* Useful for debugging and logging purposes. */
80625
  inline std::string to_string() const noexcept;
80626
  simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
80627
80628
  simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
80629
  simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
80630
  simdjson_inline const uint8_t *peek_start() const noexcept;
80631
  simdjson_inline uint32_t peek_start_length() const noexcept;
80632
  simdjson_inline uint32_t peek_root_length() const noexcept;
80633
80634
  /**
80635
   * The general idea of the advance_... methods and the peek_* methods
80636
   * is that you first peek and check that you have desired type. If you do,
80637
   * and only if you do, then you advance.
80638
   *
80639
   * We used to unconditionally advance. But this made reasoning about our
80640
   * current state difficult.
80641
   * Suppose you always advance. Look at the 'value' matching the key
80642
   * "shadowable" in the following example...
80643
   *
80644
   * ({"globals":{"a":{"shadowable":[}}}})
80645
   *
80646
   * If the user thinks it is a Boolean and asks for it, then we check the '[',
80647
   * decide it is not a Boolean, but still move into the next character ('}'). Now
80648
   * we are left pointing at '}' right after a '['. And we have not yet reported
80649
   * an error, only that we do not have a Boolean.
80650
   *
80651
   * If, instead, you just stand your ground until it is content that you know, then
80652
   * you will only even move beyond the '[' if the user tells you that you have an
80653
   * array. So you will be at the '}' character inside the array and, hopefully, you
80654
   * will then catch the error because an array cannot start with '}', but the code
80655
   * processing Boolean values does not know this.
80656
   *
80657
   * So the contract is: first call 'peek_...' and then call 'advance_...' only
80658
   * if you have determined that it is a type you can handle.
80659
   *
80660
   * Unfortunately, it makes the code more verbose, longer and maybe more error prone.
80661
   */
80662
80663
  simdjson_inline void advance_scalar(const char *type) noexcept;
80664
  simdjson_inline void advance_root_scalar(const char *type) noexcept;
80665
  simdjson_inline void advance_non_root_scalar(const char *type) noexcept;
80666
80667
  simdjson_inline const uint8_t *peek_scalar(const char *type) noexcept;
80668
  simdjson_inline const uint8_t *peek_root_scalar(const char *type) noexcept;
80669
  simdjson_inline const uint8_t *peek_non_root_scalar(const char *type) noexcept;
80670
80671
80672
  simdjson_inline error_code start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept;
80673
  simdjson_inline error_code end_container() noexcept;
80674
80675
  /**
80676
   * Advance to a place expecting a value (increasing depth).
80677
   *
80678
   * @return The current token (the one left behind).
80679
   * @error TAPE_ERROR If the document ended early.
80680
   */
80681
  simdjson_inline simdjson_result<const uint8_t *> advance_to_value() noexcept;
80682
80683
  simdjson_inline error_code incorrect_type_error(const char *message) const noexcept;
80684
  simdjson_inline error_code error_unless_more_tokens(uint32_t tokens=1) const noexcept;
80685
80686
  simdjson_inline bool is_at_start() const noexcept;
80687
  /**
80688
   * is_at_iterator_start() returns true on an array or object after it has just been
80689
   * created, whether the instance is empty or not.
80690
   *
80691
   * Usage: used by array::begin() in debug mode (SIMDJSON_DEVELOPMENT_CHECKS)
80692
   */
80693
  simdjson_inline bool is_at_iterator_start() const noexcept;
80694
80695
  /**
80696
   * Assuming that we are within an object, this returns true if we
80697
   * are pointing at a key.
80698
   *
80699
   * Usage: the skip_child() method should never be used while we are pointing
80700
   * at a key inside an object.
80701
   */
80702
  simdjson_inline bool is_at_key() const noexcept;
80703
80704
  inline void assert_at_start() const noexcept;
80705
  inline void assert_at_container_start() const noexcept;
80706
  inline void assert_at_root() const noexcept;
80707
  inline void assert_at_child() const noexcept;
80708
  inline void assert_at_next() const noexcept;
80709
  inline void assert_at_non_root_start() const noexcept;
80710
80711
  /** Get the starting position of this value */
80712
  simdjson_inline token_position start_position() const noexcept;
80713
80714
  /** @copydoc error_code json_iterator::position() const noexcept; */
80715
  simdjson_inline token_position position() const noexcept;
80716
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
80717
  simdjson_inline token_position last_position() const noexcept;
80718
  /** @copydoc error_code json_iterator::end_position() const noexcept; */
80719
  simdjson_inline token_position end_position() const noexcept;
80720
  /** @copydoc error_code json_iterator::report_error(error_code error, const char *message) noexcept; */
80721
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
80722
80723
  friend class document;
80724
  friend class object;
80725
  friend class array;
80726
  friend class value;
80727
  friend class field;
80728
}; // value_iterator
80729
80730
} // namespace ondemand
80731
} // namespace westmere
80732
} // namespace simdjson
80733
80734
namespace simdjson {
80735
80736
template<>
80737
struct simdjson_result<westmere::ondemand::value_iterator> : public westmere::implementation_simdjson_result_base<westmere::ondemand::value_iterator> {
80738
public:
80739
  simdjson_inline simdjson_result(westmere::ondemand::value_iterator &&value) noexcept; ///< @private
80740
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
80741
  simdjson_inline simdjson_result() noexcept = default;
80742
};
80743
80744
} // namespace simdjson
80745
80746
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
80747
/* end file simdjson/generic/ondemand/value_iterator.h for westmere */
80748
/* including simdjson/generic/ondemand/value.h for westmere: #include "simdjson/generic/ondemand/value.h" */
80749
/* begin file simdjson/generic/ondemand/value.h for westmere */
80750
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H
80751
80752
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
80753
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_H */
80754
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
80755
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
80756
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
80757
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
80758
80759
namespace simdjson {
80760
namespace westmere {
80761
namespace ondemand {
80762
80763
/**
80764
 * An ephemeral JSON value returned during iteration. It is only valid for as long as you do
80765
 * not access more data in the JSON document.
80766
 */
80767
class value {
80768
public:
80769
  /**
80770
   * Create a new invalid value.
80771
   *
80772
   * Exists so you can declare a variable and later assign to it before use.
80773
   */
80774
  simdjson_inline value() noexcept = default;
80775
80776
  /**
80777
   * Get this value as the given type.
80778
   *
80779
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
80780
   *
80781
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
80782
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
80783
   *
80784
   * @returns A value of the given type, parsed from the JSON.
80785
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
80786
   */
80787
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
80788
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
80789
    // immediately fail.
80790
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
80791
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
80792
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
80793
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
80794
      " You may also add support for custom types, see our documentation.");
80795
  }
80796
80797
  /**
80798
   * Get this value as the given type.
80799
   *
80800
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
80801
   *
80802
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
80803
   * @returns INCORRECT_TYPE If the JSON value is not an object.
80804
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
80805
   */
80806
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
80807
80808
  /**
80809
   * Cast this JSON value to an array.
80810
   *
80811
   * @returns An object that can be used to iterate the array.
80812
   * @returns INCORRECT_TYPE If the JSON value is not an array.
80813
   */
80814
  simdjson_inline simdjson_result<array> get_array() noexcept;
80815
80816
  /**
80817
   * Cast this JSON value to an object.
80818
   *
80819
   * @returns An object that can be used to look up or iterate fields.
80820
   * @returns INCORRECT_TYPE If the JSON value is not an object.
80821
   */
80822
  simdjson_inline simdjson_result<object> get_object() noexcept;
80823
80824
  /**
80825
   * Cast this JSON value to an unsigned integer.
80826
   *
80827
   * @returns A unsigned 64-bit integer.
80828
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
80829
   */
80830
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
80831
80832
  /**
80833
   * Cast this JSON value (inside string) to a unsigned integer.
80834
   *
80835
   * @returns A unsigned 64-bit integer.
80836
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
80837
   */
80838
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
80839
80840
  /**
80841
   * Cast this JSON value to a signed integer.
80842
   *
80843
   * @returns A signed 64-bit integer.
80844
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
80845
   */
80846
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
80847
80848
  /**
80849
   * Cast this JSON value (inside string) to a signed integer.
80850
   *
80851
   * @returns A signed 64-bit integer.
80852
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
80853
   */
80854
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
80855
80856
  /**
80857
   * Cast this JSON value to a double.
80858
   *
80859
   * @returns A double.
80860
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
80861
   */
80862
  simdjson_inline simdjson_result<double> get_double() noexcept;
80863
80864
  /**
80865
   * Cast this JSON value (inside string) to a double
80866
   *
80867
   * @returns A double.
80868
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
80869
   */
80870
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
80871
80872
  /**
80873
   * Cast this JSON value to a string.
80874
   *
80875
   * The string is guaranteed to be valid UTF-8.
80876
   *
80877
   * Equivalent to get<std::string_view>().
80878
   *
80879
   * Important: a value should be consumed once. Calling get_string() twice on the same value
80880
   * is an error.
80881
   *
80882
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
80883
   *          time it parses a document or when it is destroyed.
80884
   * @returns INCORRECT_TYPE if the JSON value is not a string.
80885
   */
80886
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
80887
80888
  /**
80889
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
80890
   *
80891
   * The string is guaranteed to be valid UTF-8.
80892
   *
80893
   * Important: a value should be consumed once. Calling get_string() twice on the same value
80894
   * is an error.
80895
   *
80896
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
80897
   * We recommend you avoid allocating an std::string unless you need to.
80898
   *
80899
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
80900
   */
80901
  template <typename string_type>
80902
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
80903
80904
  /**
80905
   * Cast this JSON value to a "wobbly" string.
80906
   *
80907
   * The string is may not be a valid UTF-8 string.
80908
   * See https://simonsapin.github.io/wtf-8/
80909
   *
80910
   * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value
80911
   * is an error.
80912
   *
80913
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
80914
   *          time it parses a document or when it is destroyed.
80915
   * @returns INCORRECT_TYPE if the JSON value is not a string.
80916
   */
80917
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
80918
  /**
80919
   * Cast this JSON value to a raw_json_string.
80920
   *
80921
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
80922
   *
80923
   * @returns A pointer to the raw JSON for the given string.
80924
   * @returns INCORRECT_TYPE if the JSON value is not a string.
80925
   */
80926
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
80927
80928
  /**
80929
   * Cast this JSON value to a bool.
80930
   *
80931
   * @returns A bool value.
80932
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
80933
   */
80934
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
80935
80936
  /**
80937
   * Checks if this JSON value is null. If and only if the value is
80938
   * null, then it is consumed (we advance). If we find a token that
80939
   * begins with 'n' but is not 'null', then an error is returned.
80940
   *
80941
   * @returns Whether the value is null.
80942
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
80943
   */
80944
  simdjson_inline simdjson_result<bool> is_null() noexcept;
80945
80946
#if SIMDJSON_EXCEPTIONS
80947
  /**
80948
   * Cast this JSON value to an instance of type T. The programmer is responsible for
80949
   * providing an implementation of get<T> for the type T, if T is not one of the types
80950
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.).
80951
   *
80952
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
80953
   *
80954
   * @returns An instance of type T
80955
   */
80956
  template <class T>
80957
  explicit simdjson_inline operator T() noexcept(false);
80958
  /**
80959
   * Cast this JSON value to an array.
80960
   *
80961
   * @returns An object that can be used to iterate the array.
80962
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
80963
   */
80964
  simdjson_inline operator array() noexcept(false);
80965
  /**
80966
   * Cast this JSON value to an object.
80967
   *
80968
   * @returns An object that can be used to look up or iterate fields.
80969
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
80970
   */
80971
  simdjson_inline operator object() noexcept(false);
80972
  /**
80973
   * Cast this JSON value to an unsigned integer.
80974
   *
80975
   * @returns A signed 64-bit integer.
80976
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
80977
   */
80978
  simdjson_inline operator uint64_t() noexcept(false);
80979
  /**
80980
   * Cast this JSON value to a signed integer.
80981
   *
80982
   * @returns A signed 64-bit integer.
80983
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
80984
   */
80985
  simdjson_inline operator int64_t() noexcept(false);
80986
  /**
80987
   * Cast this JSON value to a double.
80988
   *
80989
   * @returns A double.
80990
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
80991
   */
80992
  simdjson_inline operator double() noexcept(false);
80993
  /**
80994
   * Cast this JSON value to a string.
80995
   *
80996
   * The string is guaranteed to be valid UTF-8.
80997
   *
80998
   * Equivalent to get<std::string_view>().
80999
   *
81000
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
81001
   *          time it parses a document or when it is destroyed.
81002
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
81003
   */
81004
  simdjson_inline operator std::string_view() noexcept(false);
81005
  /**
81006
   * Cast this JSON value to a raw_json_string.
81007
   *
81008
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
81009
   *
81010
   * @returns A pointer to the raw JSON for the given string.
81011
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
81012
   */
81013
  simdjson_inline operator raw_json_string() noexcept(false);
81014
  /**
81015
   * Cast this JSON value to a bool.
81016
   *
81017
   * @returns A bool value.
81018
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
81019
   */
81020
  simdjson_inline operator bool() noexcept(false);
81021
#endif
81022
81023
  /**
81024
   * Begin array iteration.
81025
   *
81026
   * Part of the std::iterable interface.
81027
   *
81028
   * @returns INCORRECT_TYPE If the JSON value is not an array.
81029
   */
81030
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
81031
  /**
81032
   * Sentinel representing the end of the array.
81033
   *
81034
   * Part of the std::iterable interface.
81035
   */
81036
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
81037
  /**
81038
   * This method scans the array and counts the number of elements.
81039
   * The count_elements method should always be called before you have begun
81040
   * iterating through the array: it is expected that you are pointing at
81041
   * the beginning of the array.
81042
   * The runtime complexity is linear in the size of the array. After
81043
   * calling this function, if successful, the array is 'rewinded' at its
81044
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
81045
   * there is a missing comma), then an error is returned and it is no longer
81046
   * safe to continue.
81047
   *
81048
   * Performance hint: You should only call count_elements() as a last
81049
   * resort as it may require scanning the document twice or more.
81050
   */
81051
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
81052
  /**
81053
   * This method scans the object and counts the number of key-value pairs.
81054
   * The count_fields method should always be called before you have begun
81055
   * iterating through the object: it is expected that you are pointing at
81056
   * the beginning of the object.
81057
   * The runtime complexity is linear in the size of the object. After
81058
   * calling this function, if successful, the object is 'rewinded' at its
81059
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
81060
   * there is a missing comma), then an error is returned and it is no longer
81061
   * safe to continue.
81062
   *
81063
   * To check that an object is empty, it is more performant to use
81064
   * the is_empty() method on the object instance.
81065
   *
81066
   * Performance hint: You should only call count_fields() as a last
81067
   * resort as it may require scanning the document twice or more.
81068
   */
81069
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
81070
  /**
81071
   * Get the value at the given index in the array. This function has linear-time complexity.
81072
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
81073
   *
81074
   * @return The value at the given index, or:
81075
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
81076
   */
81077
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
81078
  /**
81079
   * Look up a field by name on an object (order-sensitive).
81080
   *
81081
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
81082
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
81083
   *
81084
   * ```c++
81085
   * simdjson::ondemand::parser parser;
81086
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
81087
   * double z = obj.find_field("z");
81088
   * double y = obj.find_field("y");
81089
   * double x = obj.find_field("x");
81090
   * ```
81091
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
81092
   * that only one field is returned.
81093
81094
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
81095
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
81096
   *
81097
   * @param key The key to look up.
81098
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
81099
   */
81100
  simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept;
81101
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
81102
  simdjson_inline simdjson_result<value> find_field(const char *key) noexcept;
81103
81104
  /**
81105
   * Look up a field by name on an object, without regard to key order.
81106
   *
81107
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
81108
   * and often appears negligible. It starts out normally, starting out at the last field; but if
81109
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
81110
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
81111
   * in question is large. The fact that the extra code is there also bumps the executable size.
81112
   *
81113
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
81114
   * default behavior failed to look up a field just because it was in the wrong order--and many
81115
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
81116
   *
81117
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
81118
   * that only one field is returned.
81119
   *
81120
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
81121
   * field as not there when they are not in order).
81122
   *
81123
   * @param key The key to look up.
81124
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
81125
   */
81126
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
81127
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
81128
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
81129
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
81130
  simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept;
81131
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
81132
  simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
81133
81134
  /**
81135
   * Get the type of this JSON value. It does not validate or consume the value.
81136
   * E.g., you must still call "is_null()" to check that a value is null even if
81137
   * "type()" returns json_type::null.
81138
   *
81139
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
81140
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
81141
   * let it throw an exception).
81142
   *
81143
   * @return The type of JSON value (json_type::array, json_type::object, json_type::string,
81144
   *     json_type::number, json_type::boolean, or json_type::null).
81145
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
81146
   */
81147
  simdjson_inline simdjson_result<json_type> type() noexcept;
81148
81149
  /**
81150
   * Checks whether the value is a scalar (string, number, null, Boolean).
81151
   * Returns false when there it is an array or object.
81152
   *
81153
   * @returns true if the type is string, number, null, Boolean
81154
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
81155
   */
81156
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
81157
  /**
81158
   * Checks whether the value is a string.
81159
   *
81160
   * @returns true if the type is string
81161
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
81162
   */
81163
  simdjson_inline simdjson_result<bool> is_string() noexcept;
81164
81165
  /**
81166
   * Checks whether the value is a negative number.
81167
   *
81168
   * @returns true if the number if negative.
81169
   */
81170
  simdjson_inline bool is_negative() noexcept;
81171
  /**
81172
   * Checks whether the value is an integer number. Note that
81173
   * this requires to partially parse the number string. If
81174
   * the value is determined to be an integer, it may still
81175
   * not parse properly as an integer in subsequent steps
81176
   * (e.g., it might overflow).
81177
   *
81178
   * Performance note: if you call this function systematically
81179
   * before parsing a number, you may have fallen for a performance
81180
   * anti-pattern.
81181
   *
81182
   * @returns true if the number if negative.
81183
   */
81184
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
81185
  /**
81186
   * Determine the number type (integer or floating-point number) as quickly
81187
   * as possible. This function does not fully validate the input. It is
81188
   * useful when you only need to classify the numbers, without parsing them.
81189
   *
81190
   * If you are planning to retrieve the value or you need full validation,
81191
   * consider using the get_number() method instead: it will fully parse
81192
   * and validate the input, and give you access to the type:
81193
   * get_number().get_number_type().
81194
   *
81195
   * get_number_type() is number_type::unsigned_integer if we have
81196
   * an integer greater or equal to 9223372036854775808.
81197
   * get_number_type() is number_type::signed_integer if we have an
81198
   * integer that is less than 9223372036854775808.
81199
   * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits,
81200
   * in which case the digit_count is set to the length of the big integer string.
81201
   * Otherwise, get_number_type() has value number_type::floating_point_number.
81202
   *
81203
   * This function requires processing the number string, but it is expected
81204
   * to be faster than get_number().get_number_type() because it is does not
81205
   * parse the number value.
81206
   *
81207
   * @returns the type of the number
81208
   */
81209
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
81210
81211
  /**
81212
   * Attempt to parse an ondemand::number. An ondemand::number may
81213
   * contain an integer value or a floating-point value, the simdjson
81214
   * library will autodetect the type. Thus it is a dynamically typed
81215
   * number. Before accessing the value, you must determine the detected
81216
   * type.
81217
   *
81218
   * number.get_number_type() is number_type::signed_integer if we have
81219
   * an integer in [-9223372036854775808,9223372036854775808)
81220
   * You can recover the value by calling number.get_int64() and you
81221
   * have that number.is_int64() is true.
81222
   *
81223
   * number.get_number_type() is number_type::unsigned_integer if we have
81224
   * an integer in [9223372036854775808,18446744073709551616)
81225
   * You can recover the value by calling number.get_uint64() and you
81226
   * have that number.is_uint64() is true.
81227
   *
81228
   * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code.
81229
   *
81230
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
81231
   * and we have a binary64 number.
81232
   * You can recover the value by calling number.get_double() and you
81233
   * have that number.is_double() is true.
81234
   *
81235
   * You must check the type before accessing the value: it is an error
81236
   * to call "get_int64()" when number.get_number_type() is not
81237
   * number_type::signed_integer and when number.is_int64() is false.
81238
   *
81239
   * Performance note: this is designed with performance in mind. When
81240
   * calling 'get_number()', you scan the number string only once, determining
81241
   * efficiently the type and storing it in an efficient manner.
81242
   */
81243
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
81244
81245
  /**
81246
   * Get the raw JSON for this token.
81247
   *
81248
   * The string_view will always point into the input buffer.
81249
   *
81250
   * The string_view will start at the beginning of the token, and include the entire token
81251
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
81252
   * string token always begins with a " and is always terminated by the final ", possibly
81253
   * followed by a number of spaces.
81254
   *
81255
   * The string_view is *not* null-terminated. However, if this is a scalar (string, number,
81256
   * boolean, or null), the character after the end of the string_view is guaranteed to be
81257
   * a non-space token.
81258
   *
81259
   * Tokens include:
81260
   * - {
81261
   * - [
81262
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
81263
   * - -1.2e-100
81264
   * - true
81265
   * - false
81266
   * - null
81267
   *
81268
   * See also value::raw_json().
81269
   */
81270
  simdjson_inline std::string_view raw_json_token() noexcept;
81271
81272
  /**
81273
   * Get a string_view pointing at this value in the JSON document.
81274
   * If this element is an array or an object, it consumes the array or the object
81275
   * and returns a string_view instance corresponding to the
81276
   * array as represented in JSON. It points inside the original document.
81277
   * If this element is a scalar (string, number, Boolean, null), it returns what
81278
   * raw_json_token() would return.
81279
   */
81280
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
81281
81282
  /**
81283
   * Returns the current location in the document if in bounds.
81284
   */
81285
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
81286
81287
  /**
81288
   * Returns the current depth in the document if in bounds.
81289
   *
81290
   * E.g.,
81291
   *  0 = finished with document
81292
   *  1 = document root value (could be [ or {, not yet known)
81293
   *  2 = , or } inside root array/object
81294
   *  3 = key or value inside root array/object.
81295
   */
81296
  simdjson_inline int32_t current_depth() const noexcept;
81297
81298
  /**
81299
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
81300
   * https://tools.ietf.org/html/rfc6901 standard.
81301
   *
81302
   *   ondemand::parser parser;
81303
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
81304
   *   auto doc = parser.iterate(json);
81305
   *   doc.at_pointer("/foo/a/1") == 20
81306
   *
81307
   * It is allowed for a key to be the empty string:
81308
   *
81309
   *   ondemand::parser parser;
81310
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
81311
   *   auto doc = parser.iterate(json);
81312
   *   doc.at_pointer("//a/1") == 20
81313
   *
81314
   * Note that at_pointer() called on the document automatically calls the document's rewind
81315
   * method between each call. It invalidates all previously accessed arrays, objects and values
81316
   * that have not been consumed.
81317
   *
81318
   * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not
81319
   * standardized (by RFC 6901). We provide some experimental support for JSON pointers
81320
   * on non-document instances.  Yet it is not the case when calling at_pointer on an array
81321
   * or an object instance: there is no rewind and no invalidation.
81322
   *
81323
   * You may only call at_pointer on an array after it has been created, but before it has
81324
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
81325
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
81326
   * to call at_pointer on the same array.
81327
   *
81328
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
81329
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
81330
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
81331
   *
81332
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
81333
   *
81334
   * @return The value associated with the given JSON pointer, or:
81335
   *         - NO_SUCH_FIELD if a field does not exist in an object
81336
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
81337
   *         - INCORRECT_TYPE if a non-integer is used to access an array
81338
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
81339
   */
81340
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
81341
81342
  /**
81343
   * Get the value associated with the given JSONPath expression. We only support
81344
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
81345
   * names and array indices.
81346
   *
81347
   * @return The value associated with the given JSONPath expression, or:
81348
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
81349
   *         - NO_SUCH_FIELD if a field does not exist in an object
81350
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
81351
   *         - INCORRECT_TYPE if a non-integer is used to access an array
81352
   */
81353
  simdjson_inline simdjson_result<value> at_path(std::string_view at_path) noexcept;
81354
81355
81356
protected:
81357
  /**
81358
   * Create a value.
81359
   */
81360
  simdjson_inline value(const value_iterator &iter) noexcept;
81361
81362
  /**
81363
   * Skip this value, allowing iteration to continue.
81364
   */
81365
  simdjson_inline void skip() noexcept;
81366
81367
  /**
81368
   * Start a value at the current position.
81369
   *
81370
   * (It should already be started; this is just a self-documentation method.)
81371
   */
81372
  static simdjson_inline value start(const value_iterator &iter) noexcept;
81373
81374
  /**
81375
   * Resume a value.
81376
   */
81377
  static simdjson_inline value resume(const value_iterator &iter) noexcept;
81378
81379
  /**
81380
   * Get the object, starting or resuming it as necessary
81381
   */
81382
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
81383
81384
  // simdjson_inline void log_value(const char *type) const noexcept;
81385
  // simdjson_inline void log_error(const char *message) const noexcept;
81386
81387
  value_iterator iter{};
81388
81389
  friend class document;
81390
  friend class array_iterator;
81391
  friend class field;
81392
  friend class object;
81393
  friend struct simdjson_result<value>;
81394
  friend struct simdjson_result<field>;
81395
  friend class field;
81396
};
81397
81398
} // namespace ondemand
81399
} // namespace westmere
81400
} // namespace simdjson
81401
81402
namespace simdjson {
81403
81404
template<>
81405
struct simdjson_result<westmere::ondemand::value> : public westmere::implementation_simdjson_result_base<westmere::ondemand::value> {
81406
public:
81407
  simdjson_inline simdjson_result(westmere::ondemand::value &&value) noexcept; ///< @private
81408
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
81409
  simdjson_inline simdjson_result() noexcept = default;
81410
81411
  simdjson_inline simdjson_result<westmere::ondemand::array> get_array() noexcept;
81412
  simdjson_inline simdjson_result<westmere::ondemand::object> get_object() noexcept;
81413
81414
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
81415
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
81416
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
81417
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
81418
  simdjson_inline simdjson_result<double> get_double() noexcept;
81419
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
81420
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
81421
  template <typename string_type>
81422
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
81423
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
81424
  simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> get_raw_json_string() noexcept;
81425
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
81426
  simdjson_inline simdjson_result<bool> is_null() noexcept;
81427
81428
  template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
81429
81430
  template<typename T> simdjson_inline error_code get(T &out) noexcept;
81431
81432
#if SIMDJSON_EXCEPTIONS
81433
  template <class T>
81434
  explicit simdjson_inline operator T() noexcept(false);
81435
  simdjson_inline operator westmere::ondemand::array() noexcept(false);
81436
  simdjson_inline operator westmere::ondemand::object() noexcept(false);
81437
  simdjson_inline operator uint64_t() noexcept(false);
81438
  simdjson_inline operator int64_t() noexcept(false);
81439
  simdjson_inline operator double() noexcept(false);
81440
  simdjson_inline operator std::string_view() noexcept(false);
81441
  simdjson_inline operator westmere::ondemand::raw_json_string() noexcept(false);
81442
  simdjson_inline operator bool() noexcept(false);
81443
#endif
81444
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
81445
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
81446
  simdjson_inline simdjson_result<westmere::ondemand::value> at(size_t index) noexcept;
81447
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> begin() & noexcept;
81448
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> end() & noexcept;
81449
81450
  /**
81451
   * Look up a field by name on an object (order-sensitive).
81452
   *
81453
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
81454
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
81455
   *
81456
   * ```c++
81457
   * simdjson::ondemand::parser parser;
81458
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
81459
   * double z = obj.find_field("z");
81460
   * double y = obj.find_field("y");
81461
   * double x = obj.find_field("x");
81462
   * ```
81463
   *
81464
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
81465
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
81466
   *
81467
   * @param key The key to look up.
81468
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
81469
   */
81470
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(std::string_view key) noexcept;
81471
  /** @overload simdjson_inline simdjson_result<westmere::ondemand::value> find_field(std::string_view key) noexcept; */
81472
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(const char *key) noexcept;
81473
81474
  /**
81475
   * Look up a field by name on an object, without regard to key order.
81476
   *
81477
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
81478
   * and often appears negligible. It starts out normally, starting out at the last field; but if
81479
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
81480
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
81481
   * in question is large. The fact that the extra code is there also bumps the executable size.
81482
   *
81483
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
81484
   * default behavior failed to look up a field just because it was in the wrong order--and many
81485
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
81486
   *
81487
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
81488
   * field as not there when they are not in order).
81489
   *
81490
   * @param key The key to look up.
81491
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
81492
   */
81493
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) noexcept;
81494
  /** @overload simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
81495
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(const char *key) noexcept;
81496
  /** @overload simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
81497
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](std::string_view key) noexcept;
81498
  /** @overload simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
81499
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](const char *key) noexcept;
81500
81501
  /**
81502
   * Get the type of this JSON value.
81503
   *
81504
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
81505
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
81506
   * let it throw an exception).
81507
   */
81508
  simdjson_inline simdjson_result<westmere::ondemand::json_type> type() noexcept;
81509
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
81510
  simdjson_inline simdjson_result<bool> is_string() noexcept;
81511
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
81512
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
81513
  simdjson_inline simdjson_result<westmere::number_type> get_number_type() noexcept;
81514
  simdjson_inline simdjson_result<westmere::ondemand::number> get_number() noexcept;
81515
81516
  /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
81517
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
81518
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
81519
81520
  /** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
81521
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
81522
  /** @copydoc simdjson_inline int32_t current_depth() const noexcept */
81523
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
81524
  simdjson_inline simdjson_result<westmere::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
81525
  simdjson_inline simdjson_result<westmere::ondemand::value> at_path(std::string_view json_path) noexcept;
81526
};
81527
81528
} // namespace simdjson
81529
81530
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H
81531
/* end file simdjson/generic/ondemand/value.h for westmere */
81532
/* including simdjson/generic/ondemand/logger.h for westmere: #include "simdjson/generic/ondemand/logger.h" */
81533
/* begin file simdjson/generic/ondemand/logger.h for westmere */
81534
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
81535
81536
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
81537
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_H */
81538
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
81539
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
81540
81541
namespace simdjson {
81542
namespace westmere {
81543
namespace ondemand {
81544
81545
// Logging should be free unless SIMDJSON_VERBOSE_LOGGING is set. Importantly, it is critical
81546
// that the call to the log functions be side-effect free. Thus, for example, you should not
81547
// create temporary std::string instances.
81548
namespace logger {
81549
81550
enum class log_level : int32_t {
81551
  info = 0,
81552
  error = 1
81553
};
81554
81555
#if SIMDJSON_VERBOSE_LOGGING
81556
  static constexpr const bool LOG_ENABLED = true;
81557
#else
81558
  static constexpr const bool LOG_ENABLED = false;
81559
#endif
81560
81561
// We do not want these functions to be 'really inlined' since real inlining is
81562
// for performance purposes and if you are using the loggers, you do not care about
81563
// performance (or should not).
81564
static inline void log_headers() noexcept;
81565
// If args are provided, title will be treated as format string
81566
template <typename... Args>
81567
static inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
81568
template <typename... Args>
81569
static inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
81570
static inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
81571
static inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
81572
static inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
81573
static inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
81574
static inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
81575
static inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
81576
81577
static inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail="") noexcept;
81578
static inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
81579
81580
static inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
81581
static inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
81582
static inline void log_start_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
81583
static inline void log_end_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
81584
static inline void log_error(const value_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
81585
81586
} // namespace logger
81587
} // namespace ondemand
81588
} // namespace westmere
81589
} // namespace simdjson
81590
81591
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
81592
/* end file simdjson/generic/ondemand/logger.h for westmere */
81593
/* including simdjson/generic/ondemand/token_iterator.h for westmere: #include "simdjson/generic/ondemand/token_iterator.h" */
81594
/* begin file simdjson/generic/ondemand/token_iterator.h for westmere */
81595
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
81596
81597
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
81598
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H */
81599
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
81600
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
81601
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
81602
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
81603
81604
namespace simdjson {
81605
namespace westmere {
81606
namespace ondemand {
81607
81608
/**
81609
 * Iterates through JSON tokens (`{` `}` `[` `]` `,` `:` `"<string>"` `123` `true` `false` `null`)
81610
 * detected by stage 1.
81611
 *
81612
 * @private This is not intended for external use.
81613
 */
81614
class token_iterator {
81615
public:
81616
  /**
81617
   * Create a new invalid token_iterator.
81618
   *
81619
   * Exists so you can declare a variable and later assign to it before use.
81620
   */
81621
  simdjson_inline token_iterator() noexcept = default;
81622
  simdjson_inline token_iterator(token_iterator &&other) noexcept = default;
81623
  simdjson_inline token_iterator &operator=(token_iterator &&other) noexcept = default;
81624
  simdjson_inline token_iterator(const token_iterator &other) noexcept = default;
81625
  simdjson_inline token_iterator &operator=(const token_iterator &other) noexcept = default;
81626
81627
  /**
81628
   * Advance to the next token (returning the current one).
81629
   */
81630
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
81631
  /**
81632
   * Reports the current offset in bytes from the start of the underlying buffer.
81633
   */
81634
  simdjson_inline uint32_t current_offset() const noexcept;
81635
  /**
81636
   * Get the JSON text for a given token (relative).
81637
   *
81638
   * This is not null-terminated; it is a view into the JSON.
81639
   *
81640
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
81641
   *              1 = next token, -1 = prev token.
81642
   *
81643
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
81644
   * it is not used...
81645
   */
81646
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
81647
  /**
81648
   * Get the maximum length of the JSON text for a given token.
81649
   *
81650
   * The length will include any whitespace at the end of the token.
81651
   *
81652
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
81653
   *              1 = next token, -1 = prev token.
81654
   */
81655
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
81656
81657
  /**
81658
   * Get the JSON text for a given token.
81659
   *
81660
   * This is not null-terminated; it is a view into the JSON.
81661
   *
81662
   * @param position The position of the token.
81663
   *
81664
   */
81665
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
81666
  /**
81667
   * Get the maximum length of the JSON text for a given token.
81668
   *
81669
   * The length will include any whitespace at the end of the token.
81670
   *
81671
   * @param position The position of the token.
81672
   */
81673
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
81674
  /**
81675
   * Get the maximum length of the JSON text for a root token.
81676
   *
81677
   * The length will include any whitespace at the end of the token.
81678
   *
81679
   * @param position The position of the token (start of the document).
81680
   */
81681
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
81682
  /**
81683
   * Return the current index.
81684
   */
81685
  simdjson_inline token_position position() const noexcept;
81686
  /**
81687
   * Reset to a previously saved index.
81688
   */
81689
  simdjson_inline void set_position(token_position target_position) noexcept;
81690
81691
  // NOTE: we don't support a full C++ iterator interface, because we expect people to make
81692
  // different calls to advance the iterator based on *their own* state.
81693
81694
  simdjson_inline bool operator==(const token_iterator &other) const noexcept;
81695
  simdjson_inline bool operator!=(const token_iterator &other) const noexcept;
81696
  simdjson_inline bool operator>(const token_iterator &other) const noexcept;
81697
  simdjson_inline bool operator>=(const token_iterator &other) const noexcept;
81698
  simdjson_inline bool operator<(const token_iterator &other) const noexcept;
81699
  simdjson_inline bool operator<=(const token_iterator &other) const noexcept;
81700
81701
protected:
81702
  simdjson_inline token_iterator(const uint8_t *buf, token_position position) noexcept;
81703
81704
  /**
81705
   * Get the index of the JSON text for a given token (relative).
81706
   *
81707
   * This is not null-terminated; it is a view into the JSON.
81708
   *
81709
   * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
81710
   *              1 = next token, -1 = prev token.
81711
   */
81712
  simdjson_inline uint32_t peek_index(int32_t delta=0) const noexcept;
81713
  /**
81714
   * Get the index of the JSON text for a given token.
81715
   *
81716
   * This is not null-terminated; it is a view into the JSON.
81717
   *
81718
   * @param position The position of the token.
81719
   *
81720
   */
81721
  simdjson_inline uint32_t peek_index(token_position position) const noexcept;
81722
81723
  const uint8_t *buf{};
81724
  token_position _position{};
81725
81726
  friend class json_iterator;
81727
  friend class value_iterator;
81728
  friend class object;
81729
  template <typename... Args>
81730
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
81731
  template <typename... Args>
81732
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
81733
};
81734
81735
} // namespace ondemand
81736
} // namespace westmere
81737
} // namespace simdjson
81738
81739
namespace simdjson {
81740
81741
template<>
81742
struct simdjson_result<westmere::ondemand::token_iterator> : public westmere::implementation_simdjson_result_base<westmere::ondemand::token_iterator> {
81743
public:
81744
  simdjson_inline simdjson_result(westmere::ondemand::token_iterator &&value) noexcept; ///< @private
81745
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
81746
  simdjson_inline simdjson_result() noexcept = default;
81747
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
81748
};
81749
81750
} // namespace simdjson
81751
81752
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
81753
/* end file simdjson/generic/ondemand/token_iterator.h for westmere */
81754
/* including simdjson/generic/ondemand/json_iterator.h for westmere: #include "simdjson/generic/ondemand/json_iterator.h" */
81755
/* begin file simdjson/generic/ondemand/json_iterator.h for westmere */
81756
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
81757
81758
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
81759
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H */
81760
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
81761
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
81762
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
81763
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
81764
81765
namespace simdjson {
81766
namespace westmere {
81767
namespace ondemand {
81768
81769
/**
81770
 * Iterates through JSON tokens, keeping track of depth and string buffer.
81771
 *
81772
 * @private This is not intended for external use.
81773
 */
81774
class json_iterator {
81775
protected:
81776
  token_iterator token{};
81777
  ondemand::parser *parser{};
81778
  /**
81779
   * Next free location in the string buffer.
81780
   *
81781
   * Used by raw_json_string::unescape() to have a place to unescape strings to.
81782
   */
81783
  uint8_t *_string_buf_loc{};
81784
  /**
81785
   * JSON error, if there is one.
81786
   *
81787
   * INCORRECT_TYPE and NO_SUCH_FIELD are *not* stored here, ever.
81788
   *
81789
   * PERF NOTE: we *hope* this will be elided into control flow, as it is only used (a) in the first
81790
   * iteration of the loop, or (b) for the final iteration after a missing comma is found in ++. If
81791
   * this is not elided, we should make sure it's at least not using up a register. Failing that,
81792
   * we should store it in document so there's only one of them.
81793
   */
81794
  error_code error{SUCCESS};
81795
  /**
81796
   * Depth of the current token in the JSON.
81797
   *
81798
   * - 0 = finished with document
81799
   * - 1 = document root value (could be [ or {, not yet known)
81800
   * - 2 = , or } inside root array/object
81801
   * - 3 = key or value inside root array/object.
81802
   */
81803
  depth_t _depth{};
81804
  /**
81805
   * Beginning of the document indexes.
81806
   * Normally we have root == parser->implementation->structural_indexes.get()
81807
   * but this may differ, especially in streaming mode (where we have several
81808
   * documents);
81809
   */
81810
  token_position _root{};
81811
  /**
81812
   * Normally, a json_iterator operates over a single document, but in
81813
   * some cases, we may have a stream of documents. This attribute is meant
81814
   * as meta-data: the json_iterator works the same irrespective of the
81815
   * value of this attribute.
81816
   */
81817
  bool _streaming{false};
81818
81819
public:
81820
  simdjson_inline json_iterator() noexcept = default;
81821
  simdjson_inline json_iterator(json_iterator &&other) noexcept;
81822
  simdjson_inline json_iterator &operator=(json_iterator &&other) noexcept;
81823
  simdjson_inline explicit json_iterator(const json_iterator &other) noexcept = default;
81824
  simdjson_inline json_iterator &operator=(const json_iterator &other) noexcept = default;
81825
  /**
81826
   * Skips a JSON value, whether it is a scalar, array or object.
81827
   */
81828
  simdjson_warn_unused simdjson_inline error_code skip_child(depth_t parent_depth) noexcept;
81829
81830
  /**
81831
   * Tell whether the iterator is still at the start
81832
   */
81833
  simdjson_inline bool at_root() const noexcept;
81834
81835
  /**
81836
   * Tell whether we should be expected to run in streaming
81837
   * mode (iterating over many documents). It is pure metadata
81838
   * that does not affect how the iterator works. It is used by
81839
   * start_root_array() and start_root_object().
81840
   */
81841
  simdjson_inline bool streaming() const noexcept;
81842
81843
  /**
81844
   * Get the root value iterator
81845
   */
81846
  simdjson_inline token_position root_position() const noexcept;
81847
  /**
81848
   * Assert that we are at the document depth (== 1)
81849
   */
81850
  simdjson_inline void assert_at_document_depth() const noexcept;
81851
  /**
81852
   * Assert that we are at the root of the document
81853
   */
81854
  simdjson_inline void assert_at_root() const noexcept;
81855
81856
  /**
81857
   * Tell whether the iterator is at the EOF mark
81858
   */
81859
  simdjson_inline bool at_end() const noexcept;
81860
81861
  /**
81862
   * Tell whether the iterator is live (has not been moved).
81863
   */
81864
  simdjson_inline bool is_alive() const noexcept;
81865
81866
  /**
81867
   * Abandon this iterator, setting depth to 0 (as if the document is finished).
81868
   */
81869
  simdjson_inline void abandon() noexcept;
81870
81871
  /**
81872
   * Advance the current token without modifying depth.
81873
   */
81874
  simdjson_inline const uint8_t *return_current_and_advance() noexcept;
81875
81876
  /**
81877
   * Returns true if there is a single token in the index (i.e., it is
81878
   * a JSON with a scalar value such as a single number).
81879
   *
81880
   * @return whether there is a single token
81881
   */
81882
  simdjson_inline bool is_single_token() const noexcept;
81883
81884
  /**
81885
   * Assert that there are at least the given number of tokens left.
81886
   *
81887
   * Has no effect in release builds.
81888
   */
81889
  simdjson_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
81890
  /**
81891
   * Assert that the given position addresses an actual token (is within bounds).
81892
   *
81893
   * Has no effect in release builds.
81894
   */
81895
  simdjson_inline void assert_valid_position(token_position position) const noexcept;
81896
  /**
81897
   * Get the JSON text for a given token (relative).
81898
   *
81899
   * This is not null-terminated; it is a view into the JSON.
81900
   *
81901
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
81902
   *
81903
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
81904
   * it is not used ...
81905
   */
81906
  simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
81907
  /**
81908
   * Get the maximum length of the JSON text for the current token (or relative).
81909
   *
81910
   * The length will include any whitespace at the end of the token.
81911
   *
81912
   * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
81913
   */
81914
  simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
81915
  /**
81916
   * Get a pointer to the current location in the input buffer.
81917
   *
81918
   * This is not null-terminated; it is a view into the JSON.
81919
   *
81920
   * You may be pointing outside of the input buffer: it is not generally
81921
   * safe to dereference this pointer.
81922
   */
81923
  simdjson_inline const uint8_t *unsafe_pointer() const noexcept;
81924
  /**
81925
   * Get the JSON text for a given token.
81926
   *
81927
   * This is not null-terminated; it is a view into the JSON.
81928
   *
81929
   * @param position The position of the token to retrieve.
81930
   *
81931
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
81932
   * it is not used ...
81933
   */
81934
  simdjson_inline const uint8_t *peek(token_position position) const noexcept;
81935
  /**
81936
   * Get the maximum length of the JSON text for the current token (or relative).
81937
   *
81938
   * The length will include any whitespace at the end of the token.
81939
   *
81940
   * @param position The position of the token to retrieve.
81941
   */
81942
  simdjson_inline uint32_t peek_length(token_position position) const noexcept;
81943
  /**
81944
   * Get the maximum length of the JSON text for the current root token.
81945
   *
81946
   * The length will include any whitespace at the end of the token.
81947
   *
81948
   * @param position The position of the token to retrieve.
81949
   */
81950
  simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
81951
  /**
81952
   * Get the JSON text for the last token in the document.
81953
   *
81954
   * This is not null-terminated; it is a view into the JSON.
81955
   *
81956
   * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
81957
   * it is not used ...
81958
   */
81959
  simdjson_inline const uint8_t *peek_last() const noexcept;
81960
81961
  /**
81962
   * Ascend one level.
81963
   *
81964
   * Validates that the depth - 1 == parent_depth.
81965
   *
81966
   * @param parent_depth the expected parent depth.
81967
   */
81968
  simdjson_inline void ascend_to(depth_t parent_depth) noexcept;
81969
81970
  /**
81971
   * Descend one level.
81972
   *
81973
   * Validates that the new depth == child_depth.
81974
   *
81975
   * @param child_depth the expected child depth.
81976
   */
81977
  simdjson_inline void descend_to(depth_t child_depth) noexcept;
81978
  simdjson_inline void descend_to(depth_t child_depth, int32_t delta) noexcept;
81979
81980
  /**
81981
   * Get current depth.
81982
   */
81983
  simdjson_inline depth_t depth() const noexcept;
81984
81985
  /**
81986
   * Get current (writeable) location in the string buffer.
81987
   */
81988
  simdjson_inline uint8_t *&string_buf_loc() noexcept;
81989
81990
  /**
81991
   * Report an unrecoverable error, preventing further iteration.
81992
   *
81993
   * @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
81994
   * @param message An error message to report with the error.
81995
   */
81996
  simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
81997
81998
  /**
81999
   * Log error, but don't stop iteration.
82000
   * @param error The error to report. Must be INCORRECT_TYPE, or NO_SUCH_FIELD.
82001
   * @param message An error message to report with the error.
82002
   */
82003
  simdjson_inline error_code optional_error(error_code error, const char *message) noexcept;
82004
82005
  /**
82006
   * Take an input in json containing max_len characters and attempt to copy it over to tmpbuf, a buffer with
82007
   * N bytes of capacity. It will return false if N is too small (smaller than max_len) of if it is zero.
82008
   * The buffer (tmpbuf) is padded with space characters.
82009
   */
82010
  simdjson_warn_unused simdjson_inline bool copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept;
82011
82012
  simdjson_inline token_position position() const noexcept;
82013
  /**
82014
   * Write the raw_json_string to the string buffer and return a string_view.
82015
   * Each raw_json_string should be unescaped once, or else the string buffer might
82016
   * overflow.
82017
   */
82018
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
82019
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
82020
82021
  simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
82022
82023
  simdjson_inline error_code consume_character(char c) noexcept;
82024
#if SIMDJSON_DEVELOPMENT_CHECKS
82025
  simdjson_inline token_position start_position(depth_t depth) const noexcept;
82026
  simdjson_inline void set_start_position(depth_t depth, token_position position) noexcept;
82027
#endif
82028
82029
  /* Useful for debugging and logging purposes. */
82030
  inline std::string to_string() const noexcept;
82031
82032
  /**
82033
   * Returns the current location in the document if in bounds.
82034
   */
82035
  inline simdjson_result<const char *> current_location() const noexcept;
82036
82037
  /**
82038
   * Updates this json iterator so that it is back at the beginning of the document,
82039
   * as if it had just been created.
82040
   */
82041
  inline void rewind() noexcept;
82042
  /**
82043
   * This checks whether the {,},[,] are balanced so that the document
82044
   * ends with proper zero depth. This requires scanning the whole document
82045
   * and it may be expensive. It is expected that it will be rarely called.
82046
   * It does not attempt to match { with } and [ with ].
82047
   */
82048
  inline bool balanced() const noexcept;
82049
protected:
82050
  simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
82051
  /// The last token before the end
82052
  simdjson_inline token_position last_position() const noexcept;
82053
  /// The token *at* the end. This points at gibberish and should only be used for comparison.
82054
  simdjson_inline token_position end_position() const noexcept;
82055
  /// The end of the buffer.
82056
  simdjson_inline token_position end() const noexcept;
82057
82058
  friend class document;
82059
  friend class document_stream;
82060
  friend class object;
82061
  friend class array;
82062
  friend class value;
82063
  friend class raw_json_string;
82064
  friend class parser;
82065
  friend class value_iterator;
82066
  friend class field;
82067
  template <typename... Args>
82068
  friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
82069
  template <typename... Args>
82070
  friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
82071
}; // json_iterator
82072
82073
} // namespace ondemand
82074
} // namespace westmere
82075
} // namespace simdjson
82076
82077
namespace simdjson {
82078
82079
template<>
82080
struct simdjson_result<westmere::ondemand::json_iterator> : public westmere::implementation_simdjson_result_base<westmere::ondemand::json_iterator> {
82081
public:
82082
  simdjson_inline simdjson_result(westmere::ondemand::json_iterator &&value) noexcept; ///< @private
82083
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
82084
82085
  simdjson_inline simdjson_result() noexcept = default;
82086
};
82087
82088
} // namespace simdjson
82089
82090
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
82091
/* end file simdjson/generic/ondemand/json_iterator.h for westmere */
82092
/* including simdjson/generic/ondemand/json_type.h for westmere: #include "simdjson/generic/ondemand/json_type.h" */
82093
/* begin file simdjson/generic/ondemand/json_type.h for westmere */
82094
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
82095
82096
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
82097
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H */
82098
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
82099
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
82100
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
82101
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
82102
82103
namespace simdjson {
82104
namespace westmere {
82105
namespace ondemand {
82106
82107
/**
82108
 * The type of a JSON value.
82109
 */
82110
enum class json_type {
82111
    // Start at 1 to catch uninitialized / default values more easily
82112
    array=1, ///< A JSON array   ( [ 1, 2, 3 ... ] )
82113
    object,  ///< A JSON object  ( { "a": 1, "b" 2, ... } )
82114
    number,  ///< A JSON number  ( 1 or -2.3 or 4.5e6 ...)
82115
    string,  ///< A JSON string  ( "a" or "hello world\n" ...)
82116
    boolean, ///< A JSON boolean (true or false)
82117
    null     ///< A JSON null    (null)
82118
};
82119
82120
/**
82121
 * A type representing a JSON number.
82122
 * The design of the struct is deliberately straight-forward. All
82123
 * functions return standard values with no error check.
82124
 */
82125
struct number {
82126
82127
  /**
82128
   * return the automatically determined type of
82129
   * the number: number_type::floating_point_number,
82130
   * number_type::signed_integer or number_type::unsigned_integer.
82131
   *
82132
   *    enum class number_type {
82133
   *        floating_point_number=1, /// a binary64 number
82134
   *        signed_integer,          /// a signed integer that fits in a 64-bit word using two's complement
82135
   *        unsigned_integer         /// a positive integer larger or equal to 1<<63
82136
   *    };
82137
   */
82138
  simdjson_inline ondemand::number_type get_number_type() const noexcept;
82139
  /**
82140
   * return true if the automatically determined type of
82141
   * the number is number_type::unsigned_integer.
82142
   */
82143
  simdjson_inline bool is_uint64() const noexcept;
82144
  /**
82145
   * return the value as a uint64_t, only valid if is_uint64() is true.
82146
   */
82147
  simdjson_inline uint64_t get_uint64() const noexcept;
82148
  simdjson_inline operator uint64_t() const noexcept;
82149
82150
  /**
82151
   * return true if the automatically determined type of
82152
   * the number is number_type::signed_integer.
82153
   */
82154
  simdjson_inline bool is_int64() const noexcept;
82155
  /**
82156
   * return the value as a int64_t, only valid if is_int64() is true.
82157
   */
82158
  simdjson_inline int64_t get_int64() const noexcept;
82159
  simdjson_inline operator int64_t() const noexcept;
82160
82161
82162
  /**
82163
   * return true if the automatically determined type of
82164
   * the number is number_type::floating_point_number.
82165
   */
82166
  simdjson_inline bool is_double() const noexcept;
82167
  /**
82168
   * return the value as a double, only valid if is_double() is true.
82169
   */
82170
  simdjson_inline double get_double() const noexcept;
82171
  simdjson_inline operator double() const noexcept;
82172
82173
  /**
82174
   * Convert the number to a double. Though it always succeed, the conversion
82175
   * may be lossy if the number cannot be represented exactly.
82176
   */
82177
  simdjson_inline double as_double() const noexcept;
82178
82179
82180
protected:
82181
  /**
82182
   * The next block of declaration is designed so that we can call the number parsing
82183
   * functions on a number type. They are protected and should never be used outside
82184
   * of the core simdjson library.
82185
   */
82186
  friend class value_iterator;
82187
  template<typename W>
82188
  friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
82189
  template<typename W>
82190
  friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
82191
  /** Store a signed 64-bit value to the number. */
82192
  simdjson_inline void append_s64(int64_t value) noexcept;
82193
  /** Store an unsigned 64-bit value to the number. */
82194
  simdjson_inline void append_u64(uint64_t value) noexcept;
82195
  /** Store a double value to the number. */
82196
  simdjson_inline void append_double(double value) noexcept;
82197
  /** Specifies that the value is a double, but leave it undefined. */
82198
  simdjson_inline void skip_double() noexcept;
82199
  /**
82200
   * End of friend declarations.
82201
   */
82202
82203
  /**
82204
   * Our attributes are a union type (size = 64 bits)
82205
   * followed by a type indicator.
82206
   */
82207
  union {
82208
    double floating_point_number;
82209
    int64_t signed_integer;
82210
    uint64_t unsigned_integer;
82211
  } payload{0};
82212
  number_type type{number_type::signed_integer};
82213
};
82214
82215
/**
82216
 * Write the JSON type to the output stream
82217
 *
82218
 * @param out The output stream.
82219
 * @param type The json_type.
82220
 */
82221
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
82222
82223
#if SIMDJSON_EXCEPTIONS
82224
/**
82225
 * Send JSON type to an output stream.
82226
 *
82227
 * @param out The output stream.
82228
 * @param type The json_type.
82229
 * @throw simdjson_error if the result being printed has an error. If there is an error with the
82230
 *        underlying output stream, that error will be propagated (simdjson_error will not be
82231
 *        thrown).
82232
 */
82233
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false);
82234
#endif
82235
82236
} // namespace ondemand
82237
} // namespace westmere
82238
} // namespace simdjson
82239
82240
namespace simdjson {
82241
82242
template<>
82243
struct simdjson_result<westmere::ondemand::json_type> : public westmere::implementation_simdjson_result_base<westmere::ondemand::json_type> {
82244
public:
82245
  simdjson_inline simdjson_result(westmere::ondemand::json_type &&value) noexcept; ///< @private
82246
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
82247
  simdjson_inline simdjson_result() noexcept = default;
82248
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
82249
};
82250
82251
} // namespace simdjson
82252
82253
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
82254
/* end file simdjson/generic/ondemand/json_type.h for westmere */
82255
/* including simdjson/generic/ondemand/raw_json_string.h for westmere: #include "simdjson/generic/ondemand/raw_json_string.h" */
82256
/* begin file simdjson/generic/ondemand/raw_json_string.h for westmere */
82257
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
82258
82259
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
82260
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H */
82261
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
82262
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
82263
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
82264
82265
namespace simdjson {
82266
namespace westmere {
82267
namespace ondemand {
82268
82269
/**
82270
 * A string escaped per JSON rules, terminated with quote ("). They are used to represent
82271
 * unescaped keys inside JSON documents.
82272
 *
82273
 * (In other words, a pointer to the beginning of a string, just after the start quote, inside a
82274
 * JSON file.)
82275
 *
82276
 * This class is deliberately simplistic and has little functionality. You can
82277
 * compare a raw_json_string instance with an unescaped C string, but
82278
 * that is nearly all you can do.
82279
 *
82280
 * The raw_json_string is unescaped. If you wish to write an unescaped version of it to your own
82281
 * buffer, you may do so using the parser.unescape(string, buff) method, using an ondemand::parser
82282
 * instance. Doing so requires you to have a sufficiently large buffer.
82283
 *
82284
 * The raw_json_string instances originate typically from field instance which in turn represent
82285
 * key-value pairs from object instances. From a field instance, you get the raw_json_string
82286
 * instance by calling key(). You can, if you want a more usable string_view instance, call
82287
 * the unescaped_key() method on the field instance. You may also create a raw_json_string from
82288
 * any other string value, with the value.get_raw_json_string() method. Again, you can get
82289
 * a more usable string_view instance by calling get_string().
82290
 *
82291
 */
82292
class raw_json_string {
82293
public:
82294
  /**
82295
   * Create a new invalid raw_json_string.
82296
   *
82297
   * Exists so you can declare a variable and later assign to it before use.
82298
   */
82299
  simdjson_inline raw_json_string() noexcept = default;
82300
82301
  /**
82302
   * Create a new invalid raw_json_string pointed at the given location in the JSON.
82303
   *
82304
   * The given location must be just *after* the beginning quote (") in the JSON file.
82305
   *
82306
   * It *must* be terminated by a ", and be a valid JSON string.
82307
   */
82308
  simdjson_inline raw_json_string(const uint8_t * _buf) noexcept;
82309
  /**
82310
   * Get the raw pointer to the beginning of the string in the JSON (just after the ").
82311
   *
82312
   * It is possible for this function to return a null pointer if the instance
82313
   * has outlived its existence.
82314
   */
82315
  simdjson_inline const char * raw() const noexcept;
82316
82317
  /**
82318
   * This compares the current instance to the std::string_view target: returns true if
82319
   * they are byte-by-byte equal (no escaping is done) on target.size() characters,
82320
   * and if the raw_json_string instance has a quote character at byte index target.size().
82321
   * We never read more than length + 1 bytes in the raw_json_string instance.
82322
   * If length is smaller than target.size(), this will return false.
82323
   *
82324
   * The std::string_view instance may contain any characters. However, the caller
82325
   * is responsible for setting length so that length bytes may be read in the
82326
   * raw_json_string.
82327
   *
82328
   * Performance: the comparison may be done using memcmp which may be efficient
82329
   * for long strings.
82330
   */
82331
  simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept;
82332
82333
  /**
82334
   * This compares the current instance to the std::string_view target: returns true if
82335
   * they are byte-by-byte equal (no escaping is done).
82336
   * The std::string_view instance should not contain unescaped quote characters:
82337
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
82338
   *
82339
   * Performance: the comparison is done byte-by-byte which might be inefficient for
82340
   * long strings.
82341
   *
82342
   * If target is a compile-time constant, and your compiler likes you,
82343
   * you should be able to do the following without performance penalty...
82344
   *
82345
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
82346
   *   s.unsafe_is_equal(target);
82347
   */
82348
  simdjson_inline bool unsafe_is_equal(std::string_view target) const noexcept;
82349
82350
  /**
82351
   * This compares the current instance to the C string target: returns true if
82352
   * they are byte-by-byte equal (no escaping is done).
82353
   * The provided C string should not contain an unescaped quote character:
82354
   * the caller is responsible for this check. See is_free_from_unescaped_quote.
82355
   *
82356
   * If target is a compile-time constant, and your compiler likes you,
82357
   * you should be able to do the following without performance penalty...
82358
   *
82359
   *   static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
82360
   *   s.unsafe_is_equal(target);
82361
   */
82362
  simdjson_inline bool unsafe_is_equal(const char* target) const noexcept;
82363
82364
  /**
82365
   * This compares the current instance to the std::string_view target: returns true if
82366
   * they are byte-by-byte equal (no escaping is done).
82367
   */
82368
  simdjson_inline bool is_equal(std::string_view target) const noexcept;
82369
82370
  /**
82371
   * This compares the current instance to the C string target: returns true if
82372
   * they are byte-by-byte equal (no escaping is done).
82373
   */
82374
  simdjson_inline bool is_equal(const char* target) const noexcept;
82375
82376
  /**
82377
   * Returns true if target is free from unescaped quote. If target is known at
82378
   * compile-time, we might expect the computation to happen at compile time with
82379
   * many compilers (not all!).
82380
   */
82381
  static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
82382
  static simdjson_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
82383
82384
private:
82385
82386
82387
  /**
82388
   * This will set the inner pointer to zero, effectively making
82389
   * this instance unusable.
82390
   */
82391
  simdjson_inline void consume() noexcept { buf = nullptr; }
82392
82393
  /**
82394
   * Checks whether the inner pointer is non-null and thus usable.
82395
   */
82396
  simdjson_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
82397
82398
  /**
82399
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
82400
   * The result will be a valid UTF-8.
82401
   *
82402
   * ## IMPORTANT: string_view lifetime
82403
   *
82404
   * The string_view is only valid until the next parse() call on the parser.
82405
   *
82406
   * @param iter A json_iterator, which contains a buffer where the string will be written.
82407
   * @param allow_replacement Whether we allow replacement of invalid surrogate pairs.
82408
   */
82409
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(json_iterator &iter, bool allow_replacement) const noexcept;
82410
82411
  /**
82412
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
82413
   * The result may not be a valid UTF-8. https://simonsapin.github.io/wtf-8/
82414
   *
82415
   * ## IMPORTANT: string_view lifetime
82416
   *
82417
   * The string_view is only valid until the next parse() call on the parser.
82418
   *
82419
   * @param iter A json_iterator, which contains a buffer where the string will be written.
82420
   */
82421
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(json_iterator &iter) const noexcept;
82422
  const uint8_t * buf{};
82423
  friend class object;
82424
  friend class field;
82425
  friend class parser;
82426
  friend struct simdjson_result<raw_json_string>;
82427
};
82428
82429
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &, const raw_json_string &) noexcept;
82430
82431
/**
82432
 * Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user is responsible
82433
 * for providing a string with no unescaped quote. Note that unescaped quotes cannot be present in valid JSON strings.
82434
 */
82435
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept;
82436
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept;
82437
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept;
82438
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept;
82439
82440
82441
} // namespace ondemand
82442
} // namespace westmere
82443
} // namespace simdjson
82444
82445
namespace simdjson {
82446
82447
template<>
82448
struct simdjson_result<westmere::ondemand::raw_json_string> : public westmere::implementation_simdjson_result_base<westmere::ondemand::raw_json_string> {
82449
public:
82450
  simdjson_inline simdjson_result(westmere::ondemand::raw_json_string &&value) noexcept; ///< @private
82451
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
82452
  simdjson_inline simdjson_result() noexcept = default;
82453
  simdjson_inline ~simdjson_result() noexcept = default; ///< @private
82454
82455
  simdjson_inline simdjson_result<const char *> raw() const noexcept;
82456
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(westmere::ondemand::json_iterator &iter, bool allow_replacement) const noexcept;
82457
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(westmere::ondemand::json_iterator &iter) const noexcept;
82458
};
82459
82460
} // namespace simdjson
82461
82462
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
82463
/* end file simdjson/generic/ondemand/raw_json_string.h for westmere */
82464
/* including simdjson/generic/ondemand/parser.h for westmere: #include "simdjson/generic/ondemand/parser.h" */
82465
/* begin file simdjson/generic/ondemand/parser.h for westmere */
82466
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_H
82467
82468
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
82469
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_H */
82470
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
82471
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
82472
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
82473
82474
#include <memory>
82475
82476
namespace simdjson {
82477
namespace westmere {
82478
namespace ondemand {
82479
82480
/**
82481
 * The default batch size for document_stream instances for this On Demand kernel.
82482
 * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value
82483
 * in the future.
82484
 */
82485
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
82486
/**
82487
 * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
82488
 * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
82489
 * most users will want a much larger batch size.
82490
 *
82491
 * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
82492
 * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
82493
 */
82494
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
82495
82496
/**
82497
 * A JSON fragment iterator.
82498
 *
82499
 * This holds the actual iterator as well as the buffer for writing strings.
82500
 */
82501
class parser {
82502
public:
82503
  /**
82504
   * Create a JSON parser.
82505
   *
82506
   * The new parser will have zero capacity.
82507
   */
82508
  inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
82509
82510
  inline parser(parser &&other) noexcept = default;
82511
  simdjson_inline parser(const parser &other) = delete;
82512
  simdjson_inline parser &operator=(const parser &other) = delete;
82513
  simdjson_inline parser &operator=(parser &&other) noexcept = default;
82514
82515
  /** Deallocate the JSON parser. */
82516
  inline ~parser() noexcept = default;
82517
82518
  /**
82519
   * Start iterating an on-demand JSON document.
82520
   *
82521
   *   ondemand::parser parser;
82522
   *   document doc = parser.iterate(json);
82523
   *
82524
   * It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
82525
   * Otherwise the iterate method may return an error. In particular, the whole input should be
82526
   * valid: we do not attempt to tolerate incorrect content either before or after a JSON
82527
   * document. If there is a UTF-8 BOM, the parser skips it.
82528
   *
82529
   * ### IMPORTANT: Validate what you use
82530
   *
82531
   * Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
82532
   * iterate does not parse and validate the whole document.
82533
   *
82534
   * ### IMPORTANT: Buffer Lifetime
82535
   *
82536
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
82537
   * long as the document iteration.
82538
   *
82539
   * ### IMPORTANT: Document Lifetime
82540
   *
82541
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
82542
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
82543
   * you call parse() again or destroy the parser.
82544
   *
82545
   * ### REQUIRED: Buffer Padding
82546
   *
82547
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
82548
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
82549
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
82550
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
82551
   *
82552
   * @param json The JSON to parse.
82553
   * @param len The length of the JSON.
82554
   * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
82555
   *
82556
   * @return The document, or an error:
82557
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
82558
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
82559
   *           allocation fails.
82560
   *         - EMPTY if the document is all whitespace.
82561
   *         - UTF8_ERROR if the document is not valid UTF-8.
82562
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
82563
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
82564
   */
82565
  simdjson_warn_unused simdjson_result<document> iterate(padded_string_view json) & noexcept;
82566
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82567
  simdjson_warn_unused simdjson_result<document> iterate(const char *json, size_t len, size_t capacity) & noexcept;
82568
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82569
  simdjson_warn_unused simdjson_result<document> iterate(const uint8_t *json, size_t len, size_t capacity) & noexcept;
82570
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82571
  simdjson_warn_unused simdjson_result<document> iterate(std::string_view json, size_t capacity) & noexcept;
82572
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82573
  simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
82574
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82575
  simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
82576
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82577
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
82578
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82579
  simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
82580
  /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
82581
  simdjson_warn_unused simdjson_result<document> iterate(padded_string &&json) & noexcept = delete;
82582
82583
  /**
82584
   * @private
82585
   *
82586
   * Start iterating an on-demand JSON document.
82587
   *
82588
   *   ondemand::parser parser;
82589
   *   json_iterator doc = parser.iterate(json);
82590
   *
82591
   * ### IMPORTANT: Buffer Lifetime
82592
   *
82593
   * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
82594
   * long as the document iteration.
82595
   *
82596
   * ### IMPORTANT: Document Lifetime
82597
   *
82598
   * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
82599
   * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
82600
   * you call parse() again or destroy the parser.
82601
   *
82602
   * The ondemand::document instance holds the iterator. The document must remain in scope
82603
   * while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
82604
   *
82605
   * ### REQUIRED: Buffer Padding
82606
   *
82607
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
82608
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
82609
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
82610
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
82611
   *
82612
   * @param json The JSON to parse.
82613
   *
82614
   * @return The iterator, or an error:
82615
   *         - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
82616
   *         - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
82617
   *           allocation fails.
82618
   *         - EMPTY if the document is all whitespace.
82619
   *         - UTF8_ERROR if the document is not valid UTF-8.
82620
   *         - UNESCAPED_CHARS if a string contains control characters that must be escaped
82621
   *         - UNCLOSED_STRING if there is an unclosed string in the document.
82622
   */
82623
  simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
82624
82625
82626
  /**
82627
   * Parse a buffer containing many JSON documents.
82628
   *
82629
   *   auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
82630
   *   ondemand::parser parser;
82631
   *   ondemand::document_stream docs = parser.iterate_many(json);
82632
   *   for (auto & doc : docs) {
82633
   *     std::cout << doc["foo"] << std::endl;
82634
   *   }
82635
   *   // Prints 1 2 3
82636
   *
82637
   * No copy of the input buffer is made.
82638
   *
82639
   * The function is lazy: it may be that no more than one JSON document at a time is parsed.
82640
   *
82641
   * The caller is responsabile to ensure that the input string data remains unchanged and is
82642
   * not deleted during the loop.
82643
   *
82644
   * ### Format
82645
   *
82646
   * The buffer must contain a series of one or more JSON documents, concatenated into a single
82647
   * buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
82648
   * then starts parsing the next document at that point. (It does this with more parallelism and
82649
   * lookahead than you might think, though.)
82650
   *
82651
   * documents that consist of an object or array may omit the whitespace between them, concatenating
82652
   * with no separator. Documents that consist of a single primitive (i.e. documents that are not
82653
   * arrays or objects) MUST be separated with ASCII whitespace.
82654
   *
82655
   * The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
82656
   * If there is a UTF-8 BOM, the parser skips it.
82657
   *
82658
   * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
82659
   * Setting batch_size to excessively large or excessively small values may impact negatively the
82660
   * performance.
82661
   *
82662
   * ### REQUIRED: Buffer Padding
82663
   *
82664
   * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
82665
   * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
82666
   * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
82667
   * SIMDJSON_PADDING bytes to avoid runtime warnings.
82668
   *
82669
   * ### Threads
82670
   *
82671
   * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
82672
   * hood to do some lookahead.
82673
   *
82674
   * ### Parser Capacity
82675
   *
82676
   * If the parser's current capacity is less than batch_size, it will allocate enough capacity
82677
   * to handle it (up to max_capacity).
82678
   *
82679
   * @param buf The concatenated JSON to parse.
82680
   * @param len The length of the concatenated JSON.
82681
   * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
82682
   *                   spot is cache-related: small enough to fit in cache, yet big enough to
82683
   *                   parse as many documents as possible in one tight loop.
82684
   *                   Defaults to 10MB, which has been a reasonable sweet spot in our tests.
82685
   * @param allow_comma_separated (defaults on false) This allows a mode where the documents are
82686
   *                   separated by commas instead of whitespace. It comes with a performance
82687
   *                   penalty because the entire document is indexed at once (and the document must be
82688
   *                   less than 4 GB), and there is no multithreading. In this mode, the batch_size parameter
82689
   *                   is effectively ignored, as it is set to at least the document size.
82690
   * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
82691
   *         - MEMALLOC if the parser does not have enough capacity and memory allocation fails
82692
   *         - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
82693
   *         - other json errors if parsing fails. You should not rely on these errors to always the same for the
82694
   *           same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
82695
   */
82696
  inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
82697
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
82698
  inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
82699
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
82700
  inline simdjson_result<document_stream> iterate_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
82701
  inline simdjson_result<document_stream> iterate_many(const std::string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
82702
  /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
82703
  inline simdjson_result<document_stream> iterate_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
82704
  inline simdjson_result<document_stream> iterate_many(const padded_string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
82705
82706
  /** @private We do not want to allow implicit conversion from C string to std::string. */
82707
  simdjson_result<document_stream> iterate_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
82708
82709
  /** The capacity of this parser (the largest document it can process). */
82710
  simdjson_inline size_t capacity() const noexcept;
82711
  /** The maximum capacity of this parser (the largest document it is allowed to process). */
82712
  simdjson_inline size_t max_capacity() const noexcept;
82713
  simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
82714
  /**
82715
   * The maximum depth of this parser (the most deeply nested objects and arrays it can process).
82716
   * This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
82717
   * The document's instance current_depth() method should be used to monitor the parsing
82718
   * depth and limit it if desired.
82719
   */
82720
  simdjson_inline size_t max_depth() const noexcept;
82721
82722
  /**
82723
   * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
82724
   * and `max_depth` depth.
82725
   *
82726
   * The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
82727
   * The document's instance current_depth() method should be used to monitor the parsing
82728
   * depth and limit it if desired.
82729
   *
82730
   * @param capacity The new capacity.
82731
   * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
82732
   * @return The error, if there is one.
82733
   */
82734
  simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
82735
82736
  #ifdef SIMDJSON_THREADS_ENABLED
82737
  /**
82738
   * The parser instance can use threads when they are available to speed up some
82739
   * operations. It is enabled by default. Changing this attribute will change the
82740
   * behavior of the parser for future operations.
82741
   */
82742
  bool threaded{true};
82743
  #endif
82744
82745
  /**
82746
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
82747
   * The result must be valid UTF-8.
82748
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
82749
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
82750
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
82751
   *
82752
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
82753
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
82754
   * instead of get_raw_json_string()).
82755
   *
82756
   * ## IMPORTANT: string_view lifetime
82757
   *
82758
   * The string_view is only valid as long as the bytes in dst.
82759
   *
82760
   * @param raw_json_string input
82761
   * @param dst A pointer to a buffer at least large enough to write this string as well as
82762
   *            an additional SIMDJSON_PADDING bytes.
82763
   * @param allow_replacement Whether we allow a replacement if the input string contains unmatched surrogate pairs.
82764
   * @return A string_view pointing at the unescaped string in dst
82765
   * @error STRING_ERROR if escapes are incorrect.
82766
   */
82767
  simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement = false) const noexcept;
82768
82769
  /**
82770
   * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
82771
   * The result may not be valid UTF-8. See https://simonsapin.github.io/wtf-8/
82772
   * The provided pointer is advanced to the end of the string by reference, and a string_view instance
82773
   * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
82774
   * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
82775
   *
82776
   * This unescape function is a low-level function. If you want a more user-friendly approach, you should
82777
   * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
82778
   * instead of get_raw_json_string()).
82779
   *
82780
   * ## IMPORTANT: string_view lifetime
82781
   *
82782
   * The string_view is only valid as long as the bytes in dst.
82783
   *
82784
   * @param raw_json_string input
82785
   * @param dst A pointer to a buffer at least large enough to write this string as well as
82786
   *            an additional SIMDJSON_PADDING bytes.
82787
   * @return A string_view pointing at the unescaped string in dst
82788
   * @error STRING_ERROR if escapes are incorrect.
82789
   */
82790
  simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept;
82791
82792
private:
82793
  /** @private [for benchmarking access] The implementation to use */
82794
  std::unique_ptr<internal::dom_parser_implementation> implementation{};
82795
  size_t _capacity{0};
82796
  size_t _max_capacity;
82797
  size_t _max_depth{DEFAULT_MAX_DEPTH};
82798
  std::unique_ptr<uint8_t[]> string_buf{};
82799
#if SIMDJSON_DEVELOPMENT_CHECKS
82800
  std::unique_ptr<token_position[]> start_positions{};
82801
#endif
82802
82803
  friend class json_iterator;
82804
  friend class document_stream;
82805
};
82806
82807
} // namespace ondemand
82808
} // namespace westmere
82809
} // namespace simdjson
82810
82811
namespace simdjson {
82812
82813
template<>
82814
struct simdjson_result<westmere::ondemand::parser> : public westmere::implementation_simdjson_result_base<westmere::ondemand::parser> {
82815
public:
82816
  simdjson_inline simdjson_result(westmere::ondemand::parser &&value) noexcept; ///< @private
82817
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
82818
  simdjson_inline simdjson_result() noexcept = default;
82819
};
82820
82821
} // namespace simdjson
82822
82823
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_H
82824
/* end file simdjson/generic/ondemand/parser.h for westmere */
82825
82826
// All other declarations
82827
/* including simdjson/generic/ondemand/array.h for westmere: #include "simdjson/generic/ondemand/array.h" */
82828
/* begin file simdjson/generic/ondemand/array.h for westmere */
82829
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
82830
82831
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
82832
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H */
82833
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
82834
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
82835
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
82836
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
82837
82838
namespace simdjson {
82839
namespace westmere {
82840
namespace ondemand {
82841
82842
/**
82843
 * A forward-only JSON array.
82844
 */
82845
class array {
82846
public:
82847
  /**
82848
   * Create a new invalid array.
82849
   *
82850
   * Exists so you can declare a variable and later assign to it before use.
82851
   */
82852
  simdjson_inline array() noexcept = default;
82853
82854
  /**
82855
   * Begin array iteration.
82856
   *
82857
   * Part of the std::iterable interface.
82858
   */
82859
  simdjson_inline simdjson_result<array_iterator> begin() noexcept;
82860
  /**
82861
   * Sentinel representing the end of the array.
82862
   *
82863
   * Part of the std::iterable interface.
82864
   */
82865
  simdjson_inline simdjson_result<array_iterator> end() noexcept;
82866
  /**
82867
   * This method scans the array and counts the number of elements.
82868
   * The count_elements method should always be called before you have begun
82869
   * iterating through the array: it is expected that you are pointing at
82870
   * the beginning of the array.
82871
   * The runtime complexity is linear in the size of the array. After
82872
   * calling this function, if successful, the array is 'rewinded' at its
82873
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
82874
   * there is a missing comma), then an error is returned and it is no longer
82875
   * safe to continue.
82876
   *
82877
   * To check that an array is empty, it is more performant to use
82878
   * the is_empty() method.
82879
   */
82880
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
82881
  /**
82882
   * This method scans the beginning of the array and checks whether the
82883
   * array is empty.
82884
   * The runtime complexity is constant time. After
82885
   * calling this function, if successful, the array is 'rewinded' at its
82886
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
82887
   * there is a missing comma), then an error is returned and it is no longer
82888
   * safe to continue.
82889
   */
82890
  simdjson_inline simdjson_result<bool> is_empty() & noexcept;
82891
  /**
82892
   * Reset the iterator so that we are pointing back at the
82893
   * beginning of the array. You should still consume values only once even if you
82894
   * can iterate through the array more than once. If you unescape a string
82895
   * within the array more than once, you have unsafe code. Note that rewinding
82896
   * an array means that you may need to reparse it anew: it is not a free
82897
   * operation.
82898
   *
82899
   * @returns true if the array contains some elements (not empty)
82900
   */
82901
  inline simdjson_result<bool> reset() & noexcept;
82902
  /**
82903
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
82904
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
82905
   * as the root of its own JSON document.
82906
   *
82907
   *   ondemand::parser parser;
82908
   *   auto json = R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded;
82909
   *   auto doc = parser.iterate(json);
82910
   *   doc.at_pointer("/0/foo/a/1") == 20
82911
   *
82912
   * Note that at_pointer() called on the document automatically calls the document's rewind
82913
   * method between each call. It invalidates all previously accessed arrays, objects and values
82914
   * that have not been consumed. Yet it is not the case when calling at_pointer on an array
82915
   * instance: there is no rewind and no invalidation.
82916
   *
82917
   * You may only call at_pointer on an array after it has been created, but before it has
82918
   * been first accessed. When calling at_pointer on an array, the pointer is advanced to
82919
   * the location indicated by the JSON pointer (in case of success). It is no longer possible
82920
   * to call at_pointer on the same array.
82921
   *
82922
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
82923
   *
82924
   * @return The value associated with the given JSON pointer, or:
82925
   *         - NO_SUCH_FIELD if a field does not exist in an object
82926
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
82927
   *         - INCORRECT_TYPE if a non-integer is used to access an array
82928
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
82929
   */
82930
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
82931
82932
  /**
82933
   * Get the value associated with the given JSONPath expression. We only support
82934
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
82935
   * names and array indices.
82936
   *
82937
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
82938
   *
82939
   * @return The value associated with the given JSONPath expression, or:
82940
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
82941
   *         - NO_SUCH_FIELD if a field does not exist in an object
82942
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
82943
   *         - INCORRECT_TYPE if a non-integer is used to access an array
82944
  */
82945
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
82946
82947
  /**
82948
   * Consumes the array and returns a string_view instance corresponding to the
82949
   * array as represented in JSON. It points inside the original document.
82950
   */
82951
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
82952
82953
  /**
82954
   * Get the value at the given index. This function has linear-time complexity.
82955
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
82956
   *
82957
   * @return The value at the given index, or:
82958
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
82959
   */
82960
  simdjson_inline simdjson_result<value> at(size_t index) noexcept;
82961
protected:
82962
  /**
82963
   * Go to the end of the array, no matter where you are right now.
82964
   */
82965
  simdjson_inline error_code consume() noexcept;
82966
82967
  /**
82968
   * Begin array iteration.
82969
   *
82970
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
82971
   *        resulting array.
82972
   * @error INCORRECT_TYPE if the iterator is not at [.
82973
   */
82974
  static simdjson_inline simdjson_result<array> start(value_iterator &iter) noexcept;
82975
  /**
82976
   * Begin array iteration from the root.
82977
   *
82978
   * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
82979
   *        resulting array.
82980
   * @error INCORRECT_TYPE if the iterator is not at [.
82981
   * @error TAPE_ERROR if there is no closing ] at the end of the document.
82982
   */
82983
  static simdjson_inline simdjson_result<array> start_root(value_iterator &iter) noexcept;
82984
  /**
82985
   * Begin array iteration.
82986
   *
82987
   * This version of the method should be called after the initial [ has been verified, and is
82988
   * intended for use by switch statements that check the type of a value.
82989
   *
82990
   * @param iter The iterator. Must be after the initial [. Will be *moved* into the resulting array.
82991
   */
82992
  static simdjson_inline simdjson_result<array> started(value_iterator &iter) noexcept;
82993
82994
  /**
82995
   * Create an array at the given Internal array creation. Call array::start() or array::started() instead of this.
82996
   *
82997
   * @param iter The iterator. Must either be at the start of the first element with iter.is_alive()
82998
   *        == true, or past the [] with is_alive() == false if the array is empty. Will be *moved*
82999
   *        into the resulting array.
83000
   */
83001
  simdjson_inline array(const value_iterator &iter) noexcept;
83002
83003
  /**
83004
   * Iterator marking current position.
83005
   *
83006
   * iter.is_alive() == false indicates iteration is complete.
83007
   */
83008
  value_iterator iter{};
83009
83010
  friend class value;
83011
  friend class document;
83012
  friend struct simdjson_result<value>;
83013
  friend struct simdjson_result<array>;
83014
  friend class array_iterator;
83015
};
83016
83017
} // namespace ondemand
83018
} // namespace westmere
83019
} // namespace simdjson
83020
83021
namespace simdjson {
83022
83023
template<>
83024
struct simdjson_result<westmere::ondemand::array> : public westmere::implementation_simdjson_result_base<westmere::ondemand::array> {
83025
public:
83026
  simdjson_inline simdjson_result(westmere::ondemand::array &&value) noexcept; ///< @private
83027
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
83028
  simdjson_inline simdjson_result() noexcept = default;
83029
83030
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> begin() noexcept;
83031
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> end() noexcept;
83032
  inline simdjson_result<size_t> count_elements() & noexcept;
83033
  inline simdjson_result<bool> is_empty() & noexcept;
83034
  inline simdjson_result<bool> reset() & noexcept;
83035
  simdjson_inline simdjson_result<westmere::ondemand::value> at(size_t index) noexcept;
83036
  simdjson_inline simdjson_result<westmere::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
83037
  simdjson_inline simdjson_result<westmere::ondemand::value> at_path(std::string_view json_path) noexcept;
83038
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
83039
83040
};
83041
83042
} // namespace simdjson
83043
83044
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
83045
/* end file simdjson/generic/ondemand/array.h for westmere */
83046
/* including simdjson/generic/ondemand/array_iterator.h for westmere: #include "simdjson/generic/ondemand/array_iterator.h" */
83047
/* begin file simdjson/generic/ondemand/array_iterator.h for westmere */
83048
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
83049
83050
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
83051
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H */
83052
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
83053
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
83054
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
83055
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
83056
83057
83058
namespace simdjson {
83059
namespace westmere {
83060
namespace ondemand {
83061
83062
/**
83063
 * A forward-only JSON array.
83064
 *
83065
 * This is an input_iterator, meaning:
83066
 * - It is forward-only
83067
 * - * must be called exactly once per element.
83068
 * - ++ must be called exactly once in between each * (*, ++, *, ++, * ...)
83069
 */
83070
class array_iterator {
83071
public:
83072
  /** Create a new, invalid array iterator. */
83073
  simdjson_inline array_iterator() noexcept = default;
83074
83075
  //
83076
  // Iterator interface
83077
  //
83078
83079
  /**
83080
   * Get the current element.
83081
   *
83082
   * Part of the std::iterator interface.
83083
   */
83084
  simdjson_inline simdjson_result<value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
83085
  /**
83086
   * Check if we are at the end of the JSON.
83087
   *
83088
   * Part of the std::iterator interface.
83089
   *
83090
   * @return true if there are no more elements in the JSON array.
83091
   */
83092
  simdjson_inline bool operator==(const array_iterator &) const noexcept;
83093
  /**
83094
   * Check if there are more elements in the JSON array.
83095
   *
83096
   * Part of the std::iterator interface.
83097
   *
83098
   * @return true if there are more elements in the JSON array.
83099
   */
83100
  simdjson_inline bool operator!=(const array_iterator &) const noexcept;
83101
  /**
83102
   * Move to the next element.
83103
   *
83104
   * Part of the std::iterator interface.
83105
   */
83106
  simdjson_inline array_iterator &operator++() noexcept;
83107
83108
private:
83109
  value_iterator iter{};
83110
83111
  simdjson_inline array_iterator(const value_iterator &iter) noexcept;
83112
83113
  friend class array;
83114
  friend class value;
83115
  friend struct simdjson_result<array_iterator>;
83116
};
83117
83118
} // namespace ondemand
83119
} // namespace westmere
83120
} // namespace simdjson
83121
83122
namespace simdjson {
83123
83124
template<>
83125
struct simdjson_result<westmere::ondemand::array_iterator> : public westmere::implementation_simdjson_result_base<westmere::ondemand::array_iterator> {
83126
public:
83127
  simdjson_inline simdjson_result(westmere::ondemand::array_iterator &&value) noexcept; ///< @private
83128
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
83129
  simdjson_inline simdjson_result() noexcept = default;
83130
83131
  //
83132
  // Iterator interface
83133
  //
83134
83135
  simdjson_inline simdjson_result<westmere::ondemand::value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
83136
  simdjson_inline bool operator==(const simdjson_result<westmere::ondemand::array_iterator> &) const noexcept;
83137
  simdjson_inline bool operator!=(const simdjson_result<westmere::ondemand::array_iterator> &) const noexcept;
83138
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> &operator++() noexcept;
83139
};
83140
83141
} // namespace simdjson
83142
83143
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
83144
/* end file simdjson/generic/ondemand/array_iterator.h for westmere */
83145
/* including simdjson/generic/ondemand/document.h for westmere: #include "simdjson/generic/ondemand/document.h" */
83146
/* begin file simdjson/generic/ondemand/document.h for westmere */
83147
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
83148
83149
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
83150
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */
83151
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
83152
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
83153
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
83154
83155
namespace simdjson {
83156
namespace westmere {
83157
namespace ondemand {
83158
83159
/**
83160
 * A JSON document. It holds a json_iterator instance.
83161
 *
83162
 * Used by tokens to get text, and string buffer location.
83163
 *
83164
 * You must keep the document around during iteration.
83165
 */
83166
class document {
83167
public:
83168
  /**
83169
   * Create a new invalid document.
83170
   *
83171
   * Exists so you can declare a variable and later assign to it before use.
83172
   */
83173
  simdjson_inline document() noexcept = default;
83174
  simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
83175
  simdjson_inline document(document &&other) noexcept = default;
83176
  simdjson_inline document &operator=(const document &other) noexcept = delete;
83177
  simdjson_inline document &operator=(document &&other) noexcept = default;
83178
83179
  /**
83180
   * Cast this JSON value to an array.
83181
   *
83182
   * @returns An object that can be used to iterate the array.
83183
   * @returns INCORRECT_TYPE If the JSON value is not an array.
83184
   */
83185
  simdjson_inline simdjson_result<array> get_array() & noexcept;
83186
  /**
83187
   * Cast this JSON value to an object.
83188
   *
83189
   * @returns An object that can be used to look up or iterate fields.
83190
   * @returns INCORRECT_TYPE If the JSON value is not an object.
83191
   */
83192
  simdjson_inline simdjson_result<object> get_object() & noexcept;
83193
  /**
83194
   * Cast this JSON value to an unsigned integer.
83195
   *
83196
   * @returns A signed 64-bit integer.
83197
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
83198
   */
83199
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
83200
  /**
83201
   * Cast this JSON value (inside string) to an unsigned integer.
83202
   *
83203
   * @returns A signed 64-bit integer.
83204
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
83205
   */
83206
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
83207
  /**
83208
   * Cast this JSON value to a signed integer.
83209
   *
83210
   * @returns A signed 64-bit integer.
83211
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
83212
   */
83213
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
83214
  /**
83215
   * Cast this JSON value (inside string) to a signed integer.
83216
   *
83217
   * @returns A signed 64-bit integer.
83218
   * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
83219
   */
83220
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
83221
  /**
83222
   * Cast this JSON value to a double.
83223
   *
83224
   * @returns A double.
83225
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
83226
   */
83227
  simdjson_inline simdjson_result<double> get_double() noexcept;
83228
83229
  /**
83230
   * Cast this JSON value (inside string) to a double.
83231
   *
83232
   * @returns A double.
83233
   * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
83234
   */
83235
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
83236
  /**
83237
   * Cast this JSON value to a string.
83238
   *
83239
   * The string is guaranteed to be valid UTF-8.
83240
   *
83241
   * Important: Calling get_string() twice on the same document is an error.
83242
   *
83243
   * @param Whether to allow a replacement character for unmatched surrogate pairs.
83244
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
83245
   *          time it parses a document or when it is destroyed.
83246
   * @returns INCORRECT_TYPE if the JSON value is not a string.
83247
   */
83248
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
83249
  /**
83250
   * Attempts to fill the provided std::string reference with the parsed value of the current string.
83251
   *
83252
   * The string is guaranteed to be valid UTF-8.
83253
   *
83254
   * Important: a value should be consumed once. Calling get_string() twice on the same value
83255
   * is an error.
83256
   *
83257
   * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
83258
   * We recommend you avoid allocating an std::string unless you need to.
83259
   *
83260
   * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
83261
   */
83262
  template <typename string_type>
83263
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
83264
  /**
83265
   * Cast this JSON value to a string.
83266
   *
83267
   * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/
83268
   *
83269
   * Important: Calling get_wobbly_string() twice on the same document is an error.
83270
   *
83271
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
83272
   *          time it parses a document or when it is destroyed.
83273
   * @returns INCORRECT_TYPE if the JSON value is not a string.
83274
   */
83275
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
83276
  /**
83277
   * Cast this JSON value to a raw_json_string.
83278
   *
83279
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
83280
   *
83281
   * @returns A pointer to the raw JSON for the given string.
83282
   * @returns INCORRECT_TYPE if the JSON value is not a string.
83283
   */
83284
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
83285
  /**
83286
   * Cast this JSON value to a bool.
83287
   *
83288
   * @returns A bool value.
83289
   * @returns INCORRECT_TYPE if the JSON value is not true or false.
83290
   */
83291
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
83292
  /**
83293
   * Cast this JSON value to a value when the document is an object or an array.
83294
   *
83295
   * You must not have begun iterating through the object or array. When
83296
   * SIMDJSON_DEVELOPMENT_CHECKS is set to 1 (which is the case when building in Debug mode
83297
   * by default), and you have already begun iterating,
83298
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
83299
   * rewind() to reset the document to its initial state before calling this method.
83300
   *
83301
   * @returns A value if a JSON array or object cannot be found.
83302
   * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
83303
   */
83304
  simdjson_inline simdjson_result<value> get_value() noexcept;
83305
83306
  /**
83307
   * Checks if this JSON value is null.  If and only if the value is
83308
   * null, then it is consumed (we advance). If we find a token that
83309
   * begins with 'n' but is not 'null', then an error is returned.
83310
   *
83311
   * @returns Whether the value is null.
83312
   * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
83313
   */
83314
  simdjson_inline simdjson_result<bool> is_null() noexcept;
83315
83316
  /**
83317
   * Get this value as the given type.
83318
   *
83319
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
83320
   *
83321
   * You may use get_double(), get_bool(), get_uint64(), get_int64(),
83322
   * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
83323
   *
83324
   * @returns A value of the given type, parsed from the JSON.
83325
   * @returns INCORRECT_TYPE If the JSON value is not the given type.
83326
   */
83327
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
83328
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
83329
    // immediately fail.
83330
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
83331
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
83332
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
83333
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
83334
      " You may also add support for custom types, see our documentation.");
83335
  }
83336
  /** @overload template<typename T> simdjson_result<T> get() & noexcept */
83337
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
83338
    // Unless the simdjson library or the user provides an inline implementation, calling this method should
83339
    // immediately fail.
83340
    static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
83341
      "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
83342
      "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
83343
      " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
83344
      " You may also add support for custom types, see our documentation.");
83345
  }
83346
83347
  /**
83348
   * Get this value as the given type.
83349
   *
83350
   * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
83351
   *
83352
   * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
83353
   *
83354
   * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
83355
   * @returns INCORRECT_TYPE If the JSON value is not an object.
83356
   * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
83357
   */
83358
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
83359
  /** @overload template<typename T> error_code get(T &out) & noexcept */
83360
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
83361
83362
#if SIMDJSON_EXCEPTIONS
83363
  /**
83364
   * Cast this JSON value to an instance of type T. The programmer is responsible for
83365
   * providing an implementation of get<T> for the type T, if T is not one of the types
83366
   * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.)
83367
   *
83368
   * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
83369
   *
83370
   * @returns An instance of type T
83371
   */
83372
  template <class T>
83373
  explicit simdjson_inline operator T() noexcept(false);
83374
  /**
83375
   * Cast this JSON value to an array.
83376
   *
83377
   * @returns An object that can be used to iterate the array.
83378
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
83379
   */
83380
  simdjson_inline operator array() & noexcept(false);
83381
  /**
83382
   * Cast this JSON value to an object.
83383
   *
83384
   * @returns An object that can be used to look up or iterate fields.
83385
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
83386
   */
83387
  simdjson_inline operator object() & noexcept(false);
83388
  /**
83389
   * Cast this JSON value to an unsigned integer.
83390
   *
83391
   * @returns A signed 64-bit integer.
83392
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
83393
   */
83394
  simdjson_inline operator uint64_t() noexcept(false);
83395
  /**
83396
   * Cast this JSON value to a signed integer.
83397
   *
83398
   * @returns A signed 64-bit integer.
83399
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
83400
   */
83401
  simdjson_inline operator int64_t() noexcept(false);
83402
  /**
83403
   * Cast this JSON value to a double.
83404
   *
83405
   * @returns A double.
83406
   * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
83407
   */
83408
  simdjson_inline operator double() noexcept(false);
83409
  /**
83410
   * Cast this JSON value to a string.
83411
   *
83412
   * The string is guaranteed to be valid UTF-8.
83413
   *
83414
   * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
83415
   *          time it parses a document or when it is destroyed.
83416
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
83417
   */
83418
  simdjson_inline operator std::string_view() noexcept(false);
83419
  /**
83420
   * Cast this JSON value to a raw_json_string.
83421
   *
83422
   * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
83423
   *
83424
   * @returns A pointer to the raw JSON for the given string.
83425
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
83426
   */
83427
  simdjson_inline operator raw_json_string() noexcept(false);
83428
  /**
83429
   * Cast this JSON value to a bool.
83430
   *
83431
   * @returns A bool value.
83432
   * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
83433
   */
83434
  simdjson_inline operator bool() noexcept(false);
83435
  /**
83436
   * Cast this JSON value to a value when the document is an object or an array.
83437
   *
83438
   * You must not have begun iterating through the object or array. When
83439
   * SIMDJSON_DEVELOPMENT_CHECKS is defined, and you have already begun iterating,
83440
   * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
83441
   * rewind() to reset the document to its initial state before calling this method.
83442
   *
83443
   * @returns A value value if a JSON array or object cannot be found.
83444
   * @exception SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
83445
   */
83446
  simdjson_inline operator value() noexcept(false);
83447
#endif
83448
  /**
83449
   * This method scans the array and counts the number of elements.
83450
   * The count_elements method should always be called before you have begun
83451
   * iterating through the array: it is expected that you are pointing at
83452
   * the beginning of the array.
83453
   * The runtime complexity is linear in the size of the array. After
83454
   * calling this function, if successful, the array is 'rewinded' at its
83455
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
83456
   * there is a missing comma), then an error is returned and it is no longer
83457
   * safe to continue.
83458
   */
83459
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
83460
   /**
83461
   * This method scans the object and counts the number of key-value pairs.
83462
   * The count_fields method should always be called before you have begun
83463
   * iterating through the object: it is expected that you are pointing at
83464
   * the beginning of the object.
83465
   * The runtime complexity is linear in the size of the object. After
83466
   * calling this function, if successful, the object is 'rewinded' at its
83467
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
83468
   * there is a missing comma), then an error is returned and it is no longer
83469
   * safe to continue.
83470
   *
83471
   * To check that an object is empty, it is more performant to use
83472
   * the is_empty() method.
83473
   */
83474
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
83475
  /**
83476
   * Get the value at the given index in the array. This function has linear-time complexity.
83477
   * This function should only be called once on an array instance since the array iterator is not reset between each call.
83478
   *
83479
   * @return The value at the given index, or:
83480
   *         - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
83481
   */
83482
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
83483
  /**
83484
   * Begin array iteration.
83485
   *
83486
   * Part of the std::iterable interface.
83487
   */
83488
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
83489
  /**
83490
   * Sentinel representing the end of the array.
83491
   *
83492
   * Part of the std::iterable interface.
83493
   */
83494
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
83495
83496
  /**
83497
   * Look up a field by name on an object (order-sensitive).
83498
   *
83499
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
83500
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
83501
   *
83502
   * ```c++
83503
   * simdjson::ondemand::parser parser;
83504
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
83505
   * double z = obj.find_field("z");
83506
   * double y = obj.find_field("y");
83507
   * double x = obj.find_field("x");
83508
   * ```
83509
   *
83510
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
83511
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
83512
   *
83513
   *
83514
   * You must consume the fields on an object one at a time. A request for a new key
83515
   * invalidates previous field values: it makes them unsafe. E.g., the array
83516
   * given by content["bids"].get_array() should not be accessed after you have called
83517
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
83518
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
83519
   * OUT_OF_ORDER_ITERATION error is generated.
83520
   *
83521
   * You are expected to access keys only once. You should access the value corresponding to
83522
   * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
83523
   * is an error.
83524
   *
83525
   * @param key The key to look up.
83526
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
83527
   */
83528
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
83529
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
83530
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
83531
83532
  /**
83533
   * Look up a field by name on an object, without regard to key order.
83534
   *
83535
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
83536
   * and often appears negligible. It starts out normally, starting out at the last field; but if
83537
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
83538
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
83539
   * in question is large. The fact that the extra code is there also bumps the executable size.
83540
   *
83541
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
83542
   * default behavior failed to look up a field just because it was in the wrong order--and many
83543
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
83544
   *
83545
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
83546
   * field was not there when they are not in order).
83547
   *
83548
   * You must consume the fields on an object one at a time. A request for a new key
83549
   * invalidates previous field values: it makes them unsafe. E.g., the array
83550
   * given by content["bids"].get_array() should not be accessed after you have called
83551
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
83552
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
83553
   * OUT_OF_ORDER_ITERATION error is generated.
83554
   *
83555
   * You are expected to access keys only once. You should access the value corresponding to a key
83556
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
83557
   * is an error.
83558
   *
83559
   * @param key The key to look up.
83560
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
83561
   */
83562
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
83563
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
83564
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
83565
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
83566
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
83567
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
83568
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
83569
83570
  /**
83571
   * Get the type of this JSON value. It does not validate or consume the value.
83572
   * E.g., you must still call "is_null()" to check that a value is null even if
83573
   * "type()" returns json_type::null.
83574
   *
83575
   * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
83576
   * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
83577
   * let it throw an exception).
83578
   *
83579
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
83580
   */
83581
  simdjson_inline simdjson_result<json_type> type() noexcept;
83582
83583
  /**
83584
   * Checks whether the document is a scalar (string, number, null, Boolean).
83585
   * Returns false when there it is an array or object.
83586
   *
83587
   * @returns true if the type is string, number, null, Boolean
83588
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
83589
   */
83590
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
83591
83592
  /**
83593
   * Checks whether the document is a string.
83594
   *
83595
   * @returns true if the type is string
83596
   * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
83597
   */
83598
  simdjson_inline simdjson_result<bool> is_string() noexcept;
83599
83600
  /**
83601
   * Checks whether the document is a negative number.
83602
   *
83603
   * @returns true if the number if negative.
83604
   */
83605
  simdjson_inline bool is_negative() noexcept;
83606
  /**
83607
   * Checks whether the document is an integer number. Note that
83608
   * this requires to partially parse the number string. If
83609
   * the value is determined to be an integer, it may still
83610
   * not parse properly as an integer in subsequent steps
83611
   * (e.g., it might overflow).
83612
   *
83613
   * @returns true if the number if negative.
83614
   */
83615
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
83616
  /**
83617
   * Determine the number type (integer or floating-point number) as quickly
83618
   * as possible. This function does not fully validate the input. It is
83619
   * useful when you only need to classify the numbers, without parsing them.
83620
   *
83621
   * If you are planning to retrieve the value or you need full validation,
83622
   * consider using the get_number() method instead: it will fully parse
83623
   * and validate the input, and give you access to the type:
83624
   * get_number().get_number_type().
83625
   *
83626
   * get_number_type() is number_type::unsigned_integer if we have
83627
   * an integer greater or equal to 9223372036854775808 and no larger than 18446744073709551615.
83628
   * get_number_type() is number_type::signed_integer if we have an
83629
   * integer that is less than 9223372036854775808 and greater or equal to -9223372036854775808.
83630
   * get_number_type() is number_type::big_integer if we have an integer outside
83631
   * of those ranges (either larger than 18446744073709551615 or smaller than -9223372036854775808).
83632
   * Otherwise, get_number_type() has value number_type::floating_point_number
83633
   *
83634
   * This function requires processing the number string, but it is expected
83635
   * to be faster than get_number().get_number_type() because it is does not
83636
   * parse the number value.
83637
   *
83638
   * @returns the type of the number
83639
   */
83640
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
83641
83642
  /**
83643
   * Attempt to parse an ondemand::number. An ondemand::number may
83644
   * contain an integer value or a floating-point value, the simdjson
83645
   * library will autodetect the type. Thus it is a dynamically typed
83646
   * number. Before accessing the value, you must determine the detected
83647
   * type.
83648
   *
83649
   * number.get_number_type() is number_type::signed_integer if we have
83650
   * an integer in [-9223372036854775808,9223372036854775808)
83651
   * You can recover the value by calling number.get_int64() and you
83652
   * have that number.is_int64() is true.
83653
   *
83654
   * number.get_number_type() is number_type::unsigned_integer if we have
83655
   * an integer in [9223372036854775808,18446744073709551616)
83656
   * You can recover the value by calling number.get_uint64() and you
83657
   * have that number.is_uint64() is true.
83658
   *
83659
   * Otherwise, number.get_number_type() has value number_type::floating_point_number
83660
   * and we have a binary64 number.
83661
   * You can recover the value by calling number.get_double() and you
83662
   * have that number.is_double() is true.
83663
   *
83664
   * You must check the type before accessing the value: it is an error
83665
   * to call "get_int64()" when number.get_number_type() is not
83666
   * number_type::signed_integer and when number.is_int64() is false.
83667
   */
83668
  simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
83669
83670
  /**
83671
   * Get the raw JSON for this token.
83672
   *
83673
   * The string_view will always point into the input buffer.
83674
   *
83675
   * The string_view will start at the beginning of the token, and include the entire token
83676
   * *as well as all spaces until the next token (or EOF).* This means, for example, that a
83677
   * string token always begins with a " and is always terminated by the final ", possibly
83678
   * followed by a number of spaces.
83679
   *
83680
   * The string_view is *not* null-terminated. If this is a scalar (string, number,
83681
   * boolean, or null), the character after the end of the string_view may be the padded buffer.
83682
   *
83683
   * Tokens include:
83684
   * - {
83685
   * - [
83686
   * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
83687
   * - -1.2e-100
83688
   * - true
83689
   * - false
83690
   * - null
83691
   */
83692
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
83693
83694
  /**
83695
   * Reset the iterator inside the document instance so we are pointing back at the
83696
   * beginning of the document, as if it had just been created. It invalidates all
83697
   * values, objects and arrays that you have created so far (including unescaped strings).
83698
   */
83699
  inline void rewind() noexcept;
83700
  /**
83701
   * Returns debugging information.
83702
   */
83703
  inline std::string to_debug_string() noexcept;
83704
  /**
83705
   * Some unrecoverable error conditions may render the document instance unusable.
83706
   * The is_alive() method returns true when the document is still suitable.
83707
   */
83708
  inline bool is_alive() noexcept;
83709
83710
  /**
83711
   * Returns the current location in the document if in bounds.
83712
   */
83713
  inline simdjson_result<const char *> current_location() const noexcept;
83714
83715
  /**
83716
   * Returns true if this document has been fully parsed.
83717
   * If you have consumed the whole document and at_end() returns
83718
   * false, then there may be trailing content.
83719
   */
83720
  inline bool at_end() const noexcept;
83721
83722
  /**
83723
   * Returns the current depth in the document if in bounds.
83724
   *
83725
   * E.g.,
83726
   *  0 = finished with document
83727
   *  1 = document root value (could be [ or {, not yet known)
83728
   *  2 = , or } inside root array/object
83729
   *  3 = key or value inside root array/object.
83730
   */
83731
  simdjson_inline int32_t current_depth() const noexcept;
83732
83733
  /**
83734
   * Get the value associated with the given JSON pointer.  We use the RFC 6901
83735
   * https://tools.ietf.org/html/rfc6901 standard.
83736
   *
83737
   *   ondemand::parser parser;
83738
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
83739
   *   auto doc = parser.iterate(json);
83740
   *   doc.at_pointer("/foo/a/1") == 20
83741
   *
83742
   * It is allowed for a key to be the empty string:
83743
   *
83744
   *   ondemand::parser parser;
83745
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
83746
   *   auto doc = parser.iterate(json);
83747
   *   doc.at_pointer("//a/1") == 20
83748
   *
83749
   * Key values are matched exactly, without unescaping or Unicode normalization.
83750
   * We do a byte-by-byte comparison. E.g.
83751
   *
83752
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
83753
   *   auto doc = parser.iterate(json);
83754
   *   doc.at_pointer("/\\u00E9") == 123
83755
   *   doc.at_pointer((const char*)u8"/\u00E9") returns an error (NO_SUCH_FIELD)
83756
   *
83757
   * Note that at_pointer() automatically calls rewind between each call. Thus
83758
   * all values, objects and arrays that you have created so far (including unescaped strings)
83759
   * are invalidated. After calling at_pointer, you need to consume the result: string values
83760
   * should be stored in your own variables, arrays should be decoded and stored in your own array-like
83761
   * structures and so forth.
83762
   *
83763
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
83764
   *
83765
   * @return The value associated with the given JSON pointer, or:
83766
   *         - NO_SUCH_FIELD if a field does not exist in an object
83767
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
83768
   *         - INCORRECT_TYPE if a non-integer is used to access an array
83769
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
83770
   *         - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
83771
   */
83772
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
83773
83774
  /**
83775
   * Get the value associated with the given JSONPath expression. We only support
83776
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
83777
   * names and array indices.
83778
   *
83779
   * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
83780
   *
83781
   * Key values are matched exactly, without unescaping or Unicode normalization.
83782
   * We do a byte-by-byte comparison. E.g.
83783
   *
83784
   *   const padded_string json = "{\"\\u00E9\":123}"_padded;
83785
   *   auto doc = parser.iterate(json);
83786
   *   doc.at_path(".\\u00E9") == 123
83787
   *   doc.at_path((const char*)u8".\u00E9") returns an error (NO_SUCH_FIELD)
83788
   *
83789
   * @return The value associated with the given JSONPath expression, or:
83790
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
83791
   *         - NO_SUCH_FIELD if a field does not exist in an object
83792
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
83793
   *         - INCORRECT_TYPE if a non-integer is used to access an array
83794
   */
83795
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
83796
83797
  /**
83798
   * Consumes the document and returns a string_view instance corresponding to the
83799
   * document as represented in JSON. It points inside the original byte array containing
83800
   * the JSON document.
83801
   */
83802
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
83803
protected:
83804
  /**
83805
   * Consumes the document.
83806
   */
83807
  simdjson_inline error_code consume() noexcept;
83808
83809
  simdjson_inline document(ondemand::json_iterator &&iter) noexcept;
83810
  simdjson_inline const uint8_t *text(uint32_t idx) const noexcept;
83811
83812
  simdjson_inline value_iterator resume_value_iterator() noexcept;
83813
  simdjson_inline value_iterator get_root_value_iterator() noexcept;
83814
  simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
83815
  static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept;
83816
83817
  //
83818
  // Fields
83819
  //
83820
  json_iterator iter{}; ///< Current position in the document
83821
  static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0
83822
83823
  friend class array_iterator;
83824
  friend class value;
83825
  friend class ondemand::parser;
83826
  friend class object;
83827
  friend class array;
83828
  friend class field;
83829
  friend class token;
83830
  friend class document_stream;
83831
  friend class document_reference;
83832
};
83833
83834
83835
/**
83836
 * A document_reference is a thin wrapper around a document reference instance.
83837
 */
83838
class document_reference {
83839
public:
83840
  simdjson_inline document_reference() noexcept;
83841
  simdjson_inline document_reference(document &d) noexcept;
83842
  simdjson_inline document_reference(const document_reference &other) noexcept = default;
83843
  simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default;
83844
  simdjson_inline void rewind() noexcept;
83845
  simdjson_inline simdjson_result<array> get_array() & noexcept;
83846
  simdjson_inline simdjson_result<object> get_object() & noexcept;
83847
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
83848
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
83849
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
83850
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
83851
  simdjson_inline simdjson_result<double> get_double() noexcept;
83852
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
83853
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
83854
  template <typename string_type>
83855
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
83856
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
83857
  simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
83858
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
83859
  simdjson_inline simdjson_result<value> get_value() noexcept;
83860
83861
  simdjson_inline simdjson_result<bool> is_null() noexcept;
83862
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
83863
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
83864
  simdjson_inline operator document&() const noexcept;
83865
#if SIMDJSON_EXCEPTIONS
83866
  template <class T>
83867
  explicit simdjson_inline operator T() noexcept(false);
83868
  simdjson_inline operator array() & noexcept(false);
83869
  simdjson_inline operator object() & noexcept(false);
83870
  simdjson_inline operator uint64_t() noexcept(false);
83871
  simdjson_inline operator int64_t() noexcept(false);
83872
  simdjson_inline operator double() noexcept(false);
83873
  simdjson_inline operator std::string_view() noexcept(false);
83874
  simdjson_inline operator raw_json_string() noexcept(false);
83875
  simdjson_inline operator bool() noexcept(false);
83876
  simdjson_inline operator value() noexcept(false);
83877
#endif
83878
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
83879
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
83880
  simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
83881
  simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
83882
  simdjson_inline simdjson_result<array_iterator> end() & noexcept;
83883
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
83884
  simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
83885
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
83886
  simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
83887
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
83888
  simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
83889
83890
  simdjson_inline simdjson_result<json_type> type() noexcept;
83891
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
83892
  simdjson_inline simdjson_result<bool> is_string() noexcept;
83893
83894
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
83895
  simdjson_inline int32_t current_depth() const noexcept;
83896
  simdjson_inline bool is_negative() noexcept;
83897
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
83898
  simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
83899
  simdjson_inline simdjson_result<number> get_number() noexcept;
83900
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
83901
  simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
83902
  simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
83903
83904
private:
83905
  document *doc{nullptr};
83906
};
83907
} // namespace ondemand
83908
} // namespace westmere
83909
} // namespace simdjson
83910
83911
namespace simdjson {
83912
83913
template<>
83914
struct simdjson_result<westmere::ondemand::document> : public westmere::implementation_simdjson_result_base<westmere::ondemand::document> {
83915
public:
83916
  simdjson_inline simdjson_result(westmere::ondemand::document &&value) noexcept; ///< @private
83917
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
83918
  simdjson_inline simdjson_result() noexcept = default;
83919
  simdjson_inline error_code rewind() noexcept;
83920
83921
  simdjson_inline simdjson_result<westmere::ondemand::array> get_array() & noexcept;
83922
  simdjson_inline simdjson_result<westmere::ondemand::object> get_object() & noexcept;
83923
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
83924
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
83925
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
83926
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
83927
  simdjson_inline simdjson_result<double> get_double() noexcept;
83928
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
83929
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
83930
  template <typename string_type>
83931
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
83932
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
83933
  simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> get_raw_json_string() noexcept;
83934
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
83935
  simdjson_inline simdjson_result<westmere::ondemand::value> get_value() noexcept;
83936
  simdjson_inline simdjson_result<bool> is_null() noexcept;
83937
83938
  template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
83939
  template<typename T> simdjson_inline simdjson_result<T> get() && noexcept;
83940
83941
  template<typename T> simdjson_inline error_code get(T &out) & noexcept;
83942
  template<typename T> simdjson_inline error_code get(T &out) && noexcept;
83943
#if SIMDJSON_EXCEPTIONS
83944
  template <class T, typename std::enable_if<std::is_same<T, westmere::ondemand::document>::value == false>::type>
83945
  explicit simdjson_inline operator T() noexcept(false);
83946
  simdjson_inline operator westmere::ondemand::array() & noexcept(false);
83947
  simdjson_inline operator westmere::ondemand::object() & noexcept(false);
83948
  simdjson_inline operator uint64_t() noexcept(false);
83949
  simdjson_inline operator int64_t() noexcept(false);
83950
  simdjson_inline operator double() noexcept(false);
83951
  simdjson_inline operator std::string_view() noexcept(false);
83952
  simdjson_inline operator westmere::ondemand::raw_json_string() noexcept(false);
83953
  simdjson_inline operator bool() noexcept(false);
83954
  simdjson_inline operator westmere::ondemand::value() noexcept(false);
83955
#endif
83956
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
83957
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
83958
  simdjson_inline simdjson_result<westmere::ondemand::value> at(size_t index) & noexcept;
83959
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> begin() & noexcept;
83960
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> end() & noexcept;
83961
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(std::string_view key) & noexcept;
83962
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(const char *key) & noexcept;
83963
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](std::string_view key) & noexcept;
83964
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](const char *key) & noexcept;
83965
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
83966
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(const char *key) & noexcept;
83967
  simdjson_inline simdjson_result<westmere::ondemand::json_type> type() noexcept;
83968
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
83969
  simdjson_inline simdjson_result<bool> is_string() noexcept;
83970
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
83971
  simdjson_inline int32_t current_depth() const noexcept;
83972
  simdjson_inline bool at_end() const noexcept;
83973
  simdjson_inline bool is_negative() noexcept;
83974
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
83975
  simdjson_inline simdjson_result<westmere::number_type> get_number_type() noexcept;
83976
  simdjson_inline simdjson_result<westmere::ondemand::number> get_number() noexcept;
83977
  /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */
83978
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
83979
83980
  simdjson_inline simdjson_result<westmere::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
83981
  simdjson_inline simdjson_result<westmere::ondemand::value> at_path(std::string_view json_path) noexcept;
83982
};
83983
83984
83985
} // namespace simdjson
83986
83987
83988
83989
namespace simdjson {
83990
83991
template<>
83992
struct simdjson_result<westmere::ondemand::document_reference> : public westmere::implementation_simdjson_result_base<westmere::ondemand::document_reference> {
83993
public:
83994
  simdjson_inline simdjson_result(westmere::ondemand::document_reference value, error_code error) noexcept;
83995
  simdjson_inline simdjson_result() noexcept = default;
83996
  simdjson_inline error_code rewind() noexcept;
83997
83998
  simdjson_inline simdjson_result<westmere::ondemand::array> get_array() & noexcept;
83999
  simdjson_inline simdjson_result<westmere::ondemand::object> get_object() & noexcept;
84000
  simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
84001
  simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
84002
  simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
84003
  simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
84004
  simdjson_inline simdjson_result<double> get_double() noexcept;
84005
  simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
84006
  simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
84007
  template <typename string_type>
84008
  simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
84009
  simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
84010
  simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> get_raw_json_string() noexcept;
84011
  simdjson_inline simdjson_result<bool> get_bool() noexcept;
84012
  simdjson_inline simdjson_result<westmere::ondemand::value> get_value() noexcept;
84013
  simdjson_inline simdjson_result<bool> is_null() noexcept;
84014
#if SIMDJSON_EXCEPTIONS
84015
  template <class T, typename std::enable_if<std::is_same<T, westmere::ondemand::document_reference>::value == false>::type>
84016
  explicit simdjson_inline operator T() noexcept(false);
84017
  simdjson_inline operator westmere::ondemand::array() & noexcept(false);
84018
  simdjson_inline operator westmere::ondemand::object() & noexcept(false);
84019
  simdjson_inline operator uint64_t() noexcept(false);
84020
  simdjson_inline operator int64_t() noexcept(false);
84021
  simdjson_inline operator double() noexcept(false);
84022
  simdjson_inline operator std::string_view() noexcept(false);
84023
  simdjson_inline operator westmere::ondemand::raw_json_string() noexcept(false);
84024
  simdjson_inline operator bool() noexcept(false);
84025
  simdjson_inline operator westmere::ondemand::value() noexcept(false);
84026
#endif
84027
  simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
84028
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
84029
  simdjson_inline simdjson_result<westmere::ondemand::value> at(size_t index) & noexcept;
84030
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> begin() & noexcept;
84031
  simdjson_inline simdjson_result<westmere::ondemand::array_iterator> end() & noexcept;
84032
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(std::string_view key) & noexcept;
84033
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(const char *key) & noexcept;
84034
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](std::string_view key) & noexcept;
84035
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](const char *key) & noexcept;
84036
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
84037
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(const char *key) & noexcept;
84038
  simdjson_inline simdjson_result<westmere::ondemand::json_type> type() noexcept;
84039
  simdjson_inline simdjson_result<bool> is_scalar() noexcept;
84040
  simdjson_inline simdjson_result<bool> is_string() noexcept;
84041
  simdjson_inline simdjson_result<const char *> current_location() noexcept;
84042
  simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
84043
  simdjson_inline simdjson_result<bool> is_negative() noexcept;
84044
  simdjson_inline simdjson_result<bool> is_integer() noexcept;
84045
  simdjson_inline simdjson_result<westmere::number_type> get_number_type() noexcept;
84046
  simdjson_inline simdjson_result<westmere::ondemand::number> get_number() noexcept;
84047
  /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */
84048
  simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
84049
84050
  simdjson_inline simdjson_result<westmere::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
84051
  simdjson_inline simdjson_result<westmere::ondemand::value> at_path(std::string_view json_path) noexcept;
84052
};
84053
84054
84055
} // namespace simdjson
84056
84057
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
84058
/* end file simdjson/generic/ondemand/document.h for westmere */
84059
/* including simdjson/generic/ondemand/document_stream.h for westmere: #include "simdjson/generic/ondemand/document_stream.h" */
84060
/* begin file simdjson/generic/ondemand/document_stream.h for westmere */
84061
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
84062
84063
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
84064
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H */
84065
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
84066
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
84067
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
84068
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
84069
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
84070
84071
#ifdef SIMDJSON_THREADS_ENABLED
84072
#include <thread>
84073
#include <mutex>
84074
#include <condition_variable>
84075
#endif
84076
84077
namespace simdjson {
84078
namespace westmere {
84079
namespace ondemand {
84080
84081
#ifdef SIMDJSON_THREADS_ENABLED
84082
/** @private Custom worker class **/
84083
struct stage1_worker {
84084
  stage1_worker() noexcept = default;
84085
  stage1_worker(const stage1_worker&) = delete;
84086
  stage1_worker(stage1_worker&&) = delete;
84087
  stage1_worker operator=(const stage1_worker&) = delete;
84088
  ~stage1_worker();
84089
  /**
84090
   * We only start the thread when it is needed, not at object construction, this may throw.
84091
   * You should only call this once.
84092
   **/
84093
  void start_thread();
84094
  /**
84095
   * Start a stage 1 job. You should first call 'run', then 'finish'.
84096
   * You must call start_thread once before.
84097
   */
84098
  void run(document_stream * ds, parser * stage1, size_t next_batch_start);
84099
  /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
84100
  void finish();
84101
84102
private:
84103
84104
  /**
84105
   * Normally, we would never stop the thread. But we do in the destructor.
84106
   * This function is only safe assuming that you are not waiting for results. You
84107
   * should have called run, then finish, and be done.
84108
   **/
84109
  void stop_thread();
84110
84111
  std::thread thread{};
84112
  /** These three variables define the work done by the thread. **/
84113
  ondemand::parser * stage1_thread_parser{};
84114
  size_t _next_batch_start{};
84115
  document_stream * owner{};
84116
  /**
84117
   * We have two state variables. This could be streamlined to one variable in the future but
84118
   * we use two for clarity.
84119
   */
84120
  bool has_work{false};
84121
  bool can_work{true};
84122
84123
  /**
84124
   * We lock using a mutex.
84125
   */
84126
  std::mutex locking_mutex{};
84127
  std::condition_variable cond_var{};
84128
84129
  friend class document_stream;
84130
};
84131
#endif  // SIMDJSON_THREADS_ENABLED
84132
84133
/**
84134
 * A forward-only stream of documents.
84135
 *
84136
 * Produced by parser::iterate_many.
84137
 *
84138
 */
84139
class document_stream {
84140
public:
84141
  /**
84142
   * Construct an uninitialized document_stream.
84143
   *
84144
   *  ```c++
84145
   *  document_stream docs;
84146
   *  auto error = parser.iterate_many(json).get(docs);
84147
   *  ```
84148
   */
84149
  simdjson_inline document_stream() noexcept;
84150
  /** Move one document_stream to another. */
84151
  simdjson_inline document_stream(document_stream &&other) noexcept = default;
84152
  /** Move one document_stream to another. */
84153
  simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
84154
84155
  simdjson_inline ~document_stream() noexcept;
84156
84157
  /**
84158
   * Returns the input size in bytes.
84159
   */
84160
  inline size_t size_in_bytes() const noexcept;
84161
84162
  /**
84163
   * After iterating through the stream, this method
84164
   * returns the number of bytes that were not parsed at the end
84165
   * of the stream. If truncated_bytes() differs from zero,
84166
   * then the input was truncated maybe because incomplete JSON
84167
   * documents were found at the end of the stream. You
84168
   * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
84169
   *
84170
   * You should only call truncated_bytes() after streaming through all
84171
   * documents, like so:
84172
   *
84173
   *   document_stream stream = parser.iterate_many(json,window);
84174
   *   for(auto & doc : stream) {
84175
   *      // do something with doc
84176
   *   }
84177
   *   size_t truncated = stream.truncated_bytes();
84178
   *
84179
   */
84180
  inline size_t truncated_bytes() const noexcept;
84181
84182
  class iterator {
84183
  public:
84184
    using value_type = simdjson_result<document>;
84185
    using reference  = simdjson_result<ondemand::document_reference>;
84186
    using pointer    = void;
84187
    using difference_type   = std::ptrdiff_t;
84188
    using iterator_category = std::input_iterator_tag;
84189
84190
    /**
84191
     * Default constructor.
84192
     */
84193
    simdjson_inline iterator() noexcept;
84194
    /**
84195
     * Get the current document (or error).
84196
     */
84197
    simdjson_inline reference operator*() noexcept;
84198
    /**
84199
     * Advance to the next document (prefix).
84200
     */
84201
    inline iterator& operator++() noexcept;
84202
    /**
84203
     * Check if we're at the end yet.
84204
     * @param other the end iterator to compare to.
84205
     */
84206
    simdjson_inline bool operator!=(const iterator &other) const noexcept;
84207
    /**
84208
     * @private
84209
     *
84210
     * Gives the current index in the input document in bytes.
84211
     *
84212
     *   document_stream stream = parser.parse_many(json,window);
84213
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
84214
     *      auto doc = *i;
84215
     *      size_t index = i.current_index();
84216
     *   }
84217
     *
84218
     * This function (current_index()) is experimental and the usage
84219
     * may change in future versions of simdjson: we find the API somewhat
84220
     * awkward and we would like to offer something friendlier.
84221
     */
84222
     simdjson_inline size_t current_index() const noexcept;
84223
84224
     /**
84225
     * @private
84226
     *
84227
     * Gives a view of the current document at the current position.
84228
     *
84229
     *   document_stream stream = parser.iterate_many(json,window);
84230
     *   for(auto i = stream.begin(); i != stream.end(); ++i) {
84231
     *      std::string_view v = i.source();
84232
     *   }
84233
     *
84234
     * The returned string_view instance is simply a map to the (unparsed)
84235
     * source string: it may thus include white-space characters and all manner
84236
     * of padding.
84237
     *
84238
     * This function (source()) is experimental and the usage
84239
     * may change in future versions of simdjson: we find the API somewhat
84240
     * awkward and we would like to offer something friendlier.
84241
     *
84242
     */
84243
     simdjson_inline std::string_view source() const noexcept;
84244
84245
    /**
84246
     * Returns error of the stream (if any).
84247
     */
84248
     inline error_code error() const noexcept;
84249
84250
  private:
84251
    simdjson_inline iterator(document_stream *s, bool finished) noexcept;
84252
    /** The document_stream we're iterating through. */
84253
    document_stream* stream;
84254
    /** Whether we're finished or not. */
84255
    bool finished;
84256
84257
    friend class document;
84258
    friend class document_stream;
84259
    friend class json_iterator;
84260
  };
84261
84262
  /**
84263
   * Start iterating the documents in the stream.
84264
   */
84265
  simdjson_inline iterator begin() noexcept;
84266
  /**
84267
   * The end of the stream, for iterator comparison purposes.
84268
   */
84269
  simdjson_inline iterator end() noexcept;
84270
84271
private:
84272
84273
  document_stream &operator=(const document_stream &) = delete; // Disallow copying
84274
  document_stream(const document_stream &other) = delete; // Disallow copying
84275
84276
  /**
84277
   * Construct a document_stream. Does not allocate or parse anything until the iterator is
84278
   * used.
84279
   *
84280
   * @param parser is a reference to the parser instance used to generate this document_stream
84281
   * @param buf is the raw byte buffer we need to process
84282
   * @param len is the length of the raw byte buffer in bytes
84283
   * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
84284
   */
84285
  simdjson_inline document_stream(
84286
    ondemand::parser &parser,
84287
    const uint8_t *buf,
84288
    size_t len,
84289
    size_t batch_size,
84290
    bool allow_comma_separated
84291
  ) noexcept;
84292
84293
  /**
84294
   * Parse the first document in the buffer. Used by begin(), to handle allocation and
84295
   * initialization.
84296
   */
84297
  inline void start() noexcept;
84298
84299
  /**
84300
   * Parse the next document found in the buffer previously given to document_stream.
84301
   *
84302
   * The content should be a valid JSON document encoded as UTF-8. If there is a
84303
   * UTF-8 BOM, the parser skips it.
84304
   *
84305
   * You do NOT need to pre-allocate a parser.  This function takes care of
84306
   * pre-allocating a capacity defined by the batch_size defined when creating the
84307
   * document_stream object.
84308
   *
84309
   * The function returns simdjson::EMPTY if there is no more data to be parsed.
84310
   *
84311
   * The function returns simdjson::SUCCESS (as integer = 0) in case of success
84312
   * and indicates that the buffer has successfully been parsed to the end.
84313
   * Every document it contained has been parsed without error.
84314
   *
84315
   * The function returns an error code from simdjson/simdjson.h in case of failure
84316
   * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
84317
   * the simdjson::error_message function converts these error codes into a string).
84318
   *
84319
   * You can also check validity by calling parser.is_valid(). The same parser can
84320
   * and should be reused for the other documents in the buffer.
84321
   */
84322
  inline void next() noexcept;
84323
84324
  /** Move the json_iterator of the document to the location of the next document in the stream. */
84325
  inline void next_document() noexcept;
84326
84327
  /** Get the next document index. */
84328
  inline size_t next_batch_start() const noexcept;
84329
84330
  /** Pass the next batch through stage 1 with the given parser. */
84331
  inline error_code run_stage1(ondemand::parser &p, size_t batch_start) noexcept;
84332
84333
  // Fields
84334
  ondemand::parser *parser;
84335
  const uint8_t *buf;
84336
  size_t len;
84337
  size_t batch_size;
84338
  bool allow_comma_separated;
84339
  /**
84340
   * We are going to use just one document instance. The document owns
84341
   * the json_iterator. It implies that we only ever pass a reference
84342
   * to the document to the users.
84343
   */
84344
  document doc{};
84345
  /** The error (or lack thereof) from the current document. */
84346
  error_code error;
84347
  size_t batch_start{0};
84348
  size_t doc_index{};
84349
84350
  #ifdef SIMDJSON_THREADS_ENABLED
84351
  /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
84352
  bool use_thread;
84353
84354
  inline void load_from_stage1_thread() noexcept;
84355
84356
  /** Start a thread to run stage 1 on the next batch. */
84357
  inline void start_stage1_thread() noexcept;
84358
84359
  /** Wait for the stage 1 thread to finish and capture the results. */
84360
  inline void finish_stage1_thread() noexcept;
84361
84362
  /** The error returned from the stage 1 thread. */
84363
  error_code stage1_thread_error{UNINITIALIZED};
84364
  /** The thread used to run stage 1 against the next batch in the background. */
84365
  std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
84366
  /**
84367
   * The parser used to run stage 1 in the background. Will be swapped
84368
   * with the regular parser when finished.
84369
   */
84370
  ondemand::parser stage1_thread_parser{};
84371
84372
  friend struct stage1_worker;
84373
  #endif // SIMDJSON_THREADS_ENABLED
84374
84375
  friend class parser;
84376
  friend class document;
84377
  friend class json_iterator;
84378
  friend struct simdjson_result<ondemand::document_stream>;
84379
  friend struct internal::simdjson_result_base<ondemand::document_stream>;
84380
};  // document_stream
84381
84382
} // namespace ondemand
84383
} // namespace westmere
84384
} // namespace simdjson
84385
84386
namespace simdjson {
84387
template<>
84388
struct simdjson_result<westmere::ondemand::document_stream> : public westmere::implementation_simdjson_result_base<westmere::ondemand::document_stream> {
84389
public:
84390
  simdjson_inline simdjson_result(westmere::ondemand::document_stream &&value) noexcept; ///< @private
84391
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
84392
  simdjson_inline simdjson_result() noexcept = default;
84393
};
84394
84395
} // namespace simdjson
84396
84397
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
84398
/* end file simdjson/generic/ondemand/document_stream.h for westmere */
84399
/* including simdjson/generic/ondemand/field.h for westmere: #include "simdjson/generic/ondemand/field.h" */
84400
/* begin file simdjson/generic/ondemand/field.h for westmere */
84401
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
84402
84403
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
84404
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_H */
84405
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
84406
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
84407
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
84408
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
84409
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
84410
84411
namespace simdjson {
84412
namespace westmere {
84413
namespace ondemand {
84414
84415
/**
84416
 * A JSON field (key/value pair) in an object.
84417
 *
84418
 * Returned from object iteration.
84419
 *
84420
 * Extends from std::pair<raw_json_string, value> so you can use C++ algorithms that rely on pairs.
84421
 */
84422
class field : public std::pair<raw_json_string, value> {
84423
public:
84424
  /**
84425
   * Create a new invalid field.
84426
   *
84427
   * Exists so you can declare a variable and later assign to it before use.
84428
   */
84429
  simdjson_inline field() noexcept;
84430
84431
  /**
84432
   * Get the key as a string_view (for higher speed, consider raw_key).
84433
   * We deliberately use a more cumbersome name (unescaped_key) to force users
84434
   * to think twice about using it.
84435
   *
84436
   * This consumes the key: once you have called unescaped_key(), you cannot
84437
   * call it again nor can you call key().
84438
   */
84439
  simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescaped_key(bool allow_replacement) noexcept;
84440
  /**
84441
   * Get the key as a raw_json_string. Can be used for direct comparison with
84442
   * an unescaped C string: e.g., key() == "test".
84443
   */
84444
  simdjson_inline raw_json_string key() const noexcept;
84445
  /**
84446
   * Get the unprocessed key as a string_view. This includes the quotes and may include
84447
   * some spaces after the last quote.
84448
   */
84449
  simdjson_inline std::string_view key_raw_json_token() const noexcept;
84450
  /**
84451
   * Get the field value.
84452
   */
84453
  simdjson_inline ondemand::value &value() & noexcept;
84454
  /**
84455
   * @overload ondemand::value &ondemand::value() & noexcept
84456
   */
84457
  simdjson_inline ondemand::value value() && noexcept;
84458
84459
protected:
84460
  simdjson_inline field(raw_json_string key, ondemand::value &&value) noexcept;
84461
  static simdjson_inline simdjson_result<field> start(value_iterator &parent_iter) noexcept;
84462
  static simdjson_inline simdjson_result<field> start(const value_iterator &parent_iter, raw_json_string key) noexcept;
84463
  friend struct simdjson_result<field>;
84464
  friend class object_iterator;
84465
};
84466
84467
} // namespace ondemand
84468
} // namespace westmere
84469
} // namespace simdjson
84470
84471
namespace simdjson {
84472
84473
template<>
84474
struct simdjson_result<westmere::ondemand::field> : public westmere::implementation_simdjson_result_base<westmere::ondemand::field> {
84475
public:
84476
  simdjson_inline simdjson_result(westmere::ondemand::field &&value) noexcept; ///< @private
84477
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
84478
  simdjson_inline simdjson_result() noexcept = default;
84479
84480
  simdjson_inline simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
84481
  simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> key() noexcept;
84482
  simdjson_inline simdjson_result<std::string_view> key_raw_json_token() noexcept;
84483
  simdjson_inline simdjson_result<westmere::ondemand::value> value() noexcept;
84484
};
84485
84486
} // namespace simdjson
84487
84488
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_H
84489
/* end file simdjson/generic/ondemand/field.h for westmere */
84490
/* including simdjson/generic/ondemand/object.h for westmere: #include "simdjson/generic/ondemand/object.h" */
84491
/* begin file simdjson/generic/ondemand/object.h for westmere */
84492
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
84493
84494
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
84495
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_H */
84496
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
84497
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
84498
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
84499
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
84500
84501
namespace simdjson {
84502
namespace westmere {
84503
namespace ondemand {
84504
84505
/**
84506
 * A forward-only JSON object field iterator.
84507
 */
84508
class object {
84509
public:
84510
  /**
84511
   * Create a new invalid object.
84512
   *
84513
   * Exists so you can declare a variable and later assign to it before use.
84514
   */
84515
  simdjson_inline object() noexcept = default;
84516
84517
  simdjson_inline simdjson_result<object_iterator> begin() noexcept;
84518
  simdjson_inline simdjson_result<object_iterator> end() noexcept;
84519
  /**
84520
   * Look up a field by name on an object (order-sensitive).
84521
   *
84522
   * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
84523
   * JSON `{ "x": 1, "y": 2, "z": 3 }`:
84524
   *
84525
   * ```c++
84526
   * simdjson::ondemand::parser parser;
84527
   * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
84528
   * double z = obj.find_field("z");
84529
   * double y = obj.find_field("y");
84530
   * double x = obj.find_field("x");
84531
   * ```
84532
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
84533
   * that only one field is returned.
84534
   *
84535
   * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
84536
   * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
84537
   *
84538
   * You must consume the fields on an object one at a time. A request for a new key
84539
   * invalidates previous field values: it makes them unsafe. The value instance you get
84540
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
84541
   * given by content["bids"].get_array() should not be accessed after you have called
84542
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
84543
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
84544
   * OUT_OF_ORDER_ITERATION error is generated.
84545
   *
84546
   * You are expected to access keys only once. You should access the value corresponding to a
84547
   * key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
84548
   * is an error.
84549
   *
84550
   * @param key The key to look up.
84551
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
84552
   */
84553
  simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
84554
  /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
84555
  simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
84556
84557
  /**
84558
   * Look up a field by name on an object, without regard to key order.
84559
   *
84560
   * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
84561
   * and often appears negligible. It starts out normally, starting out at the last field; but if
84562
   * the field is not found, it scans from the beginning of the object to see if it missed it. That
84563
   * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
84564
   * in question is large. The fact that the extra code is there also bumps the executable size.
84565
   *
84566
   * It is the default, however, because it would be highly surprising (and hard to debug) if the
84567
   * default behavior failed to look up a field just because it was in the wrong order--and many
84568
   * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
84569
   *
84570
   * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
84571
   * field was not there when they are not in order).
84572
   *
84573
   * If you have multiple fields with a matching key ({"x": 1,  "x": 1}) be mindful
84574
   * that only one field is returned.
84575
   *
84576
   * You must consume the fields on an object one at a time. A request for a new key
84577
   * invalidates previous field values: it makes them unsafe. The value instance you get
84578
   * from  `content["bids"]` becomes invalid when you call `content["asks"]`. The array
84579
   * given by content["bids"].get_array() should not be accessed after you have called
84580
   * content["asks"].get_array(). You can detect such mistakes by first compiling and running
84581
   * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
84582
   * OUT_OF_ORDER_ITERATION error is generated.
84583
   *
84584
   * You are expected to access keys only once. You should access the value corresponding to a key
84585
   * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
84586
   *
84587
   * @param key The key to look up.
84588
   * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
84589
   */
84590
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
84591
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
84592
  simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
84593
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
84594
  simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
84595
  /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
84596
  simdjson_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
84597
84598
  /**
84599
   * Get the value associated with the given JSON pointer. We use the RFC 6901
84600
   * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
84601
   * as the root of its own JSON document.
84602
   *
84603
   *   ondemand::parser parser;
84604
   *   auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
84605
   *   auto doc = parser.iterate(json);
84606
   *   doc.at_pointer("/foo/a/1") == 20
84607
   *
84608
   * It is allowed for a key to be the empty string:
84609
   *
84610
   *   ondemand::parser parser;
84611
   *   auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
84612
   *   auto doc = parser.iterate(json);
84613
   *   doc.at_pointer("//a/1") == 20
84614
   *
84615
   * Note that at_pointer() called on the document automatically calls the document's rewind
84616
   * method between each call. It invalidates all previously accessed arrays, objects and values
84617
   * that have not been consumed. Yet it is not the case when calling at_pointer on an object
84618
   * instance: there is no rewind and no invalidation.
84619
   *
84620
   * You may call at_pointer more than once on an object, but each time the pointer is advanced
84621
   * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
84622
   * key (as well as the current key) can no longer be used with following JSON pointer calls.
84623
   *
84624
   * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
84625
   *
84626
   * @return The value associated with the given JSON pointer, or:
84627
   *         - NO_SUCH_FIELD if a field does not exist in an object
84628
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
84629
   *         - INCORRECT_TYPE if a non-integer is used to access an array
84630
   *         - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
84631
   */
84632
  inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
84633
84634
  /**
84635
   * Get the value associated with the given JSONPath expression. We only support
84636
   * JSONPath queries that trivially convertible to JSON Pointer queries: key
84637
   * names and array indices.
84638
   *
84639
   * @return The value associated with the given JSONPath expression, or:
84640
   *         - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
84641
   *         - NO_SUCH_FIELD if a field does not exist in an object
84642
   *         - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
84643
   *         - INCORRECT_TYPE if a non-integer is used to access an array
84644
   */
84645
  inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
84646
84647
  /**
84648
   * Reset the iterator so that we are pointing back at the
84649
   * beginning of the object. You should still consume values only once even if you
84650
   * can iterate through the object more than once. If you unescape a string within
84651
   * the object more than once, you have unsafe code. Note that rewinding an object
84652
   * means that you may need to reparse it anew: it is not a free operation.
84653
   *
84654
   * @returns true if the object contains some elements (not empty)
84655
   */
84656
  inline simdjson_result<bool> reset() & noexcept;
84657
  /**
84658
   * This method scans the beginning of the object and checks whether the
84659
   * object is empty.
84660
   * The runtime complexity is constant time. After
84661
   * calling this function, if successful, the object is 'rewinded' at its
84662
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
84663
   * there is a missing comma), then an error is returned and it is no longer
84664
   * safe to continue.
84665
   */
84666
  inline simdjson_result<bool> is_empty() & noexcept;
84667
  /**
84668
   * This method scans the object and counts the number of key-value pairs.
84669
   * The count_fields method should always be called before you have begun
84670
   * iterating through the object: it is expected that you are pointing at
84671
   * the beginning of the object.
84672
   * The runtime complexity is linear in the size of the object. After
84673
   * calling this function, if successful, the object is 'rewinded' at its
84674
   * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
84675
   * there is a missing comma), then an error is returned and it is no longer
84676
   * safe to continue.
84677
   *
84678
   * To check that an object is empty, it is more performant to use
84679
   * the is_empty() method.
84680
   *
84681
   * Performance hint: You should only call count_fields() as a last
84682
   * resort as it may require scanning the document twice or more.
84683
   */
84684
  simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
84685
  /**
84686
   * Consumes the object and returns a string_view instance corresponding to the
84687
   * object as represented in JSON. It points inside the original byte array containing
84688
   * the JSON document.
84689
   */
84690
  simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
84691
84692
protected:
84693
  /**
84694
   * Go to the end of the object, no matter where you are right now.
84695
   */
84696
  simdjson_inline error_code consume() noexcept;
84697
  static simdjson_inline simdjson_result<object> start(value_iterator &iter) noexcept;
84698
  static simdjson_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
84699
  static simdjson_inline simdjson_result<object> started(value_iterator &iter) noexcept;
84700
  static simdjson_inline object resume(const value_iterator &iter) noexcept;
84701
  simdjson_inline object(const value_iterator &iter) noexcept;
84702
84703
  simdjson_warn_unused simdjson_inline error_code find_field_raw(const std::string_view key) noexcept;
84704
84705
  value_iterator iter{};
84706
84707
  friend class value;
84708
  friend class document;
84709
  friend struct simdjson_result<object>;
84710
};
84711
84712
} // namespace ondemand
84713
} // namespace westmere
84714
} // namespace simdjson
84715
84716
namespace simdjson {
84717
84718
template<>
84719
struct simdjson_result<westmere::ondemand::object> : public westmere::implementation_simdjson_result_base<westmere::ondemand::object> {
84720
public:
84721
  simdjson_inline simdjson_result(westmere::ondemand::object &&value) noexcept; ///< @private
84722
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
84723
  simdjson_inline simdjson_result() noexcept = default;
84724
84725
  simdjson_inline simdjson_result<westmere::ondemand::object_iterator> begin() noexcept;
84726
  simdjson_inline simdjson_result<westmere::ondemand::object_iterator> end() noexcept;
84727
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(std::string_view key) & noexcept;
84728
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field(std::string_view key) && noexcept;
84729
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
84730
  simdjson_inline simdjson_result<westmere::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
84731
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](std::string_view key) & noexcept;
84732
  simdjson_inline simdjson_result<westmere::ondemand::value> operator[](std::string_view key) && noexcept;
84733
  simdjson_inline simdjson_result<westmere::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
84734
  simdjson_inline simdjson_result<westmere::ondemand::value> at_path(std::string_view json_path) noexcept;
84735
84736
  inline simdjson_result<bool> reset() noexcept;
84737
  inline simdjson_result<bool> is_empty() noexcept;
84738
  inline simdjson_result<size_t> count_fields() & noexcept;
84739
  inline simdjson_result<std::string_view> raw_json() noexcept;
84740
84741
};
84742
84743
} // namespace simdjson
84744
84745
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
84746
/* end file simdjson/generic/ondemand/object.h for westmere */
84747
/* including simdjson/generic/ondemand/object_iterator.h for westmere: #include "simdjson/generic/ondemand/object_iterator.h" */
84748
/* begin file simdjson/generic/ondemand/object_iterator.h for westmere */
84749
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
84750
84751
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
84752
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H */
84753
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
84754
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */
84755
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
84756
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
84757
84758
namespace simdjson {
84759
namespace westmere {
84760
namespace ondemand {
84761
84762
class object_iterator {
84763
public:
84764
  /**
84765
   * Create a new invalid object_iterator.
84766
   *
84767
   * Exists so you can declare a variable and later assign to it before use.
84768
   */
84769
  simdjson_inline object_iterator() noexcept = default;
84770
84771
  //
84772
  // Iterator interface
84773
  //
84774
84775
  // Reads key and value, yielding them to the user.
84776
  // MUST ONLY BE CALLED ONCE PER ITERATION.
84777
  simdjson_inline simdjson_result<field> operator*() noexcept;
84778
  // Assumes it's being compared with the end. true if depth < iter->depth.
84779
  simdjson_inline bool operator==(const object_iterator &) const noexcept;
84780
  // Assumes it's being compared with the end. true if depth >= iter->depth.
84781
  simdjson_inline bool operator!=(const object_iterator &) const noexcept;
84782
  // Checks for ']' and ','
84783
  simdjson_inline object_iterator &operator++() noexcept;
84784
84785
private:
84786
  /**
84787
   * The underlying JSON iterator.
84788
   *
84789
   * PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
84790
   * is first used, and never changes afterwards.
84791
   */
84792
  value_iterator iter{};
84793
84794
  simdjson_inline object_iterator(const value_iterator &iter) noexcept;
84795
  friend struct simdjson_result<object_iterator>;
84796
  friend class object;
84797
};
84798
84799
} // namespace ondemand
84800
} // namespace westmere
84801
} // namespace simdjson
84802
84803
namespace simdjson {
84804
84805
template<>
84806
struct simdjson_result<westmere::ondemand::object_iterator> : public westmere::implementation_simdjson_result_base<westmere::ondemand::object_iterator> {
84807
public:
84808
  simdjson_inline simdjson_result(westmere::ondemand::object_iterator &&value) noexcept; ///< @private
84809
  simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
84810
  simdjson_inline simdjson_result() noexcept = default;
84811
84812
  //
84813
  // Iterator interface
84814
  //
84815
84816
  // Reads key and value, yielding them to the user.
84817
  simdjson_inline simdjson_result<westmere::ondemand::field> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
84818
  // Assumes it's being compared with the end. true if depth < iter->depth.
84819
  simdjson_inline bool operator==(const simdjson_result<westmere::ondemand::object_iterator> &) const noexcept;
84820
  // Assumes it's being compared with the end. true if depth >= iter->depth.
84821
  simdjson_inline bool operator!=(const simdjson_result<westmere::ondemand::object_iterator> &) const noexcept;
84822
  // Checks for ']' and ','
84823
  simdjson_inline simdjson_result<westmere::ondemand::object_iterator> &operator++() noexcept;
84824
};
84825
84826
} // namespace simdjson
84827
84828
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
84829
/* end file simdjson/generic/ondemand/object_iterator.h for westmere */
84830
/* including simdjson/generic/ondemand/serialization.h for westmere: #include "simdjson/generic/ondemand/serialization.h" */
84831
/* begin file simdjson/generic/ondemand/serialization.h for westmere */
84832
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
84833
84834
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
84835
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H */
84836
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
84837
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
84838
84839
namespace simdjson {
84840
/**
84841
 * Create a string-view instance out of a document instance. The string-view instance
84842
 * contains JSON text that is suitable to be parsed as JSON again. It does not
84843
 * validate the content.
84844
 */
84845
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::document& x) noexcept;
84846
/**
84847
 * Create a string-view instance out of a value instance. The string-view instance
84848
 * contains JSON text that is suitable to be parsed as JSON again. The value must
84849
 * not have been accessed previously. It does not
84850
 * validate the content.
84851
 */
84852
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::value& x) noexcept;
84853
/**
84854
 * Create a string-view instance out of an object instance. The string-view instance
84855
 * contains JSON text that is suitable to be parsed as JSON again. It does not
84856
 * validate the content.
84857
 */
84858
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::object& x) noexcept;
84859
/**
84860
 * Create a string-view instance out of an array instance. The string-view instance
84861
 * contains JSON text that is suitable to be parsed as JSON again. It does not
84862
 * validate the content.
84863
 */
84864
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::array& x) noexcept;
84865
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::document> x);
84866
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::value> x);
84867
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::object> x);
84868
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::array> x);
84869
} // namespace simdjson
84870
84871
/**
84872
 * We want to support argument-dependent lookup (ADL).
84873
 * Hence we should define operator<< in the namespace
84874
 * where the argument (here value, object, etc.) resides.
84875
 * Credit: @madhur4127
84876
 * See https://github.com/simdjson/simdjson/issues/1768
84877
 */
84878
namespace simdjson { namespace westmere { namespace ondemand {
84879
84880
/**
84881
 * Print JSON to an output stream.  It does not
84882
 * validate the content.
84883
 *
84884
 * @param out The output stream.
84885
 * @param value The element.
84886
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
84887
 */
84888
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::value x);
84889
#if SIMDJSON_EXCEPTIONS
84890
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::value> x);
84891
#endif
84892
/**
84893
 * Print JSON to an output stream. It does not
84894
 * validate the content.
84895
 *
84896
 * @param out The output stream.
84897
 * @param value The array.
84898
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
84899
 */
84900
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::array value);
84901
#if SIMDJSON_EXCEPTIONS
84902
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::array> x);
84903
#endif
84904
/**
84905
 * Print JSON to an output stream. It does not
84906
 * validate the content.
84907
 *
84908
 * @param out The output stream.
84909
 * @param value The array.
84910
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
84911
 */
84912
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::document& value);
84913
#if SIMDJSON_EXCEPTIONS
84914
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::document>&& x);
84915
#endif
84916
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::document_reference& value);
84917
#if SIMDJSON_EXCEPTIONS
84918
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::document_reference>&& x);
84919
#endif
84920
/**
84921
 * Print JSON to an output stream. It does not
84922
 * validate the content.
84923
 *
84924
 * @param out The output stream.
84925
 * @param value The object.
84926
 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
84927
 */
84928
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::object value);
84929
#if SIMDJSON_EXCEPTIONS
84930
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::object> x);
84931
#endif
84932
}}} // namespace simdjson::westmere::ondemand
84933
84934
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
84935
/* end file simdjson/generic/ondemand/serialization.h for westmere */
84936
84937
// Inline definitions
84938
/* including simdjson/generic/ondemand/array-inl.h for westmere: #include "simdjson/generic/ondemand/array-inl.h" */
84939
/* begin file simdjson/generic/ondemand/array-inl.h for westmere */
84940
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
84941
84942
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
84943
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H */
84944
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
84945
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
84946
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator-inl.h" */
84947
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
84948
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
84949
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
84950
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
84951
84952
namespace simdjson {
84953
namespace westmere {
84954
namespace ondemand {
84955
84956
//
84957
// ### Live States
84958
//
84959
// While iterating or looking up values, depth >= iter->depth. at_start may vary. Error is
84960
// always SUCCESS:
84961
//
84962
// - Start: This is the state when the array is first found and the iterator is just past the `{`.
84963
//   In this state, at_start == true.
84964
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
84965
//   iterate over, the iterator is at the `,` before the next value (or `]`). In this state,
84966
//   depth == iter->depth, at_start == false, and error == SUCCESS.
84967
// - Unfinished Business: When we hand an array/object to the user which they do not fully
84968
//   iterate over, we need to finish that iteration by skipping child values until we reach the
84969
//   Next state. In this state, depth > iter->depth, at_start == false, and error == SUCCESS.
84970
//
84971
// ## Error States
84972
//
84973
// In error states, we will yield exactly one more value before stopping. iter->depth == depth
84974
// and at_start is always false. We decrement after yielding the error, moving to the Finished
84975
// state.
84976
//
84977
// - Chained Error: When the array iterator is part of an error chain--for example, in
84978
//   `for (auto tweet : doc["tweets"])`, where the tweet element may be missing or not be an
84979
//   array--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
84980
//   iter->depth == depth, and at_start == false. We decrement depth when we yield the error.
84981
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between elements,
84982
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
84983
//   error == TAPE_ERROR, iter->depth == depth, and at_start == false.
84984
//
84985
// ## Terminal State
84986
//
84987
// The terminal state has iter->depth < depth. at_start is always false.
84988
//
84989
// - Finished: When we have reached a `]` or have reported an error, we are finished. We signal this
84990
//   by decrementing depth. In this state, iter->depth < depth, at_start == false, and
84991
//   error == SUCCESS.
84992
//
84993
84994
simdjson_inline array::array(const value_iterator &_iter) noexcept
84995
  : iter{_iter}
84996
{
84997
}
84998
84999
simdjson_inline simdjson_result<array> array::start(value_iterator &iter) noexcept {
85000
  // We don't need to know if the array is empty to start iteration, but we do want to know if there
85001
  // is an error--thus `simdjson_unused`.
85002
  simdjson_unused bool has_value;
85003
  SIMDJSON_TRY( iter.start_array().get(has_value) );
85004
  return array(iter);
85005
}
85006
simdjson_inline simdjson_result<array> array::start_root(value_iterator &iter) noexcept {
85007
  simdjson_unused bool has_value;
85008
  SIMDJSON_TRY( iter.start_root_array().get(has_value) );
85009
  return array(iter);
85010
}
85011
simdjson_inline simdjson_result<array> array::started(value_iterator &iter) noexcept {
85012
  bool has_value;
85013
  SIMDJSON_TRY(iter.started_array().get(has_value));
85014
  return array(iter);
85015
}
85016
85017
simdjson_inline simdjson_result<array_iterator> array::begin() noexcept {
85018
#if SIMDJSON_DEVELOPMENT_CHECKS
85019
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
85020
#endif
85021
  return array_iterator(iter);
85022
}
85023
simdjson_inline simdjson_result<array_iterator> array::end() noexcept {
85024
  return array_iterator(iter);
85025
}
85026
simdjson_inline error_code array::consume() noexcept {
85027
  auto error = iter.json_iter().skip_child(iter.depth()-1);
85028
  if(error) { iter.abandon(); }
85029
  return error;
85030
}
85031
85032
simdjson_inline simdjson_result<std::string_view> array::raw_json() noexcept {
85033
  const uint8_t * starting_point{iter.peek_start()};
85034
  auto error = consume();
85035
  if(error) { return error; }
85036
  // After 'consume()', we could be left pointing just beyond the document, but that
85037
  // is ok because we are not going to dereference the final pointer position, we just
85038
  // use it to compute the length in bytes.
85039
  const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
85040
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
85041
}
85042
85043
SIMDJSON_PUSH_DISABLE_WARNINGS
85044
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
85045
simdjson_inline simdjson_result<size_t> array::count_elements() & noexcept {
85046
  size_t count{0};
85047
  // Important: we do not consume any of the values.
85048
  for(simdjson_unused auto v : *this) { count++; }
85049
  // The above loop will always succeed, but we want to report errors.
85050
  if(iter.error()) { return iter.error(); }
85051
  // We need to move back at the start because we expect users to iterate through
85052
  // the array after counting the number of elements.
85053
  iter.reset_array();
85054
  return count;
85055
}
85056
SIMDJSON_POP_DISABLE_WARNINGS
85057
85058
simdjson_inline simdjson_result<bool> array::is_empty() & noexcept {
85059
  bool is_not_empty;
85060
  auto error = iter.reset_array().get(is_not_empty);
85061
  if(error) { return error; }
85062
  return !is_not_empty;
85063
}
85064
85065
inline simdjson_result<bool> array::reset() & noexcept {
85066
  return iter.reset_array();
85067
}
85068
85069
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
85070
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
85071
  json_pointer = json_pointer.substr(1);
85072
  // - means "the append position" or "the element after the end of the array"
85073
  // We don't support this, because we're returning a real element, not a position.
85074
  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
85075
85076
  // Read the array index
85077
  size_t array_index = 0;
85078
  size_t i;
85079
  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
85080
    uint8_t digit = uint8_t(json_pointer[i] - '0');
85081
    // Check for non-digit in array index. If it's there, we're trying to get a field in an object
85082
    if (digit > 9) { return INCORRECT_TYPE; }
85083
    array_index = array_index*10 + digit;
85084
  }
85085
85086
  // 0 followed by other digits is invalid
85087
  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
85088
85089
  // Empty string is invalid; so is a "/" with no digits before it
85090
  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
85091
  // Get the child
85092
  auto child = at(array_index);
85093
  // If there is an error, it ends here
85094
  if(child.error()) {
85095
    return child;
85096
  }
85097
85098
  // If there is a /, we're not done yet, call recursively.
85099
  if (i < json_pointer.length()) {
85100
    child = child.at_pointer(json_pointer.substr(i));
85101
  }
85102
  return child;
85103
}
85104
85105
inline std::string json_path_to_pointer_conversion(std::string_view json_path) {
85106
  if (json_path.empty() || (json_path.front() != '.' &&
85107
      json_path.front() != '[')) {
85108
    return "-1"; // This is just a sentinel value, the caller should check for this and return an error.
85109
  }
85110
85111
  std::string result;
85112
  // Reserve space to reduce allocations, adjusting for potential increases due
85113
  // to escaping.
85114
  result.reserve(json_path.size() * 2);
85115
85116
  size_t i = 0;
85117
85118
  while (i < json_path.length()) {
85119
    if (json_path[i] == '.') {
85120
      result += '/';
85121
    } else if (json_path[i] == '[') {
85122
      result += '/';
85123
      ++i; // Move past the '['
85124
      while (i < json_path.length() && json_path[i] != ']') {
85125
          if (json_path[i] == '~') {
85126
            result += "~0";
85127
          } else if (json_path[i] == '/') {
85128
            result += "~1";
85129
          } else {
85130
            result += json_path[i];
85131
          }
85132
          ++i;
85133
      }
85134
      if (i == json_path.length() || json_path[i] != ']') {
85135
          return "-1"; // Using sentinel value that will be handled as an error by the caller.
85136
      }
85137
    } else {
85138
      if (json_path[i] == '~') {
85139
          result += "~0";
85140
      } else if (json_path[i] == '/') {
85141
          result += "~1";
85142
      } else {
85143
          result += json_path[i];
85144
      }
85145
    }
85146
    ++i;
85147
  }
85148
85149
  return result;
85150
}
85151
85152
inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept {
85153
  auto json_pointer = json_path_to_pointer_conversion(json_path);
85154
  if (json_pointer == "-1") { return INVALID_JSON_POINTER; }
85155
  return at_pointer(json_pointer);
85156
}
85157
85158
simdjson_inline simdjson_result<value> array::at(size_t index) noexcept {
85159
  size_t i = 0;
85160
  for (auto value : *this) {
85161
    if (i == index) { return value; }
85162
    i++;
85163
  }
85164
  return INDEX_OUT_OF_BOUNDS;
85165
}
85166
85167
} // namespace ondemand
85168
} // namespace westmere
85169
} // namespace simdjson
85170
85171
namespace simdjson {
85172
85173
simdjson_inline simdjson_result<westmere::ondemand::array>::simdjson_result(
85174
  westmere::ondemand::array &&value
85175
) noexcept
85176
  : implementation_simdjson_result_base<westmere::ondemand::array>(
85177
      std::forward<westmere::ondemand::array>(value)
85178
    )
85179
{
85180
}
85181
simdjson_inline simdjson_result<westmere::ondemand::array>::simdjson_result(
85182
  error_code error
85183
) noexcept
85184
  : implementation_simdjson_result_base<westmere::ondemand::array>(error)
85185
{
85186
}
85187
85188
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::array>::begin() noexcept {
85189
  if (error()) { return error(); }
85190
  return first.begin();
85191
}
85192
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::array>::end() noexcept {
85193
  if (error()) { return error(); }
85194
  return first.end();
85195
}
85196
simdjson_inline  simdjson_result<size_t> simdjson_result<westmere::ondemand::array>::count_elements() & noexcept {
85197
  if (error()) { return error(); }
85198
  return first.count_elements();
85199
}
85200
simdjson_inline  simdjson_result<bool> simdjson_result<westmere::ondemand::array>::is_empty() & noexcept {
85201
  if (error()) { return error(); }
85202
  return first.is_empty();
85203
}
85204
simdjson_inline  simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::array>::at(size_t index) noexcept {
85205
  if (error()) { return error(); }
85206
  return first.at(index);
85207
}
85208
simdjson_inline  simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::array>::at_pointer(std::string_view json_pointer) noexcept {
85209
  if (error()) { return error(); }
85210
  return first.at_pointer(json_pointer);
85211
}
85212
simdjson_inline  simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::array>::at_path(std::string_view json_path) noexcept {
85213
  if (error()) { return error(); }
85214
  return first.at_path(json_path);
85215
}
85216
simdjson_inline  simdjson_result<std::string_view> simdjson_result<westmere::ondemand::array>::raw_json() noexcept {
85217
  if (error()) { return error(); }
85218
  return first.raw_json();
85219
}
85220
} // namespace simdjson
85221
85222
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
85223
/* end file simdjson/generic/ondemand/array-inl.h for westmere */
85224
/* including simdjson/generic/ondemand/array_iterator-inl.h for westmere: #include "simdjson/generic/ondemand/array_iterator-inl.h" */
85225
/* begin file simdjson/generic/ondemand/array_iterator-inl.h for westmere */
85226
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
85227
85228
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
85229
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H */
85230
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
85231
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
85232
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
85233
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
85234
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
85235
85236
namespace simdjson {
85237
namespace westmere {
85238
namespace ondemand {
85239
85240
simdjson_inline array_iterator::array_iterator(const value_iterator &_iter) noexcept
85241
  : iter{_iter}
85242
{}
85243
85244
simdjson_inline simdjson_result<value> array_iterator::operator*() noexcept {
85245
  if (iter.error()) { iter.abandon(); return iter.error(); }
85246
  return value(iter.child());
85247
}
85248
simdjson_inline bool array_iterator::operator==(const array_iterator &other) const noexcept {
85249
  return !(*this != other);
85250
}
85251
simdjson_inline bool array_iterator::operator!=(const array_iterator &) const noexcept {
85252
  return iter.is_open();
85253
}
85254
simdjson_inline array_iterator &array_iterator::operator++() noexcept {
85255
  error_code error;
85256
  // PERF NOTE this is a safety rail ... users should exit loops as soon as they receive an error, so we'll never get here.
85257
  // However, it does not seem to make a perf difference, so we add it out of an abundance of caution.
85258
  if (( error = iter.error() )) { return *this; }
85259
  if (( error = iter.skip_child() )) { return *this; }
85260
  if (( error = iter.has_next_element().error() )) { return *this; }
85261
  return *this;
85262
}
85263
85264
} // namespace ondemand
85265
} // namespace westmere
85266
} // namespace simdjson
85267
85268
namespace simdjson {
85269
85270
simdjson_inline simdjson_result<westmere::ondemand::array_iterator>::simdjson_result(
85271
  westmere::ondemand::array_iterator &&value
85272
) noexcept
85273
  : westmere::implementation_simdjson_result_base<westmere::ondemand::array_iterator>(std::forward<westmere::ondemand::array_iterator>(value))
85274
{
85275
  first.iter.assert_is_valid();
85276
}
85277
simdjson_inline simdjson_result<westmere::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
85278
  : westmere::implementation_simdjson_result_base<westmere::ondemand::array_iterator>({}, error)
85279
{
85280
}
85281
85282
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::array_iterator>::operator*() noexcept {
85283
  if (error()) { return error(); }
85284
  return *first;
85285
}
85286
simdjson_inline bool simdjson_result<westmere::ondemand::array_iterator>::operator==(const simdjson_result<westmere::ondemand::array_iterator> &other) const noexcept {
85287
  if (!first.iter.is_valid()) { return !error(); }
85288
  return first == other.first;
85289
}
85290
simdjson_inline bool simdjson_result<westmere::ondemand::array_iterator>::operator!=(const simdjson_result<westmere::ondemand::array_iterator> &other) const noexcept {
85291
  if (!first.iter.is_valid()) { return error(); }
85292
  return first != other.first;
85293
}
85294
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> &simdjson_result<westmere::ondemand::array_iterator>::operator++() noexcept {
85295
  // Clear the error if there is one, so we don't yield it twice
85296
  if (error()) { second = SUCCESS; return *this; }
85297
  ++(first);
85298
  return *this;
85299
}
85300
85301
} // namespace simdjson
85302
85303
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
85304
/* end file simdjson/generic/ondemand/array_iterator-inl.h for westmere */
85305
/* including simdjson/generic/ondemand/document-inl.h for westmere: #include "simdjson/generic/ondemand/document-inl.h" */
85306
/* begin file simdjson/generic/ondemand/document-inl.h for westmere */
85307
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
85308
85309
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
85310
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */
85311
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
85312
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */
85313
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
85314
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */
85315
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
85316
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
85317
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
85318
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
85319
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */
85320
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
85321
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
85322
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
85323
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
85324
85325
namespace simdjson {
85326
namespace westmere {
85327
namespace ondemand {
85328
85329
simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept
85330
  : iter{std::forward<json_iterator>(_iter)}
85331
{
85332
  logger::log_start_value(iter, "document");
85333
}
85334
85335
simdjson_inline document document::start(json_iterator &&iter) noexcept {
85336
  return document(std::forward<json_iterator>(iter));
85337
}
85338
85339
inline void document::rewind() noexcept {
85340
  iter.rewind();
85341
}
85342
85343
inline std::string document::to_debug_string() noexcept {
85344
  return iter.to_string();
85345
}
85346
85347
inline simdjson_result<const char *> document::current_location() const noexcept {
85348
  return iter.current_location();
85349
}
85350
85351
inline int32_t document::current_depth() const noexcept {
85352
  return iter.depth();
85353
}
85354
85355
inline bool document::at_end() const noexcept {
85356
  return iter.at_end();
85357
}
85358
85359
85360
inline bool document::is_alive() noexcept {
85361
  return iter.is_alive();
85362
}
85363
simdjson_inline value_iterator document::resume_value_iterator() noexcept {
85364
  return value_iterator(&iter, 1, iter.root_position());
85365
}
85366
simdjson_inline value_iterator document::get_root_value_iterator() noexcept {
85367
  return resume_value_iterator();
85368
}
85369
simdjson_inline simdjson_result<object> document::start_or_resume_object() noexcept {
85370
  if (iter.at_root()) {
85371
    return get_object();
85372
  } else {
85373
    return object::resume(resume_value_iterator());
85374
  }
85375
}
85376
simdjson_inline simdjson_result<value> document::get_value() noexcept {
85377
  // Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
85378
  // gets called.
85379
85380
  // It is the convention throughout the code that  the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether
85381
  // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error.
85382
#if SIMDJSON_DEVELOPMENT_CHECKS
85383
  if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; }
85384
#endif
85385
  // assert_at_root() serves two purposes: in Debug mode, whether or not
85386
  // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of
85387
  // the document (this will typically be redundant). In release mode, it generates
85388
  // SIMDJSON_ASSUME statements to allow the compiler to make assumptions.
85389
  iter.assert_at_root();
85390
  switch (*iter.peek()) {
85391
    case '[': {
85392
      // The following lines check that the document ends with ].
85393
      auto value_iterator = get_root_value_iterator();
85394
      auto error = value_iterator.check_root_array();
85395
      if(error) { return error; }
85396
      return value(get_root_value_iterator());
85397
    }
85398
    case '{': {
85399
      // The following lines would check that the document ends with }.
85400
      auto value_iterator = get_root_value_iterator();
85401
      auto error = value_iterator.check_root_object();
85402
      if(error) { return error; }
85403
      return value(get_root_value_iterator());
85404
    }
85405
    default:
85406
      // Unfortunately, scalar documents are a special case in simdjson and they cannot
85407
      // be safely converted to value instances.
85408
      return SCALAR_DOCUMENT_AS_VALUE;
85409
  }
85410
}
85411
simdjson_inline simdjson_result<array> document::get_array() & noexcept {
85412
  auto value = get_root_value_iterator();
85413
  return array::start_root(value);
85414
}
85415
simdjson_inline simdjson_result<object> document::get_object() & noexcept {
85416
  auto value = get_root_value_iterator();
85417
  return object::start_root(value);
85418
}
85419
85420
/**
85421
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
85422
 * give an error, so we check for trailing content. We want to disallow trailing
85423
 * content.
85424
 * Thus, in several implementations below, we pass a 'true' parameter value to
85425
 * a get_root_value_iterator() method: this indicates that we disallow trailing content.
85426
 */
85427
85428
simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
85429
  return get_root_value_iterator().get_root_uint64(true);
85430
}
85431
simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
85432
  return get_root_value_iterator().get_root_uint64_in_string(true);
85433
}
85434
simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
85435
  return get_root_value_iterator().get_root_int64(true);
85436
}
85437
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
85438
  return get_root_value_iterator().get_root_int64_in_string(true);
85439
}
85440
simdjson_inline simdjson_result<double> document::get_double() noexcept {
85441
  return get_root_value_iterator().get_root_double(true);
85442
}
85443
simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
85444
  return get_root_value_iterator().get_root_double_in_string(true);
85445
}
85446
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
85447
  return get_root_value_iterator().get_root_string(true, allow_replacement);
85448
}
85449
template <typename string_type>
85450
simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
85451
  return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
85452
}
85453
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
85454
  return get_root_value_iterator().get_root_wobbly_string(true);
85455
}
85456
simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
85457
  return get_root_value_iterator().get_root_raw_json_string(true);
85458
}
85459
simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
85460
  return get_root_value_iterator().get_root_bool(true);
85461
}
85462
simdjson_inline simdjson_result<bool> document::is_null() noexcept {
85463
  return get_root_value_iterator().is_root_null(true);
85464
}
85465
85466
template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
85467
template<> simdjson_inline simdjson_result<object> document::get() & noexcept { return get_object(); }
85468
template<> simdjson_inline simdjson_result<raw_json_string> document::get() & noexcept { return get_raw_json_string(); }
85469
template<> simdjson_inline simdjson_result<std::string_view> document::get() & noexcept { return get_string(false); }
85470
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
85471
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
85472
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
85473
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
85474
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
85475
85476
template<> simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
85477
template<> simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
85478
template<> simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
85479
template<> simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
85480
template<> simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
85481
template<> simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
85482
template<> simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
85483
85484
template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
85485
  return get<T>().get(out);
85486
}
85487
template<typename T> simdjson_inline error_code document::get(T &out) && noexcept {
85488
  return std::forward<document>(*this).get<T>().get(out);
85489
}
85490
85491
#if SIMDJSON_EXCEPTIONS
85492
template <class T>
85493
simdjson_inline document::operator T() noexcept(false) { return get<T>(); }
85494
simdjson_inline document::operator array() & noexcept(false) { return get_array(); }
85495
simdjson_inline document::operator object() & noexcept(false) { return get_object(); }
85496
simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); }
85497
simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); }
85498
simdjson_inline document::operator double() noexcept(false) { return get_double(); }
85499
simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); }
85500
simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
85501
simdjson_inline document::operator bool() noexcept(false) { return get_bool(); }
85502
simdjson_inline document::operator value() noexcept(false) { return get_value(); }
85503
85504
#endif
85505
simdjson_inline simdjson_result<size_t> document::count_elements() & noexcept {
85506
  auto a = get_array();
85507
  simdjson_result<size_t> answer = a.count_elements();
85508
  /* If there was an array, we are now left pointing at its first element. */
85509
  if(answer.error() == SUCCESS) { rewind(); }
85510
  return answer;
85511
}
85512
simdjson_inline simdjson_result<size_t> document::count_fields() & noexcept {
85513
  auto a = get_object();
85514
  simdjson_result<size_t> answer = a.count_fields();
85515
  /* If there was an object, we are now left pointing at its first element. */
85516
  if(answer.error() == SUCCESS) { rewind(); }
85517
  return answer;
85518
}
85519
simdjson_inline simdjson_result<value> document::at(size_t index) & noexcept {
85520
  auto a = get_array();
85521
  return a.at(index);
85522
}
85523
simdjson_inline simdjson_result<array_iterator> document::begin() & noexcept {
85524
  return get_array().begin();
85525
}
85526
simdjson_inline simdjson_result<array_iterator> document::end() & noexcept {
85527
  return {};
85528
}
85529
85530
simdjson_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
85531
  return start_or_resume_object().find_field(key);
85532
}
85533
simdjson_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
85534
  return start_or_resume_object().find_field(key);
85535
}
85536
simdjson_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
85537
  return start_or_resume_object().find_field_unordered(key);
85538
}
85539
simdjson_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
85540
  return start_or_resume_object().find_field_unordered(key);
85541
}
85542
simdjson_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
85543
  return start_or_resume_object()[key];
85544
}
85545
simdjson_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
85546
  return start_or_resume_object()[key];
85547
}
85548
85549
simdjson_inline error_code document::consume() noexcept {
85550
  auto error = iter.skip_child(0);
85551
  if(error) { iter.abandon(); }
85552
  return error;
85553
}
85554
85555
simdjson_inline simdjson_result<std::string_view> document::raw_json() noexcept {
85556
  auto _iter = get_root_value_iterator();
85557
  const uint8_t * starting_point{_iter.peek_start()};
85558
  auto error = consume();
85559
  if(error) { return error; }
85560
  // After 'consume()', we could be left pointing just beyond the document, but that
85561
  // is ok because we are not going to dereference the final pointer position, we just
85562
  // use it to compute the length in bytes.
85563
  const uint8_t * final_point{iter.unsafe_pointer()};
85564
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
85565
}
85566
85567
simdjson_inline simdjson_result<json_type> document::type() noexcept {
85568
  return get_root_value_iterator().type();
85569
}
85570
85571
simdjson_inline simdjson_result<bool> document::is_scalar() noexcept {
85572
  json_type this_type;
85573
  auto error = type().get(this_type);
85574
  if(error) { return error; }
85575
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
85576
}
85577
85578
simdjson_inline simdjson_result<bool> document::is_string() noexcept {
85579
  json_type this_type;
85580
  auto error = type().get(this_type);
85581
  if(error) { return error; }
85582
  return (this_type == json_type::string);
85583
}
85584
85585
simdjson_inline bool document::is_negative() noexcept {
85586
  return get_root_value_iterator().is_root_negative();
85587
}
85588
85589
simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
85590
  return get_root_value_iterator().is_root_integer(true);
85591
}
85592
85593
simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
85594
  return get_root_value_iterator().get_root_number_type(true);
85595
}
85596
85597
simdjson_inline simdjson_result<number> document::get_number() noexcept {
85598
  return get_root_value_iterator().get_root_number(true);
85599
}
85600
85601
85602
simdjson_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
85603
  auto _iter = get_root_value_iterator();
85604
  return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_root_length());
85605
}
85606
85607
simdjson_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
85608
  rewind(); // Rewind the document each time at_pointer is called
85609
  if (json_pointer.empty()) {
85610
    return this->get_value();
85611
  }
85612
  json_type t;
85613
  SIMDJSON_TRY(type().get(t));
85614
  switch (t)
85615
  {
85616
    case json_type::array:
85617
      return (*this).get_array().at_pointer(json_pointer);
85618
    case json_type::object:
85619
      return (*this).get_object().at_pointer(json_pointer);
85620
    default:
85621
      return INVALID_JSON_POINTER;
85622
  }
85623
}
85624
85625
simdjson_inline simdjson_result<value> document::at_path(std::string_view json_path) noexcept {
85626
  rewind(); // Rewind the document each time at_pointer is called
85627
  if (json_path.empty()) {
85628
      return this->get_value();
85629
  }
85630
  json_type t;
85631
  SIMDJSON_TRY(type().get(t));
85632
  switch (t) {
85633
  case json_type::array:
85634
      return (*this).get_array().at_path(json_path);
85635
  case json_type::object:
85636
      return (*this).get_object().at_path(json_path);
85637
  default:
85638
      return INVALID_JSON_POINTER;
85639
  }
85640
}
85641
85642
} // namespace ondemand
85643
} // namespace westmere
85644
} // namespace simdjson
85645
85646
namespace simdjson {
85647
85648
simdjson_inline simdjson_result<westmere::ondemand::document>::simdjson_result(
85649
  westmere::ondemand::document &&value
85650
) noexcept :
85651
    implementation_simdjson_result_base<westmere::ondemand::document>(
85652
      std::forward<westmere::ondemand::document>(value)
85653
    )
85654
{
85655
}
85656
simdjson_inline simdjson_result<westmere::ondemand::document>::simdjson_result(
85657
  error_code error
85658
) noexcept :
85659
    implementation_simdjson_result_base<westmere::ondemand::document>(
85660
      error
85661
    )
85662
{
85663
}
85664
simdjson_inline simdjson_result<size_t> simdjson_result<westmere::ondemand::document>::count_elements() & noexcept {
85665
  if (error()) { return error(); }
85666
  return first.count_elements();
85667
}
85668
simdjson_inline simdjson_result<size_t> simdjson_result<westmere::ondemand::document>::count_fields() & noexcept {
85669
  if (error()) { return error(); }
85670
  return first.count_fields();
85671
}
85672
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::at(size_t index) & noexcept {
85673
  if (error()) { return error(); }
85674
  return first.at(index);
85675
}
85676
simdjson_inline error_code simdjson_result<westmere::ondemand::document>::rewind() noexcept {
85677
  if (error()) { return error(); }
85678
  first.rewind();
85679
  return SUCCESS;
85680
}
85681
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::document>::begin() & noexcept {
85682
  if (error()) { return error(); }
85683
  return first.begin();
85684
}
85685
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::document>::end() & noexcept {
85686
  return {};
85687
}
85688
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
85689
  if (error()) { return error(); }
85690
  return first.find_field_unordered(key);
85691
}
85692
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::find_field_unordered(const char *key) & noexcept {
85693
  if (error()) { return error(); }
85694
  return first.find_field_unordered(key);
85695
}
85696
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::operator[](std::string_view key) & noexcept {
85697
  if (error()) { return error(); }
85698
  return first[key];
85699
}
85700
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::operator[](const char *key) & noexcept {
85701
  if (error()) { return error(); }
85702
  return first[key];
85703
}
85704
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::find_field(std::string_view key) & noexcept {
85705
  if (error()) { return error(); }
85706
  return first.find_field(key);
85707
}
85708
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::find_field(const char *key) & noexcept {
85709
  if (error()) { return error(); }
85710
  return first.find_field(key);
85711
}
85712
simdjson_inline simdjson_result<westmere::ondemand::array> simdjson_result<westmere::ondemand::document>::get_array() & noexcept {
85713
  if (error()) { return error(); }
85714
  return first.get_array();
85715
}
85716
simdjson_inline simdjson_result<westmere::ondemand::object> simdjson_result<westmere::ondemand::document>::get_object() & noexcept {
85717
  if (error()) { return error(); }
85718
  return first.get_object();
85719
}
85720
simdjson_inline simdjson_result<uint64_t> simdjson_result<westmere::ondemand::document>::get_uint64() noexcept {
85721
  if (error()) { return error(); }
85722
  return first.get_uint64();
85723
}
85724
simdjson_inline simdjson_result<uint64_t> simdjson_result<westmere::ondemand::document>::get_uint64_in_string() noexcept {
85725
  if (error()) { return error(); }
85726
  return first.get_uint64_in_string();
85727
}
85728
simdjson_inline simdjson_result<int64_t> simdjson_result<westmere::ondemand::document>::get_int64() noexcept {
85729
  if (error()) { return error(); }
85730
  return first.get_int64();
85731
}
85732
simdjson_inline simdjson_result<int64_t> simdjson_result<westmere::ondemand::document>::get_int64_in_string() noexcept {
85733
  if (error()) { return error(); }
85734
  return first.get_int64_in_string();
85735
}
85736
simdjson_inline simdjson_result<double> simdjson_result<westmere::ondemand::document>::get_double() noexcept {
85737
  if (error()) { return error(); }
85738
  return first.get_double();
85739
}
85740
simdjson_inline simdjson_result<double> simdjson_result<westmere::ondemand::document>::get_double_in_string() noexcept {
85741
  if (error()) { return error(); }
85742
  return first.get_double_in_string();
85743
}
85744
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::document>::get_string(bool allow_replacement) noexcept {
85745
  if (error()) { return error(); }
85746
  return first.get_string(allow_replacement);
85747
}
85748
template <typename string_type>
85749
simdjson_inline error_code simdjson_result<westmere::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
85750
  if (error()) { return error(); }
85751
  return first.get_string(receiver, allow_replacement);
85752
}
85753
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::document>::get_wobbly_string() noexcept {
85754
  if (error()) { return error(); }
85755
  return first.get_wobbly_string();
85756
}
85757
simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> simdjson_result<westmere::ondemand::document>::get_raw_json_string() noexcept {
85758
  if (error()) { return error(); }
85759
  return first.get_raw_json_string();
85760
}
85761
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document>::get_bool() noexcept {
85762
  if (error()) { return error(); }
85763
  return first.get_bool();
85764
}
85765
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::get_value() noexcept {
85766
  if (error()) { return error(); }
85767
  return first.get_value();
85768
}
85769
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document>::is_null() noexcept {
85770
  if (error()) { return error(); }
85771
  return first.is_null();
85772
}
85773
85774
template<typename T>
85775
simdjson_inline simdjson_result<T> simdjson_result<westmere::ondemand::document>::get() & noexcept {
85776
  if (error()) { return error(); }
85777
  return first.get<T>();
85778
}
85779
template<typename T>
85780
simdjson_inline simdjson_result<T> simdjson_result<westmere::ondemand::document>::get() && noexcept {
85781
  if (error()) { return error(); }
85782
  return std::forward<westmere::ondemand::document>(first).get<T>();
85783
}
85784
template<typename T>
85785
simdjson_inline error_code simdjson_result<westmere::ondemand::document>::get(T &out) & noexcept {
85786
  if (error()) { return error(); }
85787
  return first.get<T>(out);
85788
}
85789
template<typename T>
85790
simdjson_inline error_code simdjson_result<westmere::ondemand::document>::get(T &out) && noexcept {
85791
  if (error()) { return error(); }
85792
  return std::forward<westmere::ondemand::document>(first).get<T>(out);
85793
}
85794
85795
template<> simdjson_inline simdjson_result<westmere::ondemand::document> simdjson_result<westmere::ondemand::document>::get<westmere::ondemand::document>() & noexcept = delete;
85796
template<> simdjson_inline simdjson_result<westmere::ondemand::document> simdjson_result<westmere::ondemand::document>::get<westmere::ondemand::document>() && noexcept {
85797
  if (error()) { return error(); }
85798
  return std::forward<westmere::ondemand::document>(first);
85799
}
85800
template<> simdjson_inline error_code simdjson_result<westmere::ondemand::document>::get<westmere::ondemand::document>(westmere::ondemand::document &out) & noexcept = delete;
85801
template<> simdjson_inline error_code simdjson_result<westmere::ondemand::document>::get<westmere::ondemand::document>(westmere::ondemand::document &out) && noexcept {
85802
  if (error()) { return error(); }
85803
  out = std::forward<westmere::ondemand::document>(first);
85804
  return SUCCESS;
85805
}
85806
85807
simdjson_inline simdjson_result<westmere::ondemand::json_type> simdjson_result<westmere::ondemand::document>::type() noexcept {
85808
  if (error()) { return error(); }
85809
  return first.type();
85810
}
85811
85812
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document>::is_scalar() noexcept {
85813
  if (error()) { return error(); }
85814
  return first.is_scalar();
85815
}
85816
85817
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document>::is_string() noexcept {
85818
  if (error()) { return error(); }
85819
  return first.is_string();
85820
}
85821
85822
simdjson_inline bool simdjson_result<westmere::ondemand::document>::is_negative() noexcept {
85823
  if (error()) { return error(); }
85824
  return first.is_negative();
85825
}
85826
85827
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document>::is_integer() noexcept {
85828
  if (error()) { return error(); }
85829
  return first.is_integer();
85830
}
85831
85832
simdjson_inline simdjson_result<westmere::number_type> simdjson_result<westmere::ondemand::document>::get_number_type() noexcept {
85833
  if (error()) { return error(); }
85834
  return first.get_number_type();
85835
}
85836
85837
simdjson_inline simdjson_result<westmere::ondemand::number> simdjson_result<westmere::ondemand::document>::get_number() noexcept {
85838
  if (error()) { return error(); }
85839
  return first.get_number();
85840
}
85841
85842
85843
#if SIMDJSON_EXCEPTIONS
85844
template <class T, typename std::enable_if<std::is_same<T, westmere::ondemand::document>::value == false>::type>
85845
simdjson_inline simdjson_result<westmere::ondemand::document>::operator T() noexcept(false) {
85846
  if (error()) { throw simdjson_error(error()); }
85847
  return first;
85848
}
85849
simdjson_inline simdjson_result<westmere::ondemand::document>::operator westmere::ondemand::array() & noexcept(false) {
85850
  if (error()) { throw simdjson_error(error()); }
85851
  return first;
85852
}
85853
simdjson_inline simdjson_result<westmere::ondemand::document>::operator westmere::ondemand::object() & noexcept(false) {
85854
  if (error()) { throw simdjson_error(error()); }
85855
  return first;
85856
}
85857
simdjson_inline simdjson_result<westmere::ondemand::document>::operator uint64_t() noexcept(false) {
85858
  if (error()) { throw simdjson_error(error()); }
85859
  return first;
85860
}
85861
simdjson_inline simdjson_result<westmere::ondemand::document>::operator int64_t() noexcept(false) {
85862
  if (error()) { throw simdjson_error(error()); }
85863
  return first;
85864
}
85865
simdjson_inline simdjson_result<westmere::ondemand::document>::operator double() noexcept(false) {
85866
  if (error()) { throw simdjson_error(error()); }
85867
  return first;
85868
}
85869
simdjson_inline simdjson_result<westmere::ondemand::document>::operator std::string_view() noexcept(false) {
85870
  if (error()) { throw simdjson_error(error()); }
85871
  return first;
85872
}
85873
simdjson_inline simdjson_result<westmere::ondemand::document>::operator westmere::ondemand::raw_json_string() noexcept(false) {
85874
  if (error()) { throw simdjson_error(error()); }
85875
  return first;
85876
}
85877
simdjson_inline simdjson_result<westmere::ondemand::document>::operator bool() noexcept(false) {
85878
  if (error()) { throw simdjson_error(error()); }
85879
  return first;
85880
}
85881
simdjson_inline simdjson_result<westmere::ondemand::document>::operator westmere::ondemand::value() noexcept(false) {
85882
  if (error()) { throw simdjson_error(error()); }
85883
  return first;
85884
}
85885
#endif
85886
85887
85888
simdjson_inline simdjson_result<const char *> simdjson_result<westmere::ondemand::document>::current_location() noexcept {
85889
  if (error()) { return error(); }
85890
  return first.current_location();
85891
}
85892
85893
simdjson_inline bool simdjson_result<westmere::ondemand::document>::at_end() const noexcept {
85894
  if (error()) { return error(); }
85895
  return first.at_end();
85896
}
85897
85898
85899
simdjson_inline int32_t simdjson_result<westmere::ondemand::document>::current_depth() const noexcept {
85900
  if (error()) { return error(); }
85901
  return first.current_depth();
85902
}
85903
85904
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::document>::raw_json_token() noexcept {
85905
  if (error()) { return error(); }
85906
  return first.raw_json_token();
85907
}
85908
85909
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::at_pointer(std::string_view json_pointer) noexcept {
85910
  if (error()) { return error(); }
85911
  return first.at_pointer(json_pointer);
85912
}
85913
85914
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document>::at_path(std::string_view json_path) noexcept {
85915
  if (error()) { return error(); }
85916
  return first.at_path(json_path);
85917
}
85918
85919
} // namespace simdjson
85920
85921
85922
namespace simdjson {
85923
namespace westmere {
85924
namespace ondemand {
85925
85926
simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {}
85927
simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
85928
simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
85929
simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
85930
simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
85931
/**
85932
 * The document_reference instances are used primarily/solely for streams of JSON
85933
 * documents.
85934
 * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
85935
 * give an error, so we check for trailing content.
85936
 *
85937
 * However, for streams of JSON documents, we want to be able to start from
85938
 * "321" "321" "321"
85939
 * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
85940
 * successfully each time.
85941
 *
85942
 * To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
85943
 * this indicates that we allow trailing content.
85944
 */
85945
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
85946
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
85947
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
85948
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
85949
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
85950
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
85951
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
85952
template <typename string_type>
85953
simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
85954
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
85955
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
85956
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
85957
simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
85958
simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
85959
template<> simdjson_inline simdjson_result<array> document_reference::get() & noexcept { return get_array(); }
85960
template<> simdjson_inline simdjson_result<object> document_reference::get() & noexcept { return get_object(); }
85961
template<> simdjson_inline simdjson_result<raw_json_string> document_reference::get() & noexcept { return get_raw_json_string(); }
85962
template<> simdjson_inline simdjson_result<std::string_view> document_reference::get() & noexcept { return get_string(false); }
85963
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
85964
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
85965
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
85966
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
85967
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
85968
#if SIMDJSON_EXCEPTIONS
85969
template <class T>
85970
simdjson_inline document_reference::operator T() noexcept(false) { return get<T>(); }
85971
simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
85972
simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
85973
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
85974
simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
85975
simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
85976
simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
85977
simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
85978
simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
85979
simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
85980
#endif
85981
simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
85982
simdjson_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
85983
simdjson_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
85984
simdjson_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
85985
simdjson_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
85986
simdjson_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
85987
simdjson_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
85988
simdjson_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
85989
simdjson_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
85990
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
85991
simdjson_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
85992
simdjson_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
85993
simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
85994
simdjson_inline simdjson_result<bool> document_reference::is_string() noexcept { return doc->is_string(); }
85995
simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
85996
simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
85997
simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
85998
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
85999
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
86000
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
86001
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
86002
simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
86003
simdjson_inline simdjson_result<value> document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); }
86004
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
86005
simdjson_inline document_reference::operator document&() const noexcept { return *doc; }
86006
86007
} // namespace ondemand
86008
} // namespace westmere
86009
} // namespace simdjson
86010
86011
86012
86013
namespace simdjson {
86014
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::simdjson_result(westmere::ondemand::document_reference value, error_code error)
86015
  noexcept : implementation_simdjson_result_base<westmere::ondemand::document_reference>(std::forward<westmere::ondemand::document_reference>(value), error) {}
86016
86017
86018
simdjson_inline simdjson_result<size_t> simdjson_result<westmere::ondemand::document_reference>::count_elements() & noexcept {
86019
  if (error()) { return error(); }
86020
  return first.count_elements();
86021
}
86022
simdjson_inline simdjson_result<size_t> simdjson_result<westmere::ondemand::document_reference>::count_fields() & noexcept {
86023
  if (error()) { return error(); }
86024
  return first.count_fields();
86025
}
86026
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::at(size_t index) & noexcept {
86027
  if (error()) { return error(); }
86028
  return first.at(index);
86029
}
86030
simdjson_inline error_code simdjson_result<westmere::ondemand::document_reference>::rewind() noexcept {
86031
  if (error()) { return error(); }
86032
  first.rewind();
86033
  return SUCCESS;
86034
}
86035
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::document_reference>::begin() & noexcept {
86036
  if (error()) { return error(); }
86037
  return first.begin();
86038
}
86039
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::document_reference>::end() & noexcept {
86040
  return {};
86041
}
86042
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
86043
  if (error()) { return error(); }
86044
  return first.find_field_unordered(key);
86045
}
86046
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
86047
  if (error()) { return error(); }
86048
  return first.find_field_unordered(key);
86049
}
86050
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
86051
  if (error()) { return error(); }
86052
  return first[key];
86053
}
86054
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::operator[](const char *key) & noexcept {
86055
  if (error()) { return error(); }
86056
  return first[key];
86057
}
86058
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
86059
  if (error()) { return error(); }
86060
  return first.find_field(key);
86061
}
86062
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::find_field(const char *key) & noexcept {
86063
  if (error()) { return error(); }
86064
  return first.find_field(key);
86065
}
86066
simdjson_inline simdjson_result<westmere::ondemand::array> simdjson_result<westmere::ondemand::document_reference>::get_array() & noexcept {
86067
  if (error()) { return error(); }
86068
  return first.get_array();
86069
}
86070
simdjson_inline simdjson_result<westmere::ondemand::object> simdjson_result<westmere::ondemand::document_reference>::get_object() & noexcept {
86071
  if (error()) { return error(); }
86072
  return first.get_object();
86073
}
86074
simdjson_inline simdjson_result<uint64_t> simdjson_result<westmere::ondemand::document_reference>::get_uint64() noexcept {
86075
  if (error()) { return error(); }
86076
  return first.get_uint64();
86077
}
86078
simdjson_inline simdjson_result<uint64_t> simdjson_result<westmere::ondemand::document_reference>::get_uint64_in_string() noexcept {
86079
  if (error()) { return error(); }
86080
  return first.get_uint64_in_string();
86081
}
86082
simdjson_inline simdjson_result<int64_t> simdjson_result<westmere::ondemand::document_reference>::get_int64() noexcept {
86083
  if (error()) { return error(); }
86084
  return first.get_int64();
86085
}
86086
simdjson_inline simdjson_result<int64_t> simdjson_result<westmere::ondemand::document_reference>::get_int64_in_string() noexcept {
86087
  if (error()) { return error(); }
86088
  return first.get_int64_in_string();
86089
}
86090
simdjson_inline simdjson_result<double> simdjson_result<westmere::ondemand::document_reference>::get_double() noexcept {
86091
  if (error()) { return error(); }
86092
  return first.get_double();
86093
}
86094
simdjson_inline simdjson_result<double> simdjson_result<westmere::ondemand::document_reference>::get_double_in_string() noexcept {
86095
  if (error()) { return error(); }
86096
  return first.get_double_in_string();
86097
}
86098
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::document_reference>::get_string(bool allow_replacement) noexcept {
86099
  if (error()) { return error(); }
86100
  return first.get_string(allow_replacement);
86101
}
86102
template <typename string_type>
86103
simdjson_inline error_code simdjson_result<westmere::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
86104
  if (error()) { return error(); }
86105
  return first.get_string(receiver, allow_replacement);
86106
}
86107
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::document_reference>::get_wobbly_string() noexcept {
86108
  if (error()) { return error(); }
86109
  return first.get_wobbly_string();
86110
}
86111
simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> simdjson_result<westmere::ondemand::document_reference>::get_raw_json_string() noexcept {
86112
  if (error()) { return error(); }
86113
  return first.get_raw_json_string();
86114
}
86115
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document_reference>::get_bool() noexcept {
86116
  if (error()) { return error(); }
86117
  return first.get_bool();
86118
}
86119
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::get_value() noexcept {
86120
  if (error()) { return error(); }
86121
  return first.get_value();
86122
}
86123
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document_reference>::is_null() noexcept {
86124
  if (error()) { return error(); }
86125
  return first.is_null();
86126
}
86127
simdjson_inline simdjson_result<westmere::ondemand::json_type> simdjson_result<westmere::ondemand::document_reference>::type() noexcept {
86128
  if (error()) { return error(); }
86129
  return first.type();
86130
}
86131
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document_reference>::is_scalar() noexcept {
86132
  if (error()) { return error(); }
86133
  return first.is_scalar();
86134
}
86135
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document_reference>::is_string() noexcept {
86136
  if (error()) { return error(); }
86137
  return first.is_string();
86138
}
86139
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document_reference>::is_negative() noexcept {
86140
  if (error()) { return error(); }
86141
  return first.is_negative();
86142
}
86143
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::document_reference>::is_integer() noexcept {
86144
  if (error()) { return error(); }
86145
  return first.is_integer();
86146
}
86147
simdjson_inline simdjson_result<westmere::number_type> simdjson_result<westmere::ondemand::document_reference>::get_number_type() noexcept {
86148
  if (error()) { return error(); }
86149
  return first.get_number_type();
86150
}
86151
simdjson_inline simdjson_result<westmere::ondemand::number> simdjson_result<westmere::ondemand::document_reference>::get_number() noexcept {
86152
  if (error()) { return error(); }
86153
  return first.get_number();
86154
}
86155
#if SIMDJSON_EXCEPTIONS
86156
template <class T, typename std::enable_if<std::is_same<T, westmere::ondemand::document_reference>::value == false>::type>
86157
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator T() noexcept(false) {
86158
  if (error()) { throw simdjson_error(error()); }
86159
  return first;
86160
}
86161
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator westmere::ondemand::array() & noexcept(false) {
86162
  if (error()) { throw simdjson_error(error()); }
86163
  return first;
86164
}
86165
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator westmere::ondemand::object() & noexcept(false) {
86166
  if (error()) { throw simdjson_error(error()); }
86167
  return first;
86168
}
86169
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator uint64_t() noexcept(false) {
86170
  if (error()) { throw simdjson_error(error()); }
86171
  return first;
86172
}
86173
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator int64_t() noexcept(false) {
86174
  if (error()) { throw simdjson_error(error()); }
86175
  return first;
86176
}
86177
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator double() noexcept(false) {
86178
  if (error()) { throw simdjson_error(error()); }
86179
  return first;
86180
}
86181
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator std::string_view() noexcept(false) {
86182
  if (error()) { throw simdjson_error(error()); }
86183
  return first;
86184
}
86185
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator westmere::ondemand::raw_json_string() noexcept(false) {
86186
  if (error()) { throw simdjson_error(error()); }
86187
  return first;
86188
}
86189
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator bool() noexcept(false) {
86190
  if (error()) { throw simdjson_error(error()); }
86191
  return first;
86192
}
86193
simdjson_inline simdjson_result<westmere::ondemand::document_reference>::operator westmere::ondemand::value() noexcept(false) {
86194
  if (error()) { throw simdjson_error(error()); }
86195
  return first;
86196
}
86197
#endif
86198
86199
simdjson_inline simdjson_result<const char *> simdjson_result<westmere::ondemand::document_reference>::current_location() noexcept {
86200
  if (error()) { return error(); }
86201
  return first.current_location();
86202
}
86203
86204
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::document_reference>::raw_json_token() noexcept {
86205
  if (error()) { return error(); }
86206
  return first.raw_json_token();
86207
}
86208
86209
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
86210
  if (error()) { return error(); }
86211
  return first.at_pointer(json_pointer);
86212
}
86213
86214
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::document_reference>::at_path(std::string_view json_path) noexcept {
86215
  if (error()) {
86216
      return error();
86217
  }
86218
  return first.at_path(json_path);
86219
}
86220
86221
} // namespace simdjson
86222
86223
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
86224
/* end file simdjson/generic/ondemand/document-inl.h for westmere */
86225
/* including simdjson/generic/ondemand/document_stream-inl.h for westmere: #include "simdjson/generic/ondemand/document_stream-inl.h" */
86226
/* begin file simdjson/generic/ondemand/document_stream-inl.h for westmere */
86227
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
86228
86229
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
86230
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */
86231
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
86232
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
86233
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
86234
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
86235
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
86236
86237
#include <algorithm>
86238
#include <stdexcept>
86239
86240
namespace simdjson {
86241
namespace westmere {
86242
namespace ondemand {
86243
86244
#ifdef SIMDJSON_THREADS_ENABLED
86245
86246
inline void stage1_worker::finish() {
86247
  // After calling "run" someone would call finish() to wait
86248
  // for the end of the processing.
86249
  // This function will wait until either the thread has done
86250
  // the processing or, else, the destructor has been called.
86251
  std::unique_lock<std::mutex> lock(locking_mutex);
86252
  cond_var.wait(lock, [this]{return has_work == false;});
86253
}
86254
86255
inline stage1_worker::~stage1_worker() {
86256
  // The thread may never outlive the stage1_worker instance
86257
  // and will always be stopped/joined before the stage1_worker
86258
  // instance is gone.
86259
  stop_thread();
86260
}
86261
86262
inline void stage1_worker::start_thread() {
86263
  std::unique_lock<std::mutex> lock(locking_mutex);
86264
  if(thread.joinable()) {
86265
    return; // This should never happen but we never want to create more than one thread.
86266
  }
86267
  thread = std::thread([this]{
86268
      while(true) {
86269
        std::unique_lock<std::mutex> thread_lock(locking_mutex);
86270
        // We wait for either "run" or "stop_thread" to be called.
86271
        cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
86272
        // If, for some reason, the stop_thread() method was called (i.e., the
86273
        // destructor of stage1_worker is called, then we want to immediately destroy
86274
        // the thread (and not do any more processing).
86275
        if(!can_work) {
86276
          break;
86277
        }
86278
        this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
86279
              this->_next_batch_start);
86280
        this->has_work = false;
86281
        // The condition variable call should be moved after thread_lock.unlock() for performance
86282
        // reasons but thread sanitizers may report it as a data race if we do.
86283
        // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
86284
        cond_var.notify_one(); // will notify "finish"
86285
        thread_lock.unlock();
86286
      }
86287
    }
86288
  );
86289
}
86290
86291
86292
inline void stage1_worker::stop_thread() {
86293
  std::unique_lock<std::mutex> lock(locking_mutex);
86294
  // We have to make sure that all locks can be released.
86295
  can_work = false;
86296
  has_work = false;
86297
  cond_var.notify_all();
86298
  lock.unlock();
86299
  if(thread.joinable()) {
86300
    thread.join();
86301
  }
86302
}
86303
86304
inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) {
86305
  std::unique_lock<std::mutex> lock(locking_mutex);
86306
  owner = ds;
86307
  _next_batch_start = next_batch_start;
86308
  stage1_thread_parser = stage1;
86309
  has_work = true;
86310
  // The condition variable call should be moved after thread_lock.unlock() for performance
86311
  // reasons but thread sanitizers may report it as a data race if we do.
86312
  // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
86313
  cond_var.notify_one(); // will notify the thread lock that we have work
86314
  lock.unlock();
86315
}
86316
86317
#endif  // SIMDJSON_THREADS_ENABLED
86318
86319
simdjson_inline document_stream::document_stream(
86320
  ondemand::parser &_parser,
86321
  const uint8_t *_buf,
86322
  size_t _len,
86323
  size_t _batch_size,
86324
  bool _allow_comma_separated
86325
) noexcept
86326
  : parser{&_parser},
86327
    buf{_buf},
86328
    len{_len},
86329
    batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
86330
    allow_comma_separated{_allow_comma_separated},
86331
    error{SUCCESS}
86332
    #ifdef SIMDJSON_THREADS_ENABLED
86333
    , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
86334
    #endif
86335
{
86336
#ifdef SIMDJSON_THREADS_ENABLED
86337
  if(worker.get() == nullptr) {
86338
    error = MEMALLOC;
86339
  }
86340
#endif
86341
}
86342
86343
simdjson_inline document_stream::document_stream() noexcept
86344
  : parser{nullptr},
86345
    buf{nullptr},
86346
    len{0},
86347
    batch_size{0},
86348
    allow_comma_separated{false},
86349
    error{UNINITIALIZED}
86350
    #ifdef SIMDJSON_THREADS_ENABLED
86351
    , use_thread(false)
86352
    #endif
86353
{
86354
}
86355
86356
simdjson_inline document_stream::~document_stream() noexcept
86357
{
86358
  #ifdef SIMDJSON_THREADS_ENABLED
86359
  worker.reset();
86360
  #endif
86361
}
86362
86363
inline size_t document_stream::size_in_bytes() const noexcept {
86364
  return len;
86365
}
86366
86367
inline size_t document_stream::truncated_bytes() const noexcept {
86368
  if(error == CAPACITY) { return len - batch_start; }
86369
  return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
86370
}
86371
86372
simdjson_inline document_stream::iterator::iterator() noexcept
86373
  : stream{nullptr}, finished{true} {
86374
}
86375
86376
simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
86377
  : stream{_stream}, finished{is_end} {
86378
}
86379
86380
simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
86381
  //if(stream->error) { return stream->error; }
86382
  return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
86383
}
86384
86385
simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
86386
  // If there is an error, then we want the iterator
86387
  // to be finished, no matter what. (E.g., we do not
86388
  // keep generating documents with errors, or go beyond
86389
  // a document with errors.)
86390
  //
86391
  // Users do not have to call "operator*()" when they use operator++,
86392
  // so we need to end the stream in the operator++ function.
86393
  //
86394
  // Note that setting finished = true is essential otherwise
86395
  // we would enter an infinite loop.
86396
  if (stream->error) { finished = true; }
86397
  // Note that stream->error() is guarded against error conditions
86398
  // (it will immediately return if stream->error casts to false).
86399
  // In effect, this next function does nothing when (stream->error)
86400
  // is true (hence the risk of an infinite loop).
86401
  stream->next();
86402
  // If that was the last document, we're finished.
86403
  // It is the only type of error we do not want to appear
86404
  // in operator*.
86405
  if (stream->error == EMPTY) { finished = true; }
86406
  // If we had any other kind of error (not EMPTY) then we want
86407
  // to pass it along to the operator* and we cannot mark the result
86408
  // as "finished" just yet.
86409
  return *this;
86410
}
86411
86412
simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
86413
  return finished != other.finished;
86414
}
86415
86416
simdjson_inline document_stream::iterator document_stream::begin() noexcept {
86417
  start();
86418
  // If there are no documents, we're finished.
86419
  return iterator(this, error == EMPTY);
86420
}
86421
86422
simdjson_inline document_stream::iterator document_stream::end() noexcept {
86423
  return iterator(this, true);
86424
}
86425
86426
inline void document_stream::start() noexcept {
86427
  if (error) { return; }
86428
  error = parser->allocate(batch_size);
86429
  if (error) { return; }
86430
  // Always run the first stage 1 parse immediately
86431
  batch_start = 0;
86432
  error = run_stage1(*parser, batch_start);
86433
  while(error == EMPTY) {
86434
    // In exceptional cases, we may start with an empty block
86435
    batch_start = next_batch_start();
86436
    if (batch_start >= len) { return; }
86437
    error = run_stage1(*parser, batch_start);
86438
  }
86439
  if (error) { return; }
86440
  doc_index = batch_start;
86441
  doc = document(json_iterator(&buf[batch_start], parser));
86442
  doc.iter._streaming = true;
86443
86444
  #ifdef SIMDJSON_THREADS_ENABLED
86445
  if (use_thread && next_batch_start() < len) {
86446
    // Kick off the first thread on next batch if needed
86447
    error = stage1_thread_parser.allocate(batch_size);
86448
    if (error) { return; }
86449
    worker->start_thread();
86450
    start_stage1_thread();
86451
    if (error) { return; }
86452
  }
86453
  #endif // SIMDJSON_THREADS_ENABLED
86454
}
86455
86456
inline void document_stream::next() noexcept {
86457
  // We always enter at once once in an error condition.
86458
  if (error) { return; }
86459
  next_document();
86460
  if (error) { return; }
86461
  auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get();
86462
  doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index];
86463
86464
  // Check if at end of structural indexes (i.e. at end of batch)
86465
  if(cur_struct_index >= static_cast<int64_t>(parser->implementation->n_structural_indexes)) {
86466
    error = EMPTY;
86467
    // Load another batch (if available)
86468
    while (error == EMPTY) {
86469
      batch_start = next_batch_start();
86470
      if (batch_start >= len) { break; }
86471
      #ifdef SIMDJSON_THREADS_ENABLED
86472
      if(use_thread) {
86473
        load_from_stage1_thread();
86474
      } else {
86475
        error = run_stage1(*parser, batch_start);
86476
      }
86477
      #else
86478
      error = run_stage1(*parser, batch_start);
86479
      #endif
86480
      /**
86481
       * Whenever we move to another window, we need to update all pointers to make
86482
       * it appear as if the input buffer started at the beginning of the window.
86483
       *
86484
       * Take this input:
86485
       *
86486
       * {"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]  [15,  11,   12, 13]  [154,  110,   112, 1311]
86487
       *
86488
       * Say you process the following window...
86489
       *
86490
       * '{"z":5}  {"1":1,"2":2,"4":4} [7,  10,   9]'
86491
       *
86492
       * When you do so, the json_iterator has a pointer at the beginning of the memory region
86493
       * (pointing at the beginning of '{"z"...'.
86494
       *
86495
       * When you move to the window that starts at...
86496
       *
86497
       * '[7,  10,   9]  [15,  11,   12, 13] ...
86498
       *
86499
       * then it is not sufficient to just run stage 1. You also need to re-anchor the
86500
       * json_iterator so that it believes we are starting at '[7,  10,   9]...'.
86501
       *
86502
       * Under the DOM front-end, this gets done automatically because the parser owns
86503
       * the pointer the data, and when you call stage1 and then stage2 on the same
86504
       * parser, then stage2 will run on the pointer acquired by stage1.
86505
       *
86506
       * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that
86507
       * we used. But json_iterator has no callback when stage1 is called on the parser.
86508
       * In fact, I think that the parser is unaware of json_iterator.
86509
       *
86510
       *
86511
       * So we need to re-anchor the json_iterator after each call to stage 1 so that
86512
       * all of the pointers are in sync.
86513
       */
86514
      doc.iter = json_iterator(&buf[batch_start], parser);
86515
      doc.iter._streaming = true;
86516
      /**
86517
       * End of resync.
86518
       */
86519
86520
      if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
86521
      doc_index = batch_start;
86522
    }
86523
  }
86524
}
86525
86526
inline void document_stream::next_document() noexcept {
86527
  // Go to next place where depth=0 (document depth)
86528
  error = doc.iter.skip_child(0);
86529
  if (error) { return; }
86530
  // Always set depth=1 at the start of document
86531
  doc.iter._depth = 1;
86532
  // consume comma if comma separated is allowed
86533
  if (allow_comma_separated) { doc.iter.consume_character(','); }
86534
  // Resets the string buffer at the beginning, thus invalidating the strings.
86535
  doc.iter._string_buf_loc = parser->string_buf.get();
86536
  doc.iter._root = doc.iter.position();
86537
}
86538
86539
inline size_t document_stream::next_batch_start() const noexcept {
86540
  return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
86541
}
86542
86543
inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept {
86544
  // This code only updates the structural index in the parser, it does not update any json_iterator
86545
  // instance.
86546
  size_t remaining = len - _batch_start;
86547
  if (remaining <= batch_size) {
86548
    return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
86549
  } else {
86550
    return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
86551
  }
86552
}
86553
86554
simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
86555
  return stream->doc_index;
86556
}
86557
86558
simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
86559
  auto depth = stream->doc.iter.depth();
86560
  auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get();
86561
86562
  // If at root, process the first token to determine if scalar value
86563
  if (stream->doc.iter.at_root()) {
86564
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
86565
      case '{': case '[':   // Depth=1 already at start of document
86566
        break;
86567
      case '}': case ']':
86568
        depth--;
86569
        break;
86570
      default:    // Scalar value document
86571
        // TODO: Remove any trailing whitespaces
86572
        // This returns a string spanning from start of value to the beginning of the next document (excluded)
86573
        return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[++cur_struct_index] - current_index() - 1);
86574
    }
86575
    cur_struct_index++;
86576
  }
86577
86578
  while (cur_struct_index <= static_cast<int64_t>(stream->parser->implementation->n_structural_indexes)) {
86579
    switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
86580
      case '{': case '[':
86581
        depth++;
86582
        break;
86583
      case '}': case ']':
86584
        depth--;
86585
        break;
86586
    }
86587
    if (depth == 0) { break; }
86588
    cur_struct_index++;
86589
  }
86590
86591
  return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);;
86592
}
86593
86594
inline error_code document_stream::iterator::error() const noexcept {
86595
  return stream->error;
86596
}
86597
86598
#ifdef SIMDJSON_THREADS_ENABLED
86599
86600
inline void document_stream::load_from_stage1_thread() noexcept {
86601
  worker->finish();
86602
  // Swap to the parser that was loaded up in the thread. Make sure the parser has
86603
  // enough memory to swap to, as well.
86604
  std::swap(stage1_thread_parser,*parser);
86605
  error = stage1_thread_error;
86606
  if (error) { return; }
86607
86608
  // If there's anything left, start the stage 1 thread!
86609
  if (next_batch_start() < len) {
86610
    start_stage1_thread();
86611
  }
86612
}
86613
86614
inline void document_stream::start_stage1_thread() noexcept {
86615
  // we call the thread on a lambda that will update
86616
  // this->stage1_thread_error
86617
  // there is only one thread that may write to this value
86618
  // TODO this is NOT exception-safe.
86619
  this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
86620
  size_t _next_batch_start = this->next_batch_start();
86621
86622
  worker->run(this, & this->stage1_thread_parser, _next_batch_start);
86623
}
86624
86625
#endif // SIMDJSON_THREADS_ENABLED
86626
86627
} // namespace ondemand
86628
} // namespace westmere
86629
} // namespace simdjson
86630
86631
namespace simdjson {
86632
86633
simdjson_inline simdjson_result<westmere::ondemand::document_stream>::simdjson_result(
86634
  error_code error
86635
) noexcept :
86636
    implementation_simdjson_result_base<westmere::ondemand::document_stream>(error)
86637
{
86638
}
86639
simdjson_inline simdjson_result<westmere::ondemand::document_stream>::simdjson_result(
86640
  westmere::ondemand::document_stream &&value
86641
) noexcept :
86642
    implementation_simdjson_result_base<westmere::ondemand::document_stream>(
86643
      std::forward<westmere::ondemand::document_stream>(value)
86644
    )
86645
{
86646
}
86647
86648
}
86649
86650
#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
86651
/* end file simdjson/generic/ondemand/document_stream-inl.h for westmere */
86652
/* including simdjson/generic/ondemand/field-inl.h for westmere: #include "simdjson/generic/ondemand/field-inl.h" */
86653
/* begin file simdjson/generic/ondemand/field-inl.h for westmere */
86654
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
86655
86656
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
86657
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */
86658
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
86659
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
86660
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
86661
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
86662
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
86663
86664
namespace simdjson {
86665
namespace westmere {
86666
namespace ondemand {
86667
86668
// clang 6 does not think the default constructor can be noexcept, so we make it explicit
86669
simdjson_inline field::field() noexcept : std::pair<raw_json_string, ondemand::value>() {}
86670
86671
simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept
86672
  : std::pair<raw_json_string, ondemand::value>(key, std::forward<ondemand::value>(value))
86673
{
86674
}
86675
86676
simdjson_inline simdjson_result<field> field::start(value_iterator &parent_iter) noexcept {
86677
  raw_json_string key;
86678
  SIMDJSON_TRY( parent_iter.field_key().get(key) );
86679
  SIMDJSON_TRY( parent_iter.field_value() );
86680
  return field::start(parent_iter, key);
86681
}
86682
86683
simdjson_inline simdjson_result<field> field::start(const value_iterator &parent_iter, raw_json_string key) noexcept {
86684
    return field(key, parent_iter.child());
86685
}
86686
86687
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> field::unescaped_key(bool allow_replacement) noexcept {
86688
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us.
86689
  simdjson_result<std::string_view> answer = first.unescape(second.iter.json_iter(), allow_replacement);
86690
  first.consume();
86691
  return answer;
86692
}
86693
86694
simdjson_inline raw_json_string field::key() const noexcept {
86695
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
86696
  return first;
86697
}
86698
86699
86700
simdjson_inline std::string_view field::key_raw_json_token() const noexcept {
86701
  SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
86702
  return std::string_view(reinterpret_cast<const char*>(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1);
86703
}
86704
86705
simdjson_inline value &field::value() & noexcept {
86706
  return second;
86707
}
86708
86709
simdjson_inline value field::value() && noexcept {
86710
  return std::forward<field>(*this).second;
86711
}
86712
86713
} // namespace ondemand
86714
} // namespace westmere
86715
} // namespace simdjson
86716
86717
namespace simdjson {
86718
86719
simdjson_inline simdjson_result<westmere::ondemand::field>::simdjson_result(
86720
  westmere::ondemand::field &&value
86721
) noexcept :
86722
    implementation_simdjson_result_base<westmere::ondemand::field>(
86723
      std::forward<westmere::ondemand::field>(value)
86724
    )
86725
{
86726
}
86727
simdjson_inline simdjson_result<westmere::ondemand::field>::simdjson_result(
86728
  error_code error
86729
) noexcept :
86730
    implementation_simdjson_result_base<westmere::ondemand::field>(error)
86731
{
86732
}
86733
86734
simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> simdjson_result<westmere::ondemand::field>::key() noexcept {
86735
  if (error()) { return error(); }
86736
  return first.key();
86737
}
86738
86739
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::field>::key_raw_json_token() noexcept {
86740
  if (error()) { return error(); }
86741
  return first.key_raw_json_token();
86742
}
86743
86744
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::field>::unescaped_key(bool allow_replacement) noexcept {
86745
  if (error()) { return error(); }
86746
  return first.unescaped_key(allow_replacement);
86747
}
86748
86749
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::field>::value() noexcept {
86750
  if (error()) { return error(); }
86751
  return std::move(first.value());
86752
}
86753
86754
} // namespace simdjson
86755
86756
#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
86757
/* end file simdjson/generic/ondemand/field-inl.h for westmere */
86758
/* including simdjson/generic/ondemand/json_iterator-inl.h for westmere: #include "simdjson/generic/ondemand/json_iterator-inl.h" */
86759
/* begin file simdjson/generic/ondemand/json_iterator-inl.h for westmere */
86760
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
86761
86762
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
86763
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */
86764
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
86765
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
86766
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
86767
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
86768
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
86769
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */
86770
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */
86771
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */
86772
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
86773
86774
namespace simdjson {
86775
namespace westmere {
86776
namespace ondemand {
86777
86778
simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
86779
  : token(std::forward<token_iterator>(other.token)),
86780
    parser{other.parser},
86781
    _string_buf_loc{other._string_buf_loc},
86782
    error{other.error},
86783
    _depth{other._depth},
86784
    _root{other._root},
86785
    _streaming{other._streaming}
86786
{
86787
  other.parser = nullptr;
86788
}
86789
simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept {
86790
  token = other.token;
86791
  parser = other.parser;
86792
  _string_buf_loc = other._string_buf_loc;
86793
  error = other.error;
86794
  _depth = other._depth;
86795
  _root = other._root;
86796
  _streaming = other._streaming;
86797
  other.parser = nullptr;
86798
  return *this;
86799
}
86800
86801
simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept
86802
  : token(buf, &_parser->implementation->structural_indexes[0]),
86803
    parser{_parser},
86804
    _string_buf_loc{parser->string_buf.get()},
86805
    _depth{1},
86806
    _root{parser->implementation->structural_indexes.get()},
86807
    _streaming{false}
86808
86809
{
86810
  logger::log_headers();
86811
#if SIMDJSON_CHECK_EOF
86812
  assert_more_tokens();
86813
#endif
86814
}
86815
86816
inline void json_iterator::rewind() noexcept {
86817
  token.set_position( root_position() );
86818
  logger::log_headers(); // We start again
86819
  _string_buf_loc = parser->string_buf.get();
86820
  _depth = 1;
86821
}
86822
86823
inline bool json_iterator::balanced() const noexcept {
86824
  token_iterator ti(token);
86825
  int32_t count{0};
86826
  ti.set_position( root_position() );
86827
  while(ti.peek() <= peek_last()) {
86828
    switch (*ti.return_current_and_advance())
86829
    {
86830
    case '[': case '{':
86831
      count++;
86832
      break;
86833
    case ']': case '}':
86834
      count--;
86835
      break;
86836
    default:
86837
      break;
86838
    }
86839
  }
86840
  return count == 0;
86841
}
86842
86843
86844
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
86845
// relating depth and parent_depth, which is a desired effect. The warning does not show up if the
86846
// skip_child() function is not marked inline).
86847
SIMDJSON_PUSH_DISABLE_WARNINGS
86848
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
86849
simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
86850
  if (depth() <= parent_depth) { return SUCCESS; }
86851
  switch (*return_current_and_advance()) {
86852
    // TODO consider whether matching braces is a requirement: if non-matching braces indicates
86853
    // *missing* braces, then future lookups are not in the object/arrays they think they are,
86854
    // violating the rule "validate enough structure that the user can be confident they are
86855
    // looking at the right values."
86856
    // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
86857
86858
    // For the first open array/object in a value, we've already incremented depth, so keep it the same
86859
    // We never stop at colon, but if we did, it wouldn't affect depth
86860
    case '[': case '{': case ':':
86861
      logger::log_start_value(*this, "skip");
86862
      break;
86863
    // If there is a comma, we have just finished a value in an array/object, and need to get back in
86864
    case ',':
86865
      logger::log_value(*this, "skip");
86866
      break;
86867
    // ] or } means we just finished a value and need to jump out of the array/object
86868
    case ']': case '}':
86869
      logger::log_end_value(*this, "skip");
86870
      _depth--;
86871
      if (depth() <= parent_depth) { return SUCCESS; }
86872
#if SIMDJSON_CHECK_EOF
86873
      // If there are no more tokens, the parent is incomplete.
86874
      if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
86875
#endif // SIMDJSON_CHECK_EOF
86876
      break;
86877
    case '"':
86878
      if(*peek() == ':') {
86879
        // We are at a key!!!
86880
        // This might happen if you just started an object and you skip it immediately.
86881
        // Performance note: it would be nice to get rid of this check as it is somewhat
86882
        // expensive.
86883
        // https://github.com/simdjson/simdjson/issues/1742
86884
        logger::log_value(*this, "key");
86885
        return_current_and_advance(); // eat up the ':'
86886
        break; // important!!!
86887
      }
86888
      simdjson_fallthrough;
86889
    // Anything else must be a scalar value
86890
    default:
86891
      // For the first scalar, we will have incremented depth already, so we decrement it here.
86892
      logger::log_value(*this, "skip");
86893
      _depth--;
86894
      if (depth() <= parent_depth) { return SUCCESS; }
86895
      break;
86896
  }
86897
86898
  // Now that we've considered the first value, we only increment/decrement for arrays/objects
86899
  while (position() < end_position()) {
86900
    switch (*return_current_and_advance()) {
86901
      case '[': case '{':
86902
        logger::log_start_value(*this, "skip");
86903
        _depth++;
86904
        break;
86905
      // TODO consider whether matching braces is a requirement: if non-matching braces indicates
86906
      // *missing* braces, then future lookups are not in the object/arrays they think they are,
86907
      // violating the rule "validate enough structure that the user can be confident they are
86908
      // looking at the right values."
86909
      // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
86910
      case ']': case '}':
86911
        logger::log_end_value(*this, "skip");
86912
        _depth--;
86913
        if (depth() <= parent_depth) { return SUCCESS; }
86914
        break;
86915
      default:
86916
        logger::log_value(*this, "skip", "");
86917
        break;
86918
    }
86919
  }
86920
86921
  return report_error(TAPE_ERROR, "not enough close braces");
86922
}
86923
86924
SIMDJSON_POP_DISABLE_WARNINGS
86925
86926
simdjson_inline bool json_iterator::at_root() const noexcept {
86927
  return position() == root_position();
86928
}
86929
86930
simdjson_inline bool json_iterator::is_single_token() const noexcept {
86931
  return parser->implementation->n_structural_indexes == 1;
86932
}
86933
86934
simdjson_inline bool json_iterator::streaming() const noexcept {
86935
  return _streaming;
86936
}
86937
86938
simdjson_inline token_position json_iterator::root_position() const noexcept {
86939
  return _root;
86940
}
86941
86942
simdjson_inline void json_iterator::assert_at_document_depth() const noexcept {
86943
  SIMDJSON_ASSUME( _depth == 1 );
86944
}
86945
86946
simdjson_inline void json_iterator::assert_at_root() const noexcept {
86947
  SIMDJSON_ASSUME( _depth == 1 );
86948
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
86949
  // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument
86950
  // has side effects that will be discarded.
86951
  SIMDJSON_ASSUME( token.position() == _root );
86952
#endif
86953
}
86954
86955
simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
86956
  assert_valid_position(token._position + required_tokens - 1);
86957
}
86958
86959
simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
86960
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
86961
  SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
86962
  SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
86963
#endif
86964
}
86965
86966
simdjson_inline bool json_iterator::at_end() const noexcept {
86967
  return position() == end_position();
86968
}
86969
simdjson_inline token_position json_iterator::end_position() const noexcept {
86970
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
86971
  return &parser->implementation->structural_indexes[n_structural_indexes];
86972
}
86973
86974
inline std::string json_iterator::to_string() const noexcept {
86975
  if( !is_alive() ) { return "dead json_iterator instance"; }
86976
  const char * current_structural = reinterpret_cast<const char *>(token.peek());
86977
  return std::string("json_iterator [ depth : ") + std::to_string(_depth)
86978
          + std::string(", structural : '") + std::string(current_structural,1)
86979
          + std::string("', offset : ") + std::to_string(token.current_offset())
86980
          + std::string("', error : ") + error_message(error)
86981
          + std::string(" ]");
86982
}
86983
86984
inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
86985
  if (!is_alive()) {    // Unrecoverable error
86986
    if (!at_root()) {
86987
      return reinterpret_cast<const char *>(token.peek(-1));
86988
    } else {
86989
      return reinterpret_cast<const char *>(token.peek());
86990
    }
86991
  }
86992
  if (at_end()) {
86993
    return OUT_OF_BOUNDS;
86994
  }
86995
  return reinterpret_cast<const char *>(token.peek());
86996
}
86997
86998
simdjson_inline bool json_iterator::is_alive() const noexcept {
86999
  return parser;
87000
}
87001
87002
simdjson_inline void json_iterator::abandon() noexcept {
87003
  parser = nullptr;
87004
  _depth = 0;
87005
}
87006
87007
simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
87008
#if SIMDJSON_CHECK_EOF
87009
  assert_more_tokens();
87010
#endif // SIMDJSON_CHECK_EOF
87011
  return token.return_current_and_advance();
87012
}
87013
87014
simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
87015
  // deliberately done without safety guard:
87016
  return token.peek();
87017
}
87018
87019
simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
87020
#if SIMDJSON_CHECK_EOF
87021
  assert_more_tokens(delta+1);
87022
#endif // SIMDJSON_CHECK_EOF
87023
  return token.peek(delta);
87024
}
87025
87026
simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
87027
#if SIMDJSON_CHECK_EOF
87028
  assert_more_tokens(delta+1);
87029
#endif // #if SIMDJSON_CHECK_EOF
87030
  return token.peek_length(delta);
87031
}
87032
87033
simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
87034
  // todo: currently we require end-of-string buffering, but the following
87035
  // assert_valid_position should be turned on if/when we lift that condition.
87036
  // assert_valid_position(position);
87037
  // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
87038
  // is ON by default, we have no choice but to disable it for real with a comment.
87039
  return token.peek(position);
87040
}
87041
87042
simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
87043
#if SIMDJSON_CHECK_EOF
87044
  assert_valid_position(position);
87045
#endif // SIMDJSON_CHECK_EOF
87046
  return token.peek_length(position);
87047
}
87048
simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept {
87049
#if SIMDJSON_CHECK_EOF
87050
  assert_valid_position(position);
87051
#endif // SIMDJSON_CHECK_EOF
87052
  return token.peek_root_length(position);
87053
}
87054
87055
simdjson_inline token_position json_iterator::last_position() const noexcept {
87056
  // The following line fails under some compilers...
87057
  // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0);
87058
  // since it has side-effects.
87059
  uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
87060
  SIMDJSON_ASSUME(n_structural_indexes > 0);
87061
  return &parser->implementation->structural_indexes[n_structural_indexes - 1];
87062
}
87063
simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept {
87064
  return token.peek(last_position());
87065
}
87066
87067
simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
87068
  SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
87069
  SIMDJSON_ASSUME(_depth == parent_depth + 1);
87070
  _depth = parent_depth;
87071
}
87072
87073
simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
87074
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
87075
  SIMDJSON_ASSUME(_depth == child_depth - 1);
87076
  _depth = child_depth;
87077
}
87078
87079
simdjson_inline depth_t json_iterator::depth() const noexcept {
87080
  return _depth;
87081
}
87082
87083
simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
87084
  return _string_buf_loc;
87085
}
87086
87087
simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept {
87088
  SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD);
87089
  logger::log_error(*this, message);
87090
  error = _error;
87091
  return error;
87092
}
87093
87094
simdjson_inline token_position json_iterator::position() const noexcept {
87095
  return token.position();
87096
}
87097
87098
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept {
87099
  return parser->unescape(in, _string_buf_loc, allow_replacement);
87100
}
87101
87102
simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in) noexcept {
87103
  return parser->unescape_wobbly(in, _string_buf_loc);
87104
}
87105
87106
simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
87107
  SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
87108
  SIMDJSON_ASSUME(_depth == child_depth - 1);
87109
#if SIMDJSON_DEVELOPMENT_CHECKS
87110
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
87111
  SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
87112
  SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
87113
#endif
87114
#endif
87115
  token.set_position(position);
87116
  _depth = child_depth;
87117
}
87118
87119
simdjson_inline error_code json_iterator::consume_character(char c) noexcept {
87120
  if (*peek() == c) {
87121
    return_current_and_advance();
87122
    return SUCCESS;
87123
  }
87124
  return TAPE_ERROR;
87125
}
87126
87127
#if SIMDJSON_DEVELOPMENT_CHECKS
87128
87129
simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
87130
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
87131
  return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
87132
}
87133
87134
simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
87135
  SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
87136
  if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
87137
}
87138
87139
#endif
87140
87141
87142
simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept {
87143
  SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD);
87144
  logger::log_error(*this, message);
87145
  return _error;
87146
}
87147
87148
87149
simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept {
87150
  // This function is not expected to be called in performance-sensitive settings.
87151
  // Let us guard against silly cases:
87152
  if((N < max_len) || (N == 0)) { return false; }
87153
  // Copy to the buffer.
87154
  std::memcpy(tmpbuf, json, max_len);
87155
  if(N > max_len) { // We pad whatever remains with ' '.
87156
    std::memset(tmpbuf + max_len, ' ', N - max_len);
87157
  }
87158
  return true;
87159
}
87160
87161
} // namespace ondemand
87162
} // namespace westmere
87163
} // namespace simdjson
87164
87165
namespace simdjson {
87166
87167
simdjson_inline simdjson_result<westmere::ondemand::json_iterator>::simdjson_result(westmere::ondemand::json_iterator &&value) noexcept
87168
    : implementation_simdjson_result_base<westmere::ondemand::json_iterator>(std::forward<westmere::ondemand::json_iterator>(value)) {}
87169
simdjson_inline simdjson_result<westmere::ondemand::json_iterator>::simdjson_result(error_code error) noexcept
87170
    : implementation_simdjson_result_base<westmere::ondemand::json_iterator>(error) {}
87171
87172
} // namespace simdjson
87173
87174
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
87175
/* end file simdjson/generic/ondemand/json_iterator-inl.h for westmere */
87176
/* including simdjson/generic/ondemand/json_type-inl.h for westmere: #include "simdjson/generic/ondemand/json_type-inl.h" */
87177
/* begin file simdjson/generic/ondemand/json_type-inl.h for westmere */
87178
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
87179
87180
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
87181
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */
87182
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
87183
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
87184
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
87185
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
87186
87187
namespace simdjson {
87188
namespace westmere {
87189
namespace ondemand {
87190
87191
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
87192
    switch (type) {
87193
        case json_type::array: out << "array"; break;
87194
        case json_type::object: out << "object"; break;
87195
        case json_type::number: out << "number"; break;
87196
        case json_type::string: out << "string"; break;
87197
        case json_type::boolean: out << "boolean"; break;
87198
        case json_type::null: out << "null"; break;
87199
        default: SIMDJSON_UNREACHABLE();
87200
    }
87201
    return out;
87202
}
87203
87204
#if SIMDJSON_EXCEPTIONS
87205
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
87206
    return out << type.value();
87207
}
87208
#endif
87209
87210
87211
87212
simdjson_inline number_type number::get_number_type() const noexcept {
87213
  return type;
87214
}
87215
87216
simdjson_inline bool number::is_uint64() const noexcept {
87217
  return get_number_type() == number_type::unsigned_integer;
87218
}
87219
87220
simdjson_inline uint64_t number::get_uint64() const noexcept {
87221
  return payload.unsigned_integer;
87222
}
87223
87224
simdjson_inline number::operator uint64_t() const noexcept {
87225
  return get_uint64();
87226
}
87227
87228
simdjson_inline bool number::is_int64() const noexcept {
87229
  return get_number_type() == number_type::signed_integer;
87230
}
87231
87232
simdjson_inline int64_t number::get_int64() const noexcept {
87233
  return payload.signed_integer;
87234
}
87235
87236
simdjson_inline number::operator int64_t() const noexcept {
87237
  return get_int64();
87238
}
87239
87240
simdjson_inline bool number::is_double() const noexcept {
87241
    return get_number_type() == number_type::floating_point_number;
87242
}
87243
87244
simdjson_inline double number::get_double() const noexcept {
87245
  return payload.floating_point_number;
87246
}
87247
87248
simdjson_inline number::operator double() const noexcept {
87249
  return get_double();
87250
}
87251
87252
simdjson_inline double number::as_double() const noexcept {
87253
  if(is_double()) {
87254
    return payload.floating_point_number;
87255
  }
87256
  if(is_int64()) {
87257
    return double(payload.signed_integer);
87258
  }
87259
  return double(payload.unsigned_integer);
87260
}
87261
87262
simdjson_inline void number::append_s64(int64_t value) noexcept {
87263
  payload.signed_integer = value;
87264
  type = number_type::signed_integer;
87265
}
87266
87267
simdjson_inline void number::append_u64(uint64_t value) noexcept {
87268
  payload.unsigned_integer = value;
87269
  type = number_type::unsigned_integer;
87270
}
87271
87272
simdjson_inline void number::append_double(double value) noexcept {
87273
  payload.floating_point_number = value;
87274
  type = number_type::floating_point_number;
87275
}
87276
87277
simdjson_inline void number::skip_double() noexcept {
87278
  type = number_type::floating_point_number;
87279
}
87280
87281
} // namespace ondemand
87282
} // namespace westmere
87283
} // namespace simdjson
87284
87285
namespace simdjson {
87286
87287
simdjson_inline simdjson_result<westmere::ondemand::json_type>::simdjson_result(westmere::ondemand::json_type &&value) noexcept
87288
    : implementation_simdjson_result_base<westmere::ondemand::json_type>(std::forward<westmere::ondemand::json_type>(value)) {}
87289
simdjson_inline simdjson_result<westmere::ondemand::json_type>::simdjson_result(error_code error) noexcept
87290
    : implementation_simdjson_result_base<westmere::ondemand::json_type>(error) {}
87291
87292
} // namespace simdjson
87293
87294
#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
87295
/* end file simdjson/generic/ondemand/json_type-inl.h for westmere */
87296
/* including simdjson/generic/ondemand/logger-inl.h for westmere: #include "simdjson/generic/ondemand/logger-inl.h" */
87297
/* begin file simdjson/generic/ondemand/logger-inl.h for westmere */
87298
#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
87299
87300
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
87301
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */
87302
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
87303
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */
87304
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
87305
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
87306
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
87307
87308
#include <memory>
87309
#include <cstring>
87310
87311
namespace simdjson {
87312
namespace westmere {
87313
namespace ondemand {
87314
namespace logger {
87315
87316
static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
87317
static constexpr const int LOG_EVENT_LEN = 20;
87318
static constexpr const int LOG_BUFFER_LEN = 30;
87319
static constexpr const int LOG_SMALL_BUFFER_LEN = 10;
87320
static int log_depth = 0; // Not threadsafe. Log only.
87321
87322
// Helper to turn unprintable or newline characters into spaces
87323
static inline char printable_char(char c) {
87324
  if (c >= 0x20) {
87325
    return c;
87326
  } else {
87327
    return ' ';
87328
  }
87329
}
87330
87331
template<typename... Args>
87332
static inline std::string string_format(const std::string& format, const Args&... args)
87333
{
87334
  SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
87335
  int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
87336
  auto size = static_cast<size_t>(size_s);
87337
  if (size <= 0) return std::string();
87338
  std::unique_ptr<char[]> buf(new char[size]);
87339
  std::snprintf(buf.get(), size, format.c_str(), args...);
87340
  SIMDJSON_POP_DISABLE_WARNINGS
87341
  return std::string(buf.get(), buf.get() + size - 1);
87342
}
87343
87344
static inline log_level get_log_level_from_env()
87345
{
87346
  SIMDJSON_PUSH_DISABLE_WARNINGS
87347
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
87348
      char *lvl = getenv("SIMDJSON_LOG_LEVEL");
87349
  SIMDJSON_POP_DISABLE_WARNINGS
87350
  if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; }
87351
  return log_level::info;
87352
}
87353
87354
static inline log_level log_threshold()
87355
{
87356
  static log_level threshold = get_log_level_from_env();
87357
  return threshold;
87358
}
87359
87360
static inline bool should_log(log_level level)
87361
{
87362
  return level >= log_threshold();
87363
}
87364
87365
inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
87366
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
87367
}
87368
87369
inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
87370
  log_line(iter, index, depth, "", type, detail, log_level::info);
87371
}
87372
inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
87373
  log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
87374
}
87375
87376
inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
87377
  log_line(iter, index, depth, "+", type, detail, log_level::info);
87378
  if (LOG_ENABLED) { log_depth++; }
87379
}
87380
inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
87381
  log_line(iter, "+", type, "", delta, depth_delta, log_level::info);
87382
  if (LOG_ENABLED) { log_depth++; }
87383
}
87384
87385
inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
87386
  if (LOG_ENABLED) { log_depth--; }
87387
  log_line(iter, "-", type, "", delta, depth_delta, log_level::info);
87388
}
87389
87390
inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
87391
  log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error);
87392
}
87393
inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept {
87394
  log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error);
87395
}
87396
87397
inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
87398
  log_event(iter.json_iter(), type, detail, delta, depth_delta);
87399
}
87400
87401
inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
87402
  log_value(iter.json_iter(), type, detail, delta, depth_delta);
87403
}
87404
87405
inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
87406
  log_start_value(iter.json_iter(), type, delta, depth_delta);
87407
}
87408
87409
inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
87410
  log_end_value(iter.json_iter(), type, delta, depth_delta);
87411
}
87412
87413
inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
87414
  log_error(iter.json_iter(), error, detail, delta, depth_delta);
87415
}
87416
87417
inline void log_headers() noexcept {
87418
  if (LOG_ENABLED) {
87419
    if (simdjson_unlikely(should_log(log_level::info))) {
87420
      // Technically a static variable is not thread-safe, but if you are using threads and logging... well...
87421
      static bool displayed_hint{false};
87422
      log_depth = 0;
87423
      printf("\n");
87424
      if (!displayed_hint) {
87425
        // We only print this helpful header once.
87426
        printf("# Logging provides the depth and position of the iterator user-visible steps:\n");
87427
        printf("# +array says 'this is where we were when we discovered the start array'\n");
87428
        printf(
87429
            "# -array says 'this is where we were when we ended the array'\n");
87430
        printf("# skip says 'this is a structural or value I am skipping'\n");
87431
        printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
87432
        printf("#\n");
87433
        printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
87434
        printf("# in addition to the depth being displayed.\n");
87435
        printf("#\n");
87436
        printf("# Every token in the document has a single depth determined by the tokens before it,\n");
87437
        printf("# and is not affected by what the token actually is.\n");
87438
        printf("#\n");
87439
        printf("# Not all structural elements are presented as tokens in the logs.\n");
87440
        printf("#\n");
87441
        printf("# We never give control to the user within an empty array or an empty object.\n");
87442
        printf("#\n");
87443
        printf("# Inside an array, having a depth greater than the array's depth means that\n");
87444
        printf("# we are pointing inside a value.\n");
87445
        printf("# Having a depth equal to the array means that we are pointing right before a value.\n");
87446
        printf("# Having a depth smaller than the array means that we have moved beyond the array.\n");
87447
        displayed_hint = true;
87448
      }
87449
      printf("\n");
87450
      printf("| %-*s ", LOG_EVENT_LEN, "Event");
87451
      printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
87452
      printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next");
87453
      // printf("| %-*s ", 5,                    "Next#");
87454
      printf("| %-*s ", 5, "Depth");
87455
      printf("| Detail ");
87456
      printf("|\n");
87457
87458
      printf("|%.*s", LOG_EVENT_LEN + 2, DASHES);
87459
      printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES);
87460
      printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
87461
      // printf("|%.*s", 5+2, DASHES);
87462
      printf("|%.*s", 5 + 2, DASHES);
87463
      printf("|--------");
87464
      printf("|\n");
87465
      fflush(stdout);
87466
    }
87467
  }
87468
}
87469
87470
template <typename... Args>
87471
inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept {
87472
  log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
87473
}
87474
87475
template <typename... Args>
87476
inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
87477
  if (LOG_ENABLED) {
87478
    if (simdjson_unlikely(should_log(level))) {
87479
      const int indent = depth * 2;
87480
      const auto buf = iter.token.buf;
87481
      auto msg = string_format(title, std::forward<Args>(args)...);
87482
      printf("| %*s%s%-*s ", indent, "", title_prefix,
87483
             LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str());
87484
      {
87485
        // Print the current structural.
87486
        printf("| ");
87487
        // Before we begin, the index might point right before the document.
87488
        // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
87489
        if (index < iter._root) {
87490
          printf("%*s", LOG_BUFFER_LEN, "");
87491
        } else {
87492
          auto current_structural = &buf[*index];
87493
          for (int i = 0; i < LOG_BUFFER_LEN; i++) {
87494
            printf("%c", printable_char(current_structural[i]));
87495
          }
87496
        }
87497
        printf(" ");
87498
      }
87499
      {
87500
        // Print the next structural.
87501
        printf("| ");
87502
        auto next_structural = &buf[*(index + 1)];
87503
        for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
87504
          printf("%c", printable_char(next_structural[i]));
87505
        }
87506
        printf(" ");
87507
      }
87508
      // printf("| %5u ", *(index+1));
87509
      printf("| %5i ", depth);
87510
      printf("| %6.*s ", int(detail.size()), detail.data());
87511
      printf("|\n");
87512
      fflush(stdout);
87513
    }
87514
  }
87515
}
87516
87517
} // namespace logger
87518
} // namespace ondemand
87519
} // namespace westmere
87520
} // namespace simdjson
87521
87522
#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
87523
/* end file simdjson/generic/ondemand/logger-inl.h for westmere */
87524
/* including simdjson/generic/ondemand/object-inl.h for westmere: #include "simdjson/generic/ondemand/object-inl.h" */
87525
/* begin file simdjson/generic/ondemand/object-inl.h for westmere */
87526
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
87527
87528
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
87529
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */
87530
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
87531
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */
87532
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
87533
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
87534
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
87535
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
87536
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */
87537
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
87538
87539
namespace simdjson {
87540
namespace westmere {
87541
namespace ondemand {
87542
87543
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
87544
  bool has_value;
87545
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
87546
  if (!has_value) {
87547
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
87548
    return NO_SUCH_FIELD;
87549
  }
87550
  return value(iter.child());
87551
}
87552
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
87553
  bool has_value;
87554
  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
87555
  if (!has_value) {
87556
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
87557
    return NO_SUCH_FIELD;
87558
  }
87559
  return value(iter.child());
87560
}
87561
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
87562
  return find_field_unordered(key);
87563
}
87564
simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
87565
  return std::forward<object>(*this).find_field_unordered(key);
87566
}
87567
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
87568
  bool has_value;
87569
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
87570
  if (!has_value) {
87571
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
87572
    return NO_SUCH_FIELD;
87573
  }
87574
  return value(iter.child());
87575
}
87576
simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
87577
  bool has_value;
87578
  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
87579
  if (!has_value) {
87580
    logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
87581
    return NO_SUCH_FIELD;
87582
  }
87583
  return value(iter.child());
87584
}
87585
87586
simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
87587
  SIMDJSON_TRY( iter.start_object().error() );
87588
  return object(iter);
87589
}
87590
simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
87591
  SIMDJSON_TRY( iter.start_root_object().error() );
87592
  return object(iter);
87593
}
87594
simdjson_inline error_code object::consume() noexcept {
87595
  if(iter.is_at_key()) {
87596
    /**
87597
     * whenever you are pointing at a key, calling skip_child() is
87598
     * unsafe because you will hit a string and you will assume that
87599
     * it is string value, and this mistake will lead you to make bad
87600
     * depth computation.
87601
     */
87602
    /**
87603
     * We want to 'consume' the key. We could really
87604
     * just do _json_iter->return_current_and_advance(); at this
87605
     * point, but, for clarity, we will use the high-level API to
87606
     * eat the key. We assume that the compiler optimizes away
87607
     * most of the work.
87608
     */
87609
    simdjson_unused raw_json_string actual_key;
87610
    auto error = iter.field_key().get(actual_key);
87611
    if (error) { iter.abandon(); return error; };
87612
    // Let us move to the value while we are at it.
87613
    if ((error = iter.field_value())) { iter.abandon(); return error; }
87614
  }
87615
  auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
87616
  if(error_skip) { iter.abandon(); }
87617
  return error_skip;
87618
}
87619
87620
simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
87621
  const uint8_t * starting_point{iter.peek_start()};
87622
  auto error = consume();
87623
  if(error) { return error; }
87624
  const uint8_t * final_point{iter._json_iter->peek()};
87625
  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
87626
}
87627
87628
simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
87629
  SIMDJSON_TRY( iter.started_object().error() );
87630
  return object(iter);
87631
}
87632
87633
simdjson_inline object object::resume(const value_iterator &iter) noexcept {
87634
  return iter;
87635
}
87636
87637
simdjson_inline object::object(const value_iterator &_iter) noexcept
87638
  : iter{_iter}
87639
{
87640
}
87641
87642
simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
87643
#if SIMDJSON_DEVELOPMENT_CHECKS
87644
  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
87645
#endif
87646
  return object_iterator(iter);
87647
}
87648
simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
87649
  return object_iterator(iter);
87650
}
87651
87652
inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
87653
  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
87654
  json_pointer = json_pointer.substr(1);
87655
  size_t slash = json_pointer.find('/');
87656
  std::string_view key = json_pointer.substr(0, slash);
87657
  // Grab the child with the given key
87658
  simdjson_result<value> child;
87659
87660
  // If there is an escape character in the key, unescape it and then get the child.
87661
  size_t escape = key.find('~');
87662
  if (escape != std::string_view::npos) {
87663
    // Unescape the key
87664
    std::string unescaped(key);
87665
    do {
87666
      switch (unescaped[escape+1]) {
87667
        case '0':
87668
          unescaped.replace(escape, 2, "~");
87669
          break;
87670
        case '1':
87671
          unescaped.replace(escape, 2, "/");
87672
          break;
87673
        default:
87674
          return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
87675
      }
87676
      escape = unescaped.find('~', escape+1);
87677
    } while (escape != std::string::npos);
87678
    child = find_field(unescaped);  // Take note find_field does not unescape keys when matching
87679
  } else {
87680
    child = find_field(key);
87681
  }
87682
  if(child.error()) {
87683
    return child; // we do not continue if there was an error
87684
  }
87685
  // If there is a /, we have to recurse and look up more of the path
87686
  if (slash != std::string_view::npos) {
87687
    child = child.at_pointer(json_pointer.substr(slash));
87688
  }
87689
  return child;
87690
}
87691
87692
inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
87693
  auto json_pointer = json_path_to_pointer_conversion(json_path);
87694
  if (json_pointer == "-1") {
87695
    return INVALID_JSON_POINTER;
87696
  }
87697
  return at_pointer(json_pointer);
87698
}
87699
87700
simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
87701
  size_t count{0};
87702
  // Important: we do not consume any of the values.
87703
  for(simdjson_unused auto v : *this) { count++; }
87704
  // The above loop will always succeed, but we want to report errors.
87705
  if(iter.error()) { return iter.error(); }
87706
  // We need to move back at the start because we expect users to iterate through
87707
  // the object after counting the number of elements.
87708
  iter.reset_object();
87709
  return count;
87710
}
87711
87712
simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
87713
  bool is_not_empty;
87714
  auto error = iter.reset_object().get(is_not_empty);
87715
  if(error) { return error; }
87716
  return !is_not_empty;
87717
}
87718
87719
simdjson_inline simdjson_result<bool> object::reset() & noexcept {
87720
  return iter.reset_object();
87721
}
87722
87723
} // namespace ondemand
87724
} // namespace westmere
87725
} // namespace simdjson
87726
87727
namespace simdjson {
87728
87729
simdjson_inline simdjson_result<westmere::ondemand::object>::simdjson_result(westmere::ondemand::object &&value) noexcept
87730
    : implementation_simdjson_result_base<westmere::ondemand::object>(std::forward<westmere::ondemand::object>(value)) {}
87731
simdjson_inline simdjson_result<westmere::ondemand::object>::simdjson_result(error_code error) noexcept
87732
    : implementation_simdjson_result_base<westmere::ondemand::object>(error) {}
87733
87734
simdjson_inline simdjson_result<westmere::ondemand::object_iterator> simdjson_result<westmere::ondemand::object>::begin() noexcept {
87735
  if (error()) { return error(); }
87736
  return first.begin();
87737
}
87738
simdjson_inline simdjson_result<westmere::ondemand::object_iterator> simdjson_result<westmere::ondemand::object>::end() noexcept {
87739
  if (error()) { return error(); }
87740
  return first.end();
87741
}
87742
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
87743
  if (error()) { return error(); }
87744
  return first.find_field_unordered(key);
87745
}
87746
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
87747
  if (error()) { return error(); }
87748
  return std::forward<westmere::ondemand::object>(first).find_field_unordered(key);
87749
}
87750
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::operator[](std::string_view key) & noexcept {
87751
  if (error()) { return error(); }
87752
  return first[key];
87753
}
87754
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::operator[](std::string_view key) && noexcept {
87755
  if (error()) { return error(); }
87756
  return std::forward<westmere::ondemand::object>(first)[key];
87757
}
87758
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::find_field(std::string_view key) & noexcept {
87759
  if (error()) { return error(); }
87760
  return first.find_field(key);
87761
}
87762
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::find_field(std::string_view key) && noexcept {
87763
  if (error()) { return error(); }
87764
  return std::forward<westmere::ondemand::object>(first).find_field(key);
87765
}
87766
87767
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
87768
  if (error()) { return error(); }
87769
  return first.at_pointer(json_pointer);
87770
}
87771
87772
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::object>::at_path(
87773
    std::string_view json_path) noexcept {
87774
  if (error()) {
87775
    return error();
87776
  }
87777
  return first.at_path(json_path);
87778
}
87779
87780
inline simdjson_result<bool> simdjson_result<westmere::ondemand::object>::reset() noexcept {
87781
  if (error()) { return error(); }
87782
  return first.reset();
87783
}
87784
87785
inline simdjson_result<bool> simdjson_result<westmere::ondemand::object>::is_empty() noexcept {
87786
  if (error()) { return error(); }
87787
  return first.is_empty();
87788
}
87789
87790
simdjson_inline  simdjson_result<size_t> simdjson_result<westmere::ondemand::object>::count_fields() & noexcept {
87791
  if (error()) { return error(); }
87792
  return first.count_fields();
87793
}
87794
87795
simdjson_inline  simdjson_result<std::string_view> simdjson_result<westmere::ondemand::object>::raw_json() noexcept {
87796
  if (error()) { return error(); }
87797
  return first.raw_json();
87798
}
87799
} // namespace simdjson
87800
87801
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
87802
/* end file simdjson/generic/ondemand/object-inl.h for westmere */
87803
/* including simdjson/generic/ondemand/object_iterator-inl.h for westmere: #include "simdjson/generic/ondemand/object_iterator-inl.h" */
87804
/* begin file simdjson/generic/ondemand/object_iterator-inl.h for westmere */
87805
#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
87806
87807
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
87808
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */
87809
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
87810
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */
87811
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */
87812
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */
87813
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
87814
87815
namespace simdjson {
87816
namespace westmere {
87817
namespace ondemand {
87818
87819
//
87820
// object_iterator
87821
//
87822
87823
simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
87824
  : iter{_iter}
87825
{}
87826
87827
simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
87828
  error_code error = iter.error();
87829
  if (error) { iter.abandon(); return error; }
87830
  auto result = field::start(iter);
87831
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
87832
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
87833
  if (result.error()) { iter.abandon(); }
87834
  return result;
87835
}
87836
simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
87837
  return !(*this != other);
87838
}
87839
simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
87840
  return iter.is_open();
87841
}
87842
87843
SIMDJSON_PUSH_DISABLE_WARNINGS
87844
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
87845
simdjson_inline object_iterator &object_iterator::operator++() noexcept {
87846
  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
87847
  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
87848
  if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
87849
87850
  simdjson_unused error_code error;
87851
  if ((error = iter.skip_child() )) { return *this; }
87852
87853
  simdjson_unused bool has_value;
87854
  if ((error = iter.has_next_field().get(has_value) )) { return *this; };
87855
  return *this;
87856
}
87857
SIMDJSON_POP_DISABLE_WARNINGS
87858
87859
//
87860
// ### Live States
87861
//
87862
// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
87863
// always SUCCESS:
87864
//
87865
// - Start: This is the state when the object is first found and the iterator is just past the {.
87866
//   In this state, at_start == true.
87867
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
87868
//   iterate over, the iterator is at the , or } before the next value. In this state,
87869
//   depth == iter.depth, at_start == false, and error == SUCCESS.
87870
// - Unfinished Business: When we hand an array/object to the user which they do not fully
87871
//   iterate over, we need to finish that iteration by skipping child values until we reach the
87872
//   Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
87873
//
87874
// ## Error States
87875
//
87876
// In error states, we will yield exactly one more value before stopping. iter.depth == depth
87877
// and at_start is always false. We decrement after yielding the error, moving to the Finished
87878
// state.
87879
//
87880
// - Chained Error: When the object iterator is part of an error chain--for example, in
87881
//   `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
87882
//   object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
87883
//   iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
87884
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
87885
//   we flag that as an error and treat it exactly the same as a Chained Error. In this state,
87886
//   error == TAPE_ERROR, iter.depth == depth, and at_start == false.
87887
//
87888
// Errors that occur while reading a field to give to the user (such as when the key is not a
87889
// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
87890
// moving to the Finished state without transitioning through an Error state at all.
87891
//
87892
// ## Terminal State
87893
//
87894
// The terminal state has iter.depth < depth. at_start is always false.
87895
//
87896
// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
87897
//   In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
87898
//
87899
87900
} // namespace ondemand
87901
} // namespace westmere
87902
} // namespace simdjson
87903
87904
namespace simdjson {
87905
87906
simdjson_inline simdjson_result<westmere::ondemand::object_iterator>::simdjson_result(
87907
  westmere::ondemand::object_iterator &&value
87908
) noexcept
87909
  : implementation_simdjson_result_base<westmere::ondemand::object_iterator>(std::forward<westmere::ondemand::object_iterator>(value))
87910
{
87911
  first.iter.assert_is_valid();
87912
}
87913
simdjson_inline simdjson_result<westmere::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
87914
  : implementation_simdjson_result_base<westmere::ondemand::object_iterator>({}, error)
87915
{
87916
}
87917
87918
simdjson_inline simdjson_result<westmere::ondemand::field> simdjson_result<westmere::ondemand::object_iterator>::operator*() noexcept {
87919
  if (error()) { return error(); }
87920
  return *first;
87921
}
87922
// If we're iterating and there is an error, return the error once.
87923
simdjson_inline bool simdjson_result<westmere::ondemand::object_iterator>::operator==(const simdjson_result<westmere::ondemand::object_iterator> &other) const noexcept {
87924
  if (!first.iter.is_valid()) { return !error(); }
87925
  return first == other.first;
87926
}
87927
// If we're iterating and there is an error, return the error once.
87928
simdjson_inline bool simdjson_result<westmere::ondemand::object_iterator>::operator!=(const simdjson_result<westmere::ondemand::object_iterator> &other) const noexcept {
87929
  if (!first.iter.is_valid()) { return error(); }
87930
  return first != other.first;
87931
}
87932
// Checks for ']' and ','
87933
simdjson_inline simdjson_result<westmere::ondemand::object_iterator> &simdjson_result<westmere::ondemand::object_iterator>::operator++() noexcept {
87934
  // Clear the error if there is one, so we don't yield it twice
87935
  if (error()) { second = SUCCESS; return *this; }
87936
  ++first;
87937
  return *this;
87938
}
87939
87940
} // namespace simdjson
87941
87942
#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
87943
/* end file simdjson/generic/ondemand/object_iterator-inl.h for westmere */
87944
/* including simdjson/generic/ondemand/parser-inl.h for westmere: #include "simdjson/generic/ondemand/parser-inl.h" */
87945
/* begin file simdjson/generic/ondemand/parser-inl.h for westmere */
87946
#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
87947
87948
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
87949
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */
87950
/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */
87951
/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */
87952
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
87953
/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */
87954
/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */
87955
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
87956
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */
87957
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */
87958
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
87959
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
87960
87961
namespace simdjson {
87962
namespace westmere {
87963
namespace ondemand {
87964
87965
simdjson_inline parser::parser(size_t max_capacity) noexcept
87966
  : _max_capacity{max_capacity} {
87967
}
87968
87969
simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept {
87970
  if (new_capacity > max_capacity()) { return CAPACITY; }
87971
  if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; }
87972
87973
  // string_capacity copied from document::allocate
87974
  _capacity = 0;
87975
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64);
87976
  string_buf.reset(new (std::nothrow) uint8_t[string_capacity]);
87977
#if SIMDJSON_DEVELOPMENT_CHECKS
87978
  start_positions.reset(new (std::nothrow) token_position[new_max_depth]);
87979
#endif
87980
  if (implementation) {
87981
    SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
87982
    SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
87983
  } else {
87984
    SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
87985
  }
87986
  _capacity = new_capacity;
87987
  _max_depth = new_max_depth;
87988
  return SUCCESS;
87989
}
87990
87991
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(padded_string_view json) & noexcept {
87992
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
87993
87994
  json.remove_utf8_bom();
87995
87996
  // Allocate if needed
87997
  if (capacity() < json.length() || !string_buf) {
87998
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
87999
  }
88000
88001
  // Run stage 1.
88002
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
88003
  return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this });
88004
}
88005
88006
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const char *json, size_t len, size_t allocated) & noexcept {
88007
  return iterate(padded_string_view(json, len, allocated));
88008
}
88009
88010
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept {
88011
  return iterate(padded_string_view(json, len, allocated));
88012
}
88013
88014
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string_view json, size_t allocated) & noexcept {
88015
  return iterate(padded_string_view(json, allocated));
88016
}
88017
88018
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
88019
  if(json.capacity() - json.size() < SIMDJSON_PADDING) {
88020
    json.reserve(json.size() + SIMDJSON_PADDING);
88021
  }
88022
  return iterate(padded_string_view(json));
88023
}
88024
88025
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
88026
  return iterate(padded_string_view(json));
88027
}
88028
88029
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string_view> &result) & noexcept {
88030
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
88031
  SIMDJSON_TRY( result.error() );
88032
  padded_string_view json = result.value_unsafe();
88033
  return iterate(json);
88034
}
88035
88036
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
88037
  // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
88038
  SIMDJSON_TRY( result.error() );
88039
  const padded_string &json = result.value_unsafe();
88040
  return iterate(json);
88041
}
88042
88043
simdjson_warn_unused simdjson_inline simdjson_result<json_iterator> parser::iterate_raw(padded_string_view json) & noexcept {
88044
  if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
88045
88046
  json.remove_utf8_bom();
88047
88048
  // Allocate if needed
88049
  if (capacity() < json.length()) {
88050
    SIMDJSON_TRY( allocate(json.length(), max_depth()) );
88051
  }
88052
88053
  // Run stage 1.
88054
  SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
88055
  return json_iterator(reinterpret_cast<const uint8_t *>(json.data()), this);
88056
}
88057
88058
inline simdjson_result<document_stream> parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
88059
  if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
88060
  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
88061
    buf += 3;
88062
    len -= 3;
88063
  }
88064
  if(allow_comma_separated && batch_size < len) { batch_size = len; }
88065
  return document_stream(*this, buf, len, batch_size, allow_comma_separated);
88066
}
88067
inline simdjson_result<document_stream> parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
88068
  return iterate_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size, allow_comma_separated);
88069
}
88070
inline simdjson_result<document_stream> parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept {
88071
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
88072
}
88073
inline simdjson_result<document_stream> parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept {
88074
  return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
88075
}
88076
88077
simdjson_inline size_t parser::capacity() const noexcept {
88078
  return _capacity;
88079
}
88080
simdjson_inline size_t parser::max_capacity() const noexcept {
88081
  return _max_capacity;
88082
}
88083
simdjson_inline size_t parser::max_depth() const noexcept {
88084
  return _max_depth;
88085
}
88086
88087
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
88088
  if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
88089
    _max_capacity = max_capacity;
88090
  } else {
88091
    _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
88092
  }
88093
}
88094
88095
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept {
88096
  uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement);
88097
  if (!end) { return STRING_ERROR; }
88098
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
88099
  dst = end;
88100
  return result;
88101
}
88102
88103
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept {
88104
  uint8_t *end = implementation->parse_wobbly_string(in.buf, dst);
88105
  if (!end) { return STRING_ERROR; }
88106
  std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
88107
  dst = end;
88108
  return result;
88109
}
88110
88111
} // namespace ondemand
88112
} // namespace westmere
88113
} // namespace simdjson
88114
88115
namespace simdjson {
88116
88117
simdjson_inline simdjson_result<westmere::ondemand::parser>::simdjson_result(westmere::ondemand::parser &&value) noexcept
88118
    : implementation_simdjson_result_base<westmere::ondemand::parser>(std::forward<westmere::ondemand::parser>(value)) {}
88119
simdjson_inline simdjson_result<westmere::ondemand::parser>::simdjson_result(error_code error) noexcept
88120
    : implementation_simdjson_result_base<westmere::ondemand::parser>(error) {}
88121
88122
} // namespace simdjson
88123
88124
#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
88125
/* end file simdjson/generic/ondemand/parser-inl.h for westmere */
88126
/* including simdjson/generic/ondemand/raw_json_string-inl.h for westmere: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
88127
/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for westmere */
88128
#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
88129
88130
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
88131
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */
88132
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
88133
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
88134
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */
88135
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
88136
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
88137
88138
namespace simdjson {
88139
88140
namespace westmere {
88141
namespace ondemand {
88142
88143
simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
88144
88145
simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
88146
88147
88148
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
88149
  size_t pos{0};
88150
  // if the content has no escape character, just scan through it quickly!
88151
  for(;pos < target.size() && target[pos] != '\\';pos++) {}
88152
  // slow path may begin.
88153
  bool escaping{false};
88154
  for(;pos < target.size();pos++) {
88155
    if((target[pos] == '"') && !escaping) {
88156
      return false;
88157
    } else if(target[pos] == '\\') {
88158
      escaping = !escaping;
88159
    } else {
88160
      escaping = false;
88161
    }
88162
  }
88163
  return true;
88164
}
88165
88166
simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
88167
  size_t pos{0};
88168
  // if the content has no escape character, just scan through it quickly!
88169
  for(;target[pos] && target[pos] != '\\';pos++) {}
88170
  // slow path may begin.
88171
  bool escaping{false};
88172
  for(;target[pos];pos++) {
88173
    if((target[pos] == '"') && !escaping) {
88174
      return false;
88175
    } else if(target[pos] == '\\') {
88176
      escaping = !escaping;
88177
    } else {
88178
      escaping = false;
88179
    }
88180
  }
88181
  return true;
88182
}
88183
88184
88185
simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
88186
  // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
88187
  return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
88188
}
88189
88190
simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
88191
  // Assumptions: does not contain unescaped quote characters, and
88192
  // the raw content is quote terminated within a valid JSON string.
88193
  if(target.size() <= SIMDJSON_PADDING) {
88194
    return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
88195
  }
88196
  const char * r{raw()};
88197
  size_t pos{0};
88198
  for(;pos < target.size();pos++) {
88199
    if(r[pos] != target[pos]) { return false; }
88200
  }
88201
  if(r[pos] != '"') { return false; }
88202
  return true;
88203
}
88204
88205
simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
88206
  const char * r{raw()};
88207
  size_t pos{0};
88208
  bool escaping{false};
88209
  for(;pos < target.size();pos++) {
88210
    if(r[pos] != target[pos]) { return false; }
88211
    // if target is a compile-time constant and it is free from
88212
    // quotes, then the next part could get optimized away through
88213
    // inlining.
88214
    if((target[pos] == '"') && !escaping) {
88215
      // We have reached the end of the raw_json_string but
88216
      // the target is not done.
88217
      return false;
88218
    } else if(target[pos] == '\\') {
88219
      escaping = !escaping;
88220
    } else {
88221
      escaping = false;
88222
    }
88223
  }
88224
  if(r[pos] != '"') { return false; }
88225
  return true;
88226
}
88227
88228
88229
simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
88230
  // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
88231
  // the raw content is quote terminated within a valid JSON string.
88232
  const char * r{raw()};
88233
  size_t pos{0};
88234
  for(;target[pos];pos++) {
88235
    if(r[pos] != target[pos]) { return false; }
88236
  }
88237
  if(r[pos] != '"') { return false; }
88238
  return true;
88239
}
88240
88241
simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
88242
  // Assumptions: does not contain unescaped quote characters, and
88243
  // the raw content is quote terminated within a valid JSON string.
88244
  const char * r{raw()};
88245
  size_t pos{0};
88246
  bool escaping{false};
88247
  for(;target[pos];pos++) {
88248
    if(r[pos] != target[pos]) { return false; }
88249
    // if target is a compile-time constant and it is free from
88250
    // quotes, then the next part could get optimized away through
88251
    // inlining.
88252
    if((target[pos] == '"') && !escaping) {
88253
      // We have reached the end of the raw_json_string but
88254
      // the target is not done.
88255
      return false;
88256
    } else if(target[pos] == '\\') {
88257
      escaping = !escaping;
88258
    } else {
88259
      escaping = false;
88260
    }
88261
  }
88262
  if(r[pos] != '"') { return false; }
88263
  return true;
88264
}
88265
88266
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
88267
  return a.unsafe_is_equal(c);
88268
}
88269
88270
simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
88271
  return a == c;
88272
}
88273
88274
simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
88275
  return !(a == c);
88276
}
88277
88278
simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
88279
  return !(a == c);
88280
}
88281
88282
88283
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
88284
  return iter.unescape(*this, allow_replacement);
88285
}
88286
88287
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
88288
  return iter.unescape_wobbly(*this);
88289
}
88290
88291
simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
88292
  bool in_escape = false;
88293
  const char *s = str.raw();
88294
  while (true) {
88295
    switch (*s) {
88296
      case '\\': in_escape = !in_escape; break;
88297
      case '"': if (in_escape) { in_escape = false; } else { return out; } break;
88298
      default: if (in_escape) { in_escape = false; }
88299
    }
88300
    out << *s;
88301
    s++;
88302
  }
88303
}
88304
88305
} // namespace ondemand
88306
} // namespace westmere
88307
} // namespace simdjson
88308
88309
namespace simdjson {
88310
88311
simdjson_inline simdjson_result<westmere::ondemand::raw_json_string>::simdjson_result(westmere::ondemand::raw_json_string &&value) noexcept
88312
    : implementation_simdjson_result_base<westmere::ondemand::raw_json_string>(std::forward<westmere::ondemand::raw_json_string>(value)) {}
88313
simdjson_inline simdjson_result<westmere::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
88314
    : implementation_simdjson_result_base<westmere::ondemand::raw_json_string>(error) {}
88315
88316
simdjson_inline simdjson_result<const char *> simdjson_result<westmere::ondemand::raw_json_string>::raw() const noexcept {
88317
  if (error()) { return error(); }
88318
  return first.raw();
88319
}
88320
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<westmere::ondemand::raw_json_string>::unescape(westmere::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
88321
  if (error()) { return error(); }
88322
  return first.unescape(iter, allow_replacement);
88323
}
88324
simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<westmere::ondemand::raw_json_string>::unescape_wobbly(westmere::ondemand::json_iterator &iter) const noexcept {
88325
  if (error()) { return error(); }
88326
  return first.unescape_wobbly(iter);
88327
}
88328
} // namespace simdjson
88329
88330
#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
88331
/* end file simdjson/generic/ondemand/raw_json_string-inl.h for westmere */
88332
/* including simdjson/generic/ondemand/serialization-inl.h for westmere: #include "simdjson/generic/ondemand/serialization-inl.h" */
88333
/* begin file simdjson/generic/ondemand/serialization-inl.h for westmere */
88334
#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
88335
88336
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
88337
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */
88338
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
88339
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
88340
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */
88341
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
88342
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
88343
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */
88344
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
88345
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
88346
88347
namespace simdjson {
88348
88349
inline std::string_view trim(const std::string_view str) noexcept {
88350
  // We can almost surely do better by rolling our own find_first_not_of function.
88351
  size_t first = str.find_first_not_of(" \t\n\r");
88352
  // If we have the empty string (just white space), then no trimming is possible, and
88353
  // we return the empty string_view.
88354
  if (std::string_view::npos == first) { return std::string_view(); }
88355
  size_t last = str.find_last_not_of(" \t\n\r");
88356
  return str.substr(first, (last - first + 1));
88357
}
88358
88359
88360
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::document& x) noexcept {
88361
  std::string_view v;
88362
  auto error = x.raw_json().get(v);
88363
  if(error) {return error; }
88364
  return trim(v);
88365
}
88366
88367
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::document_reference& x) noexcept {
88368
  std::string_view v;
88369
  auto error = x.raw_json().get(v);
88370
  if(error) {return error; }
88371
  return trim(v);
88372
}
88373
88374
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::value& x) noexcept {
88375
  /**
88376
   * If we somehow receive a value that has already been consumed,
88377
   * then the following code could be in trouble. E.g., we create
88378
   * an array as needed, but if an array was already created, then
88379
   * it could be bad.
88380
   */
88381
  using namespace westmere::ondemand;
88382
  westmere::ondemand::json_type t;
88383
  auto error = x.type().get(t);
88384
  if(error != SUCCESS) { return error; }
88385
  switch (t)
88386
  {
88387
    case json_type::array:
88388
    {
88389
      westmere::ondemand::array array;
88390
      error = x.get_array().get(array);
88391
      if(error) { return error; }
88392
      return to_json_string(array);
88393
    }
88394
    case json_type::object:
88395
    {
88396
      westmere::ondemand::object object;
88397
      error = x.get_object().get(object);
88398
      if(error) { return error; }
88399
      return to_json_string(object);
88400
    }
88401
    default:
88402
      return trim(x.raw_json_token());
88403
  }
88404
}
88405
88406
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::object& x) noexcept {
88407
  std::string_view v;
88408
  auto error = x.raw_json().get(v);
88409
  if(error) {return error; }
88410
  return trim(v);
88411
}
88412
88413
inline simdjson_result<std::string_view> to_json_string(westmere::ondemand::array& x) noexcept {
88414
  std::string_view v;
88415
  auto error = x.raw_json().get(v);
88416
  if(error) {return error; }
88417
  return trim(v);
88418
}
88419
88420
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::document> x) {
88421
  if (x.error()) { return x.error(); }
88422
  return to_json_string(x.value_unsafe());
88423
}
88424
88425
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::document_reference> x) {
88426
  if (x.error()) { return x.error(); }
88427
  return to_json_string(x.value_unsafe());
88428
}
88429
88430
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::value> x) {
88431
  if (x.error()) { return x.error(); }
88432
  return to_json_string(x.value_unsafe());
88433
}
88434
88435
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::object> x) {
88436
  if (x.error()) { return x.error(); }
88437
  return to_json_string(x.value_unsafe());
88438
}
88439
88440
inline simdjson_result<std::string_view> to_json_string(simdjson_result<westmere::ondemand::array> x) {
88441
  if (x.error()) { return x.error(); }
88442
  return to_json_string(x.value_unsafe());
88443
}
88444
} // namespace simdjson
88445
88446
namespace simdjson { namespace westmere { namespace ondemand {
88447
88448
#if SIMDJSON_EXCEPTIONS
88449
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::value x) {
88450
  std::string_view v;
88451
  auto error = simdjson::to_json_string(x).get(v);
88452
  if(error == simdjson::SUCCESS) {
88453
    return (out << v);
88454
  } else {
88455
    throw simdjson::simdjson_error(error);
88456
  }
88457
}
88458
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::value> x) {
88459
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
88460
  return (out << x.value());
88461
}
88462
#else
88463
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::value x) {
88464
  std::string_view v;
88465
  auto error = simdjson::to_json_string(x).get(v);
88466
  if(error == simdjson::SUCCESS) {
88467
    return (out << v);
88468
  } else {
88469
    return (out << error);
88470
  }
88471
}
88472
#endif
88473
88474
#if SIMDJSON_EXCEPTIONS
88475
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::array value) {
88476
  std::string_view v;
88477
  auto error = simdjson::to_json_string(value).get(v);
88478
  if(error == simdjson::SUCCESS) {
88479
    return (out << v);
88480
  } else {
88481
    throw simdjson::simdjson_error(error);
88482
  }
88483
}
88484
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::array> x) {
88485
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
88486
  return (out << x.value());
88487
}
88488
#else
88489
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::array value) {
88490
  std::string_view v;
88491
  auto error = simdjson::to_json_string(value).get(v);
88492
  if(error == simdjson::SUCCESS) {
88493
    return (out << v);
88494
  } else {
88495
    return (out << error);
88496
  }
88497
}
88498
#endif
88499
88500
#if SIMDJSON_EXCEPTIONS
88501
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::document& value)  {
88502
  std::string_view v;
88503
  auto error = simdjson::to_json_string(value).get(v);
88504
  if(error == simdjson::SUCCESS) {
88505
    return (out << v);
88506
  } else {
88507
    throw simdjson::simdjson_error(error);
88508
  }
88509
}
88510
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::document_reference& value)  {
88511
  std::string_view v;
88512
  auto error = simdjson::to_json_string(value).get(v);
88513
  if(error == simdjson::SUCCESS) {
88514
    return (out << v);
88515
  } else {
88516
    throw simdjson::simdjson_error(error);
88517
  }
88518
}
88519
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::document>&& x) {
88520
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
88521
  return (out << x.value());
88522
}
88523
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::westmere::ondemand::document_reference>&& x) {
88524
  if (x.error()) { throw simdjson::simdjson_error(x.error()); }
88525
  return (out << x.value());
88526
}
88527
#else
88528
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::document& value)  {
88529
  std::string_view v;
88530
  auto error = simdjson::to_json_string(value).get(v);
88531
  if(error == simdjson::SUCCESS) {
88532
    return (out << v);
88533
  } else {
88534
    return (out << error);
88535
  }
88536
}
88537
#endif
88538
88539
#if SIMDJSON_EXCEPTIONS
88540
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::object value) {
88541
  std::string_view v;
88542
  auto error = simdjson::to_json_string(value).get(v);
88543
  if(error == simdjson::SUCCESS) {
88544
    return (out << v);
88545
  } else {
88546
    throw simdjson::simdjson_error(error);
88547
  }
88548
}
88549
inline std::ostream& operator<<(std::ostream& out,  simdjson::simdjson_result<simdjson::westmere::ondemand::object> x) {
88550
  if (x.error()) { throw  simdjson::simdjson_error(x.error()); }
88551
  return (out << x.value());
88552
}
88553
#else
88554
inline std::ostream& operator<<(std::ostream& out, simdjson::westmere::ondemand::object value) {
88555
  std::string_view v;
88556
  auto error = simdjson::to_json_string(value).get(v);
88557
  if(error == simdjson::SUCCESS) {
88558
    return (out << v);
88559
  } else {
88560
    return (out << error);
88561
  }
88562
}
88563
#endif
88564
}}} // namespace simdjson::westmere::ondemand
88565
88566
#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
88567
/* end file simdjson/generic/ondemand/serialization-inl.h for westmere */
88568
/* including simdjson/generic/ondemand/token_iterator-inl.h for westmere: #include "simdjson/generic/ondemand/token_iterator-inl.h" */
88569
/* begin file simdjson/generic/ondemand/token_iterator-inl.h for westmere */
88570
#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
88571
88572
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
88573
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */
88574
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
88575
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */
88576
/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */
88577
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
88578
88579
namespace simdjson {
88580
namespace westmere {
88581
namespace ondemand {
88582
88583
simdjson_inline token_iterator::token_iterator(
88584
  const uint8_t *_buf,
88585
  token_position position
88586
) noexcept : buf{_buf}, _position{position}
88587
{
88588
}
88589
88590
simdjson_inline uint32_t token_iterator::current_offset() const noexcept {
88591
  return *(_position);
88592
}
88593
88594
88595
simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept {
88596
  return &buf[*(_position++)];
88597
}
88598
88599
simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept {
88600
  return &buf[*position];
88601
}
88602
simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept {
88603
  return *position;
88604
}
88605
simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept {
88606
  return *(position+1) - *position;
88607
}
88608
88609
simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept {
88610
  return *(position+2) - *(position) > *(position+1) - *(position) ?
88611
      *(position+1) - *(position)
88612
      : *(position+2) - *(position);
88613
}
88614
simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept {
88615
  return &buf[*(_position+delta)];
88616
}
88617
simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept {
88618
  return *(_position+delta);
88619
}
88620
simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept {
88621
  return *(_position+delta+1) - *(_position+delta);
88622
}
88623
88624
simdjson_inline token_position token_iterator::position() const noexcept {
88625
  return _position;
88626
}
88627
simdjson_inline void token_iterator::set_position(token_position target_position) noexcept {
88628
  _position = target_position;
88629
}
88630
88631
simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept {
88632
  return _position == other._position;
88633
}
88634
simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept {
88635
  return _position != other._position;
88636
}
88637
simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept {
88638
  return _position > other._position;
88639
}
88640
simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept {
88641
  return _position >= other._position;
88642
}
88643
simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept {
88644
  return _position < other._position;
88645
}
88646
simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept {
88647
  return _position <= other._position;
88648
}
88649
88650
} // namespace ondemand
88651
} // namespace westmere
88652
} // namespace simdjson
88653
88654
namespace simdjson {
88655
88656
simdjson_inline simdjson_result<westmere::ondemand::token_iterator>::simdjson_result(westmere::ondemand::token_iterator &&value) noexcept
88657
    : implementation_simdjson_result_base<westmere::ondemand::token_iterator>(std::forward<westmere::ondemand::token_iterator>(value)) {}
88658
simdjson_inline simdjson_result<westmere::ondemand::token_iterator>::simdjson_result(error_code error) noexcept
88659
    : implementation_simdjson_result_base<westmere::ondemand::token_iterator>(error) {}
88660
88661
} // namespace simdjson
88662
88663
#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
88664
/* end file simdjson/generic/ondemand/token_iterator-inl.h for westmere */
88665
/* including simdjson/generic/ondemand/value-inl.h for westmere: #include "simdjson/generic/ondemand/value-inl.h" */
88666
/* begin file simdjson/generic/ondemand/value-inl.h for westmere */
88667
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
88668
88669
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
88670
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */
88671
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
88672
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */
88673
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */
88674
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
88675
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion.h" */
88676
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_path_to_pointer_conversion-inl.h" */
88677
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */
88678
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */
88679
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */
88680
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */
88681
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
88682
88683
namespace simdjson {
88684
namespace westmere {
88685
namespace ondemand {
88686
88687
simdjson_inline value::value(const value_iterator &_iter) noexcept
88688
  : iter{_iter}
88689
{
88690
}
88691
simdjson_inline value value::start(const value_iterator &iter) noexcept {
88692
  return iter;
88693
}
88694
simdjson_inline value value::resume(const value_iterator &iter) noexcept {
88695
  return iter;
88696
}
88697
88698
simdjson_inline simdjson_result<array> value::get_array() noexcept {
88699
  return array::start(iter);
88700
}
88701
simdjson_inline simdjson_result<object> value::get_object() noexcept {
88702
  return object::start(iter);
88703
}
88704
simdjson_inline simdjson_result<object> value::start_or_resume_object() noexcept {
88705
  if (iter.at_start()) {
88706
    return get_object();
88707
  } else {
88708
    return object::resume(iter);
88709
  }
88710
}
88711
88712
simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
88713
  return iter.get_raw_json_string();
88714
}
88715
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
88716
  return iter.get_string(allow_replacement);
88717
}
88718
template <typename string_type>
88719
simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
88720
  return iter.get_string(receiver, allow_replacement);
88721
}
88722
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
88723
  return iter.get_wobbly_string();
88724
}
88725
simdjson_inline simdjson_result<double> value::get_double() noexcept {
88726
  return iter.get_double();
88727
}
88728
simdjson_inline simdjson_result<double> value::get_double_in_string() noexcept {
88729
  return iter.get_double_in_string();
88730
}
88731
simdjson_inline simdjson_result<uint64_t> value::get_uint64() noexcept {
88732
  return iter.get_uint64();
88733
}
88734
simdjson_inline simdjson_result<uint64_t> value::get_uint64_in_string() noexcept {
88735
  return iter.get_uint64_in_string();
88736
}
88737
simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
88738
  return iter.get_int64();
88739
}
88740
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
88741
  return iter.get_int64_in_string();
88742
}
88743
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
88744
  return iter.get_bool();
88745
}
88746
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
88747
  return iter.is_null();
88748
}
88749
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
88750
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
88751
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
88752
template<> simdjson_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(false); }
88753
template<> simdjson_inline simdjson_result<number> value::get() noexcept { return get_number(); }
88754
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
88755
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
88756
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
88757
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
88758
88759
template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
88760
  return get<T>().get(out);
88761
}
88762
88763
#if SIMDJSON_EXCEPTIONS
88764
template <class T>
88765
simdjson_inline value::operator T() noexcept(false) {
88766
  return get<T>();
88767
}
88768
simdjson_inline value::operator array() noexcept(false) {
88769
  return get_array();
88770
}
88771
simdjson_inline value::operator object() noexcept(false) {
88772
  return get_object();
88773
}
88774
simdjson_inline value::operator uint64_t() noexcept(false) {
88775
  return get_uint64();
88776
}
88777
simdjson_inline value::operator int64_t() noexcept(false) {
88778
  return get_int64();
88779
}
88780
simdjson_inline value::operator double() noexcept(false) {
88781
  return get_double();
88782
}
88783
simdjson_inline value::operator std::string_view() noexcept(false) {
88784
  return get_string(false);
88785
}
88786
simdjson_inline value::operator raw_json_string() noexcept(false) {
88787
  return get_raw_json_string();
88788
}
88789
simdjson_inline value::operator bool() noexcept(false) {
88790
  return get_bool();
88791
}
88792
#endif
88793
88794
simdjson_inline simdjson_result<array_iterator> value::begin() & noexcept {
88795
  return get_array().begin();
88796
}
88797
simdjson_inline simdjson_result<array_iterator> value::end() & noexcept {
88798
  return {};
88799
}
88800
simdjson_inline simdjson_result<size_t> value::count_elements() & noexcept {
88801
  simdjson_result<size_t> answer;
88802
  auto a = get_array();
88803
  answer = a.count_elements();
88804
  // count_elements leaves you pointing inside the array, at the first element.
88805
  // We need to move back so that the user can create a new array (which requires that
88806
  // we point at '[').
88807
  iter.move_at_start();
88808
  return answer;
88809
}
88810
simdjson_inline simdjson_result<size_t> value::count_fields() & noexcept {
88811
  simdjson_result<size_t> answer;
88812
  auto a = get_object();
88813
  answer = a.count_fields();
88814
  iter.move_at_start();
88815
  return answer;
88816
}
88817
simdjson_inline simdjson_result<value> value::at(size_t index) noexcept {
88818
  auto a = get_array();
88819
  return a.at(index);
88820
}
88821
88822
simdjson_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
88823
  return start_or_resume_object().find_field(key);
88824
}
88825
simdjson_inline simdjson_result<value> value::find_field(const char *key) noexcept {
88826
  return start_or_resume_object().find_field(key);
88827
}
88828
88829
simdjson_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
88830
  return start_or_resume_object().find_field_unordered(key);
88831
}
88832
simdjson_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
88833
  return start_or_resume_object().find_field_unordered(key);
88834
}
88835
88836
simdjson_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
88837
  return start_or_resume_object()[key];
88838
}
88839
simdjson_inline simdjson_result<value> value::operator[](const char *key) noexcept {
88840
  return start_or_resume_object()[key];
88841
}
88842
88843
simdjson_inline simdjson_result<json_type> value::type() noexcept {
88844
  return iter.type();
88845
}
88846
88847
simdjson_inline simdjson_result<bool> value::is_scalar() noexcept {
88848
  json_type this_type;
88849
  auto error = type().get(this_type);
88850
  if(error) { return error; }
88851
  return ! ((this_type == json_type::array) || (this_type == json_type::object));
88852
}
88853
88854
simdjson_inline simdjson_result<bool> value::is_string() noexcept {
88855
  json_type this_type;
88856
  auto error = type().get(this_type);
88857
  if(error) { return error; }
88858
  return (this_type == json_type::string);
88859
}
88860
88861
88862
simdjson_inline bool value::is_negative() noexcept {
88863
  return iter.is_negative();
88864
}
88865
88866
simdjson_inline simdjson_result<bool> value::is_integer() noexcept {
88867
  return iter.is_integer();
88868
}
88869
simdjson_warn_unused simdjson_inline simdjson_result<number_type> value::get_number_type() noexcept {
88870
  return iter.get_number_type();
88871
}
88872
simdjson_warn_unused simdjson_inline simdjson_result<number> value::get_number() noexcept {
88873
  return iter.get_number();
88874
}
88875
88876
simdjson_inline std::string_view value::raw_json_token() noexcept {
88877
  return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
88878
}
88879
88880
simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
88881
  json_type t;
88882
  SIMDJSON_TRY(type().get(t));
88883
  switch (t)
88884
  {
88885
    case json_type::array: {
88886
      ondemand::array array;
88887
      SIMDJSON_TRY(get_array().get(array));
88888
      return array.raw_json();
88889
    }
88890
    case json_type::object: {
88891
      ondemand::object object;
88892
      SIMDJSON_TRY(get_object().get(object));
88893
      return object.raw_json();
88894
    }
88895
    default:
88896
      return raw_json_token();
88897
  }
88898
}
88899
88900
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
88901
  return iter.json_iter().current_location();
88902
}
88903
88904
simdjson_inline int32_t value::current_depth() const noexcept{
88905
  return iter.json_iter().depth();
88906
}
88907
88908
simdjson_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
88909
  json_type t;
88910
  SIMDJSON_TRY(type().get(t));
88911
  switch (t)
88912
  {
88913
    case json_type::array:
88914
      return (*this).get_array().at_pointer(json_pointer);
88915
    case json_type::object:
88916
      return (*this).get_object().at_pointer(json_pointer);
88917
    default:
88918
      return INVALID_JSON_POINTER;
88919
  }
88920
}
88921
88922
simdjson_inline simdjson_result<value> value::at_path(std::string_view json_path) noexcept {
88923
  json_type t;
88924
  SIMDJSON_TRY(type().get(t));
88925
  switch (t) {
88926
  case json_type::array:
88927
      return (*this).get_array().at_path(json_path);
88928
  case json_type::object:
88929
      return (*this).get_object().at_path(json_path);
88930
  default:
88931
      return INVALID_JSON_POINTER;
88932
  }
88933
}
88934
88935
} // namespace ondemand
88936
} // namespace westmere
88937
} // namespace simdjson
88938
88939
namespace simdjson {
88940
88941
simdjson_inline simdjson_result<westmere::ondemand::value>::simdjson_result(
88942
  westmere::ondemand::value &&value
88943
) noexcept :
88944
    implementation_simdjson_result_base<westmere::ondemand::value>(
88945
      std::forward<westmere::ondemand::value>(value)
88946
    )
88947
{
88948
}
88949
simdjson_inline simdjson_result<westmere::ondemand::value>::simdjson_result(
88950
  error_code error
88951
) noexcept :
88952
    implementation_simdjson_result_base<westmere::ondemand::value>(error)
88953
{
88954
}
88955
simdjson_inline simdjson_result<size_t> simdjson_result<westmere::ondemand::value>::count_elements() & noexcept {
88956
  if (error()) { return error(); }
88957
  return first.count_elements();
88958
}
88959
simdjson_inline simdjson_result<size_t> simdjson_result<westmere::ondemand::value>::count_fields() & noexcept {
88960
  if (error()) { return error(); }
88961
  return first.count_fields();
88962
}
88963
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::at(size_t index) noexcept {
88964
  if (error()) { return error(); }
88965
  return first.at(index);
88966
}
88967
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::value>::begin() & noexcept {
88968
  if (error()) { return error(); }
88969
  return first.begin();
88970
}
88971
simdjson_inline simdjson_result<westmere::ondemand::array_iterator> simdjson_result<westmere::ondemand::value>::end() & noexcept {
88972
  if (error()) { return error(); }
88973
  return {};
88974
}
88975
88976
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::find_field(std::string_view key) noexcept {
88977
  if (error()) { return error(); }
88978
  return first.find_field(key);
88979
}
88980
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::find_field(const char *key) noexcept {
88981
  if (error()) { return error(); }
88982
  return first.find_field(key);
88983
}
88984
88985
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
88986
  if (error()) { return error(); }
88987
  return first.find_field_unordered(key);
88988
}
88989
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::find_field_unordered(const char *key) noexcept {
88990
  if (error()) { return error(); }
88991
  return first.find_field_unordered(key);
88992
}
88993
88994
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::operator[](std::string_view key) noexcept {
88995
  if (error()) { return error(); }
88996
  return first[key];
88997
}
88998
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::operator[](const char *key) noexcept {
88999
  if (error()) { return error(); }
89000
  return first[key];
89001
}
89002
89003
simdjson_inline simdjson_result<westmere::ondemand::array> simdjson_result<westmere::ondemand::value>::get_array() noexcept {
89004
  if (error()) { return error(); }
89005
  return first.get_array();
89006
}
89007
simdjson_inline simdjson_result<westmere::ondemand::object> simdjson_result<westmere::ondemand::value>::get_object() noexcept {
89008
  if (error()) { return error(); }
89009
  return first.get_object();
89010
}
89011
simdjson_inline simdjson_result<uint64_t> simdjson_result<westmere::ondemand::value>::get_uint64() noexcept {
89012
  if (error()) { return error(); }
89013
  return first.get_uint64();
89014
}
89015
simdjson_inline simdjson_result<uint64_t> simdjson_result<westmere::ondemand::value>::get_uint64_in_string() noexcept {
89016
  if (error()) { return error(); }
89017
  return first.get_uint64_in_string();
89018
}
89019
simdjson_inline simdjson_result<int64_t> simdjson_result<westmere::ondemand::value>::get_int64() noexcept {
89020
  if (error()) { return error(); }
89021
  return first.get_int64();
89022
}
89023
simdjson_inline simdjson_result<int64_t> simdjson_result<westmere::ondemand::value>::get_int64_in_string() noexcept {
89024
  if (error()) { return error(); }
89025
  return first.get_int64_in_string();
89026
}
89027
simdjson_inline simdjson_result<double> simdjson_result<westmere::ondemand::value>::get_double() noexcept {
89028
  if (error()) { return error(); }
89029
  return first.get_double();
89030
}
89031
simdjson_inline simdjson_result<double> simdjson_result<westmere::ondemand::value>::get_double_in_string() noexcept {
89032
  if (error()) { return error(); }
89033
  return first.get_double_in_string();
89034
}
89035
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::value>::get_string(bool allow_replacement) noexcept {
89036
  if (error()) { return error(); }
89037
  return first.get_string(allow_replacement);
89038
}
89039
template <typename string_type>
89040
simdjson_inline error_code simdjson_result<westmere::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
89041
  if (error()) { return error(); }
89042
  return first.get_string(receiver, allow_replacement);
89043
}
89044
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::value>::get_wobbly_string() noexcept {
89045
  if (error()) { return error(); }
89046
  return first.get_wobbly_string();
89047
}
89048
simdjson_inline simdjson_result<westmere::ondemand::raw_json_string> simdjson_result<westmere::ondemand::value>::get_raw_json_string() noexcept {
89049
  if (error()) { return error(); }
89050
  return first.get_raw_json_string();
89051
}
89052
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::value>::get_bool() noexcept {
89053
  if (error()) { return error(); }
89054
  return first.get_bool();
89055
}
89056
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::value>::is_null() noexcept {
89057
  if (error()) { return error(); }
89058
  return first.is_null();
89059
}
89060
89061
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<westmere::ondemand::value>::get() noexcept {
89062
  if (error()) { return error(); }
89063
  return first.get<T>();
89064
}
89065
template<typename T> simdjson_inline error_code simdjson_result<westmere::ondemand::value>::get(T &out) noexcept {
89066
  if (error()) { return error(); }
89067
  return first.get<T>(out);
89068
}
89069
89070
template<> simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::get<westmere::ondemand::value>() noexcept  {
89071
  if (error()) { return error(); }
89072
  return std::move(first);
89073
}
89074
template<> simdjson_inline error_code simdjson_result<westmere::ondemand::value>::get<westmere::ondemand::value>(westmere::ondemand::value &out) noexcept {
89075
  if (error()) { return error(); }
89076
  out = first;
89077
  return SUCCESS;
89078
}
89079
89080
simdjson_inline simdjson_result<westmere::ondemand::json_type> simdjson_result<westmere::ondemand::value>::type() noexcept {
89081
  if (error()) { return error(); }
89082
  return first.type();
89083
}
89084
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::value>::is_scalar() noexcept {
89085
  if (error()) { return error(); }
89086
  return first.is_scalar();
89087
}
89088
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::value>::is_string() noexcept {
89089
  if (error()) { return error(); }
89090
  return first.is_string();
89091
}
89092
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::value>::is_negative() noexcept {
89093
  if (error()) { return error(); }
89094
  return first.is_negative();
89095
}
89096
simdjson_inline simdjson_result<bool> simdjson_result<westmere::ondemand::value>::is_integer() noexcept {
89097
  if (error()) { return error(); }
89098
  return first.is_integer();
89099
}
89100
simdjson_inline simdjson_result<westmere::number_type> simdjson_result<westmere::ondemand::value>::get_number_type() noexcept {
89101
  if (error()) { return error(); }
89102
  return first.get_number_type();
89103
}
89104
simdjson_inline simdjson_result<westmere::ondemand::number> simdjson_result<westmere::ondemand::value>::get_number() noexcept {
89105
  if (error()) { return error(); }
89106
  return first.get_number();
89107
}
89108
#if SIMDJSON_EXCEPTIONS
89109
template <class T>
89110
simdjson_inline simdjson_result<westmere::ondemand::value>::operator T() noexcept(false) {
89111
  if (error()) { throw simdjson_error(error()); }
89112
  return static_cast<T>(first);
89113
}
89114
simdjson_inline simdjson_result<westmere::ondemand::value>::operator westmere::ondemand::array() noexcept(false) {
89115
  if (error()) { throw simdjson_error(error()); }
89116
  return first;
89117
}
89118
simdjson_inline simdjson_result<westmere::ondemand::value>::operator westmere::ondemand::object() noexcept(false) {
89119
  if (error()) { throw simdjson_error(error()); }
89120
  return first;
89121
}
89122
simdjson_inline simdjson_result<westmere::ondemand::value>::operator uint64_t() noexcept(false) {
89123
  if (error()) { throw simdjson_error(error()); }
89124
  return first;
89125
}
89126
simdjson_inline simdjson_result<westmere::ondemand::value>::operator int64_t() noexcept(false) {
89127
  if (error()) { throw simdjson_error(error()); }
89128
  return first;
89129
}
89130
simdjson_inline simdjson_result<westmere::ondemand::value>::operator double() noexcept(false) {
89131
  if (error()) { throw simdjson_error(error()); }
89132
  return first;
89133
}
89134
simdjson_inline simdjson_result<westmere::ondemand::value>::operator std::string_view() noexcept(false) {
89135
  if (error()) { throw simdjson_error(error()); }
89136
  return first;
89137
}
89138
simdjson_inline simdjson_result<westmere::ondemand::value>::operator westmere::ondemand::raw_json_string() noexcept(false) {
89139
  if (error()) { throw simdjson_error(error()); }
89140
  return first;
89141
}
89142
simdjson_inline simdjson_result<westmere::ondemand::value>::operator bool() noexcept(false) {
89143
  if (error()) { throw simdjson_error(error()); }
89144
  return first;
89145
}
89146
#endif
89147
89148
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::value>::raw_json_token() noexcept {
89149
  if (error()) { return error(); }
89150
  return first.raw_json_token();
89151
}
89152
89153
simdjson_inline simdjson_result<std::string_view> simdjson_result<westmere::ondemand::value>::raw_json() noexcept {
89154
  if (error()) { return error(); }
89155
  return first.raw_json();
89156
}
89157
89158
simdjson_inline simdjson_result<const char *> simdjson_result<westmere::ondemand::value>::current_location() noexcept {
89159
  if (error()) { return error(); }
89160
  return first.current_location();
89161
}
89162
89163
simdjson_inline simdjson_result<int32_t> simdjson_result<westmere::ondemand::value>::current_depth() const noexcept {
89164
  if (error()) { return error(); }
89165
  return first.current_depth();
89166
}
89167
89168
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::at_pointer(
89169
    std::string_view json_pointer) noexcept {
89170
  if (error()) {
89171
      return error();
89172
  }
89173
  return first.at_pointer(json_pointer);
89174
}
89175
89176
simdjson_inline simdjson_result<westmere::ondemand::value> simdjson_result<westmere::ondemand::value>::at_path(
89177
      std::string_view json_path) noexcept {
89178
  if (error()) {
89179
    return error();
89180
  }
89181
  return first.at_path(json_path);
89182
}
89183
89184
} // namespace simdjson
89185
89186
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
89187
/* end file simdjson/generic/ondemand/value-inl.h for westmere */
89188
/* including simdjson/generic/ondemand/value_iterator-inl.h for westmere: #include "simdjson/generic/ondemand/value_iterator-inl.h" */
89189
/* begin file simdjson/generic/ondemand/value_iterator-inl.h for westmere */
89190
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
89191
89192
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
89193
/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */
89194
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */
89195
/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */
89196
/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */
89197
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */
89198
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */
89199
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */
89200
/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */
89201
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
89202
89203
namespace simdjson {
89204
namespace westmere {
89205
namespace ondemand {
89206
89207
simdjson_inline value_iterator::value_iterator(
89208
  json_iterator *json_iter,
89209
  depth_t depth,
89210
  token_position start_position
89211
) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
89212
{
89213
}
89214
89215
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
89216
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
89217
  return started_object();
89218
}
89219
89220
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
89221
  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
89222
  return started_root_object();
89223
}
89224
89225
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
89226
  assert_at_container_start();
89227
#if SIMDJSON_DEVELOPMENT_CHECKS
89228
  _json_iter->set_start_position(_depth, start_position());
89229
#endif
89230
  if (*_json_iter->peek() == '}') {
89231
    logger::log_value(*_json_iter, "empty object");
89232
    _json_iter->return_current_and_advance();
89233
    end_container();
89234
    return false;
89235
  }
89236
  return true;
89237
}
89238
89239
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
89240
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
89241
  // current document. It only works in the normal mode where we have indexed a single document.
89242
  // Note that adding a check for 'streaming' is not expensive since we only have at most
89243
  // one root element.
89244
  if ( ! _json_iter->streaming() ) {
89245
    // The following lines do not fully protect against garbage content within the
89246
    // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
89247
    // call `at_end()` on the document instance at the end of the processing to
89248
    // ensure that the processing has finished at the end.
89249
    //
89250
    if (*_json_iter->peek_last() != '}') {
89251
      _json_iter->abandon();
89252
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
89253
    }
89254
    // If the last character is } *and* the first gibberish character is also '}'
89255
    // then on-demand could accidentally go over. So we need additional checks.
89256
    // https://github.com/simdjson/simdjson/issues/1834
89257
    // Checking that the document is balanced requires a full scan which is potentially
89258
    // expensive, but it only happens in edge cases where the first padding character is
89259
    // a closing bracket.
89260
    if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
89261
      _json_iter->abandon();
89262
      // The exact error would require more work. It will typically be an unclosed object.
89263
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
89264
    }
89265
  }
89266
  return SUCCESS;
89267
}
89268
89269
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
89270
  auto error = check_root_object();
89271
  if(error) { return error; }
89272
  return started_object();
89273
}
89274
89275
simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
89276
#if SIMDJSON_CHECK_EOF
89277
    if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
89278
    // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
89279
#endif // SIMDJSON_CHECK_EOF
89280
    _json_iter->ascend_to(depth()-1);
89281
    return SUCCESS;
89282
}
89283
89284
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
89285
  assert_at_next();
89286
89287
  // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
89288
  // obligated to verify there are more tokens if they are not the top level.
89289
  switch (*_json_iter->return_current_and_advance()) {
89290
    case '}':
89291
      logger::log_end_value(*_json_iter, "object");
89292
      SIMDJSON_TRY( end_container() );
89293
      return false;
89294
    case ',':
89295
      return true;
89296
    default:
89297
      return report_error(TAPE_ERROR, "Missing comma between object fields");
89298
  }
89299
}
89300
89301
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
89302
  error_code error;
89303
  bool has_value;
89304
  //
89305
  // Initially, the object can be in one of a few different places:
89306
  //
89307
  // 1. The start of the object, at the first field:
89308
  //
89309
  //    ```
89310
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89311
  //      ^ (depth 2, index 1)
89312
  //    ```
89313
  if (at_first_field()) {
89314
    has_value = true;
89315
89316
  //
89317
  // 2. When a previous search did not yield a value or the object is empty:
89318
  //
89319
  //    ```
89320
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89321
  //                                     ^ (depth 0)
89322
  //    { }
89323
  //        ^ (depth 0, index 2)
89324
  //    ```
89325
  //
89326
  } else if (!is_open()) {
89327
#if SIMDJSON_DEVELOPMENT_CHECKS
89328
    // If we're past the end of the object, we're being iterated out of order.
89329
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
89330
    // this object iterator will blithely scan that object for fields.
89331
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
89332
#endif
89333
    return false;
89334
89335
  // 3. When a previous search found a field or an iterator yielded a value:
89336
  //
89337
  //    ```
89338
  //    // When a field was not fully consumed (or not even touched at all)
89339
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89340
  //           ^ (depth 2)
89341
  //    // When a field was fully consumed
89342
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89343
  //                   ^ (depth 1)
89344
  //    // When the last field was fully consumed
89345
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89346
  //                                   ^ (depth 1)
89347
  //    ```
89348
  //
89349
  } else {
89350
    if ((error = skip_child() )) { abandon(); return error; }
89351
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
89352
#if SIMDJSON_DEVELOPMENT_CHECKS
89353
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
89354
#endif
89355
  }
89356
  while (has_value) {
89357
    // Get the key and colon, stopping at the value.
89358
    raw_json_string actual_key;
89359
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
89360
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
89361
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
89362
    // The depth is left unchanged by field_key().
89363
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
89364
    // field_value() will advance and check that we find a ':' separating the
89365
    // key and the value. It will also increment the depth by one.
89366
    if ((error = field_value() )) { abandon(); return error; }
89367
    // If it matches, stop and return
89368
    // We could do it this way if we wanted to allow arbitrary
89369
    // key content (including escaped quotes).
89370
    //if (actual_key.unsafe_is_equal(max_key_length, key)) {
89371
    // Instead we do the following which may trigger buffer overruns if the
89372
    // user provides an adversarial key (containing a well placed unescaped quote
89373
    // character and being longer than the number of bytes remaining in the JSON
89374
    // input).
89375
    if (actual_key.unsafe_is_equal(key)) {
89376
      logger::log_event(*this, "match", key, -2);
89377
      // If we return here, then we return while pointing at the ':' that we just checked.
89378
      return true;
89379
    }
89380
89381
    // No match: skip the value and see if , or } is next
89382
    logger::log_event(*this, "no match", key, -2);
89383
    // The call to skip_child is meant to skip over the value corresponding to the key.
89384
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
89385
    SIMDJSON_TRY( skip_child() ); // Skip the value entirely
89386
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
89387
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
89388
    // then we are in error and we abort.
89389
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
89390
  }
89391
89392
  // If the loop ended, we're out of fields to look at.
89393
  return false;
89394
}
89395
89396
SIMDJSON_PUSH_DISABLE_WARNINGS
89397
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
89398
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
89399
  /**
89400
   * When find_field_unordered_raw is called, we can either be pointing at the
89401
   * first key, pointing outside (at the closing brace) or if a key was matched
89402
   * we can be either pointing right afterthe ':' right before the value (that we need skip),
89403
   * or we may have consumed the value and we might be at a comma or at the
89404
   * final brace (ready for a call to has_next_field()).
89405
   */
89406
  error_code error;
89407
  bool has_value;
89408
89409
  // First, we scan from that point to the end.
89410
  // If we don't find a match, we may loop back around, and scan from the beginning to that point.
89411
  token_position search_start = _json_iter->position();
89412
89413
  // We want to know whether we need to go back to the beginning.
89414
  bool at_first = at_first_field();
89415
  ///////////////
89416
  // Initially, the object can be in one of a few different places:
89417
  //
89418
  // 1. At the first key:
89419
  //
89420
  //    ```
89421
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89422
  //      ^ (depth 2, index 1)
89423
  //    ```
89424
  //
89425
  if (at_first) {
89426
    has_value = true;
89427
89428
  // 2. When a previous search did not yield a value or the object is empty:
89429
  //
89430
  //    ```
89431
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89432
  //                                     ^ (depth 0)
89433
  //    { }
89434
  //        ^ (depth 0, index 2)
89435
  //    ```
89436
  //
89437
  } else if (!is_open()) {
89438
89439
#if SIMDJSON_DEVELOPMENT_CHECKS
89440
    // If we're past the end of the object, we're being iterated out of order.
89441
    // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
89442
    // this object iterator will blithely scan that object for fields.
89443
    if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
89444
#endif
89445
    SIMDJSON_TRY(reset_object().get(has_value));
89446
    at_first = true;
89447
  // 3. When a previous search found a field or an iterator yielded a value:
89448
  //
89449
  //    ```
89450
  //    // When a field was not fully consumed (or not even touched at all)
89451
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89452
  //           ^ (depth 2)
89453
  //    // When a field was fully consumed
89454
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89455
  //                   ^ (depth 1)
89456
  //    // When the last field was fully consumed
89457
  //    { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89458
  //                                   ^ (depth 1)
89459
  //    ```
89460
  //
89461
  } else {
89462
    // If someone queried a key but they not did access the value, then we are left pointing
89463
    // at the ':' and we need to move forward through the value... If the value was
89464
    // processed then skip_child() does not move the iterator (but may adjust the depth).
89465
    if ((error = skip_child() )) { abandon(); return error; }
89466
    search_start = _json_iter->position();
89467
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
89468
#if SIMDJSON_DEVELOPMENT_CHECKS
89469
    if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
89470
#endif
89471
  }
89472
89473
  // After initial processing, we will be in one of two states:
89474
  //
89475
  // ```
89476
  // // At the beginning of a field
89477
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89478
  //   ^ (depth 1)
89479
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89480
  //                  ^ (depth 1)
89481
  // // At the end of the object
89482
  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
89483
  //                                  ^ (depth 0)
89484
  // ```
89485
  //
89486
  // Next, we find a match starting from the current position.
89487
  while (has_value) {
89488
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
89489
89490
    // Get the key and colon, stopping at the value.
89491
    raw_json_string actual_key;
89492
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
89493
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
89494
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
89495
    // The depth is left unchanged by field_key().
89496
    if ((error = field_key().get(actual_key) )) { abandon(); return error; };
89497
    // field_value() will advance and check that we find a ':' separating the
89498
    // key and the value. It will also increment the depth by one.
89499
    if ((error = field_value() )) { abandon(); return error; }
89500
89501
    // If it matches, stop and return
89502
    // We could do it this way if we wanted to allow arbitrary
89503
    // key content (including escaped quotes).
89504
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
89505
    // Instead we do the following which may trigger buffer overruns if the
89506
    // user provides an adversarial key (containing a well placed unescaped quote
89507
    // character and being longer than the number of bytes remaining in the JSON
89508
    // input).
89509
    if (actual_key.unsafe_is_equal(key)) {
89510
      logger::log_event(*this, "match", key, -2);
89511
      // If we return here, then we return while pointing at the ':' that we just checked.
89512
      return true;
89513
    }
89514
89515
    // No match: skip the value and see if , or } is next
89516
    logger::log_event(*this, "no match", key, -2);
89517
    // The call to skip_child is meant to skip over the value corresponding to the key.
89518
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
89519
    SIMDJSON_TRY( skip_child() );
89520
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
89521
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
89522
    // then we are in error and we abort.
89523
    if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
89524
  }
89525
  // Performance note: it maybe wasteful to rewind to the beginning when there might be
89526
  // no other query following. Indeed, it would require reskipping the whole object.
89527
  // Instead, you can just stay where you are. If there is a new query, there is always time
89528
  // to rewind.
89529
  if(at_first) { return false; }
89530
89531
  // If we reach the end without finding a match, search the rest of the fields starting at the
89532
  // beginning of the object.
89533
  // (We have already run through the object before, so we've already validated its structure. We
89534
  // don't check errors in this bit.)
89535
  SIMDJSON_TRY(reset_object().get(has_value));
89536
  while (true) {
89537
    SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
89538
    SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
89539
89540
    // Get the key and colon, stopping at the value.
89541
    raw_json_string actual_key;
89542
    // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
89543
    // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
89544
    // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
89545
    // The depth is left unchanged by field_key().
89546
    error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
89547
    // field_value() will advance and check that we find a ':' separating the
89548
    // key and the value.  It will also increment the depth by one.
89549
    error = field_value(); SIMDJSON_ASSUME(!error);
89550
89551
    // If it matches, stop and return
89552
    // We could do it this way if we wanted to allow arbitrary
89553
    // key content (including escaped quotes).
89554
    // if (actual_key.unsafe_is_equal(max_key_length, key)) {
89555
    // Instead we do the following which may trigger buffer overruns if the
89556
    // user provides an adversarial key (containing a well placed unescaped quote
89557
    // character and being longer than the number of bytes remaining in the JSON
89558
    // input).
89559
    if (actual_key.unsafe_is_equal(key)) {
89560
      logger::log_event(*this, "match", key, -2);
89561
      // If we return here, then we return while pointing at the ':' that we just checked.
89562
      return true;
89563
    }
89564
89565
    // No match: skip the value and see if , or } is next
89566
    logger::log_event(*this, "no match", key, -2);
89567
    // The call to skip_child is meant to skip over the value corresponding to the key.
89568
    // After skip_child(), we are right before the next comma (',') or the final brace ('}').
89569
    SIMDJSON_TRY( skip_child() );
89570
    // If we reached the end of the key-value pair we started from, then we know
89571
    // that the key is not there so we return false. We are either right before
89572
    // the next comma or the final brace.
89573
    if(_json_iter->position() == search_start) { return false; }
89574
    // The has_next_field() advances the pointer and check that either ',' or '}' is found.
89575
    // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
89576
    // then we are in error and we abort.
89577
    error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
89578
    // If we make the mistake of exiting here, then we could be left pointing at a key
89579
    // in the middle of an object. That's not an allowable state.
89580
  }
89581
  // If the loop ended, we're out of fields to look at. The program should
89582
  // never reach this point.
89583
  return false;
89584
}
89585
SIMDJSON_POP_DISABLE_WARNINGS
89586
89587
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
89588
  assert_at_next();
89589
89590
  const uint8_t *key = _json_iter->return_current_and_advance();
89591
  if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
89592
  return raw_json_string(key);
89593
}
89594
89595
simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
89596
  assert_at_next();
89597
89598
  if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
89599
  _json_iter->descend_to(depth()+1);
89600
  return SUCCESS;
89601
}
89602
89603
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
89604
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
89605
  return started_array();
89606
}
89607
89608
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
89609
  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
89610
  return started_root_array();
89611
}
89612
89613
inline std::string value_iterator::to_string() const noexcept {
89614
  auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
89615
  if(_json_iter != nullptr) { answer +=  _json_iter->to_string(); }
89616
  answer += std::string(" ]");
89617
  return answer;
89618
}
89619
89620
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
89621
  assert_at_container_start();
89622
  if (*_json_iter->peek() == ']') {
89623
    logger::log_value(*_json_iter, "empty array");
89624
    _json_iter->return_current_and_advance();
89625
    SIMDJSON_TRY( end_container() );
89626
    return false;
89627
  }
89628
  _json_iter->descend_to(depth()+1);
89629
#if SIMDJSON_DEVELOPMENT_CHECKS
89630
  _json_iter->set_start_position(_depth, start_position());
89631
#endif
89632
  return true;
89633
}
89634
89635
simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
89636
  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
89637
  // current document. It only works in the normal mode where we have indexed a single document.
89638
  // Note that adding a check for 'streaming' is not expensive since we only have at most
89639
  // one root element.
89640
  if ( ! _json_iter->streaming() ) {
89641
    // The following lines do not fully protect against garbage content within the
89642
    // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
89643
    // also call `at_end()` on the document instance at the end of the processing to
89644
    // ensure that the processing has finished at the end.
89645
    //
89646
    if (*_json_iter->peek_last() != ']') {
89647
      _json_iter->abandon();
89648
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
89649
    }
89650
    // If the last character is ] *and* the first gibberish character is also ']'
89651
    // then on-demand could accidentally go over. So we need additional checks.
89652
    // https://github.com/simdjson/simdjson/issues/1834
89653
    // Checking that the document is balanced requires a full scan which is potentially
89654
    // expensive, but it only happens in edge cases where the first padding character is
89655
    // a closing bracket.
89656
    if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
89657
      _json_iter->abandon();
89658
      // The exact error would require more work. It will typically be an unclosed array.
89659
      return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
89660
    }
89661
  }
89662
  return SUCCESS;
89663
}
89664
89665
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
89666
  auto error = check_root_array();
89667
  if (error) { return error; }
89668
  return started_array();
89669
}
89670
89671
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
89672
  assert_at_next();
89673
89674
  logger::log_event(*this, "has_next_element");
89675
  switch (*_json_iter->return_current_and_advance()) {
89676
    case ']':
89677
      logger::log_end_value(*_json_iter, "array");
89678
      SIMDJSON_TRY( end_container() );
89679
      return false;
89680
    case ',':
89681
      _json_iter->descend_to(depth()+1);
89682
      return true;
89683
    default:
89684
      return report_error(TAPE_ERROR, "Missing comma between array elements");
89685
  }
89686
}
89687
89688
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
89689
  auto not_true = atomparsing::str4ncmp(json, "true");
89690
  auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
89691
  bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
89692
  if (error) { return incorrect_type_error("Not a boolean"); }
89693
  return simdjson_result<bool>(!not_true);
89694
}
89695
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
89696
  bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
89697
  // if we start with 'n', we must be a null
89698
  if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
89699
  return is_null_string;
89700
}
89701
89702
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
89703
  return get_raw_json_string().unescape(json_iter(), allow_replacement);
89704
}
89705
template <typename string_type>
89706
simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
89707
  std::string_view content;
89708
  auto err = get_string(allow_replacement).get(content);
89709
  if (err) { return err; }
89710
  receiver = content;
89711
  return SUCCESS;
89712
}
89713
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
89714
  return get_raw_json_string().unescape_wobbly(json_iter());
89715
}
89716
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
89717
  auto json = peek_scalar("string");
89718
  if (*json != '"') { return incorrect_type_error("Not a string"); }
89719
  advance_scalar("string");
89720
  return raw_json_string(json+1);
89721
}
89722
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
89723
  auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
89724
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
89725
  return result;
89726
}
89727
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
89728
  auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
89729
  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
89730
  return result;
89731
}
89732
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
89733
  auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
89734
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
89735
  return result;
89736
}
89737
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
89738
  auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
89739
  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
89740
  return result;
89741
}
89742
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
89743
  auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
89744
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
89745
  return result;
89746
}
89747
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
89748
  auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
89749
  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
89750
  return result;
89751
}
89752
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
89753
  auto result = parse_bool(peek_non_root_scalar("bool"));
89754
  if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
89755
  return result;
89756
}
89757
simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
89758
  bool is_null_value;
89759
  SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
89760
  if(is_null_value) { advance_non_root_scalar("null"); }
89761
  return is_null_value;
89762
}
89763
simdjson_inline bool value_iterator::is_negative() noexcept {
89764
  return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
89765
}
89766
simdjson_inline bool value_iterator::is_root_negative() noexcept {
89767
  return numberparsing::is_negative(peek_root_scalar("numbersign"));
89768
}
89769
simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
89770
  return numberparsing::is_integer(peek_non_root_scalar("integer"));
89771
}
89772
simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
89773
  return numberparsing::get_number_type(peek_non_root_scalar("integer"));
89774
}
89775
simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
89776
  number num;
89777
  error_code error =  numberparsing::parse_number(peek_non_root_scalar("number"), num);
89778
  if(error) { return error; }
89779
  return num;
89780
}
89781
89782
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
89783
  auto max_len = peek_root_length();
89784
  auto json = peek_root_scalar("is_root_integer");
89785
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
89786
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
89787
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
89788
    return false; // if there are more than 20 characters, it cannot be represented as an integer.
89789
  }
89790
  auto answer = numberparsing::is_integer(tmpbuf);
89791
  // If the parsing was a success, we must still check that it is
89792
  // a single scalar. Note that we parse first because of cases like '[]' where
89793
  // getting TRAILING_CONTENT is wrong.
89794
  if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
89795
  return answer;
89796
}
89797
89798
simdjson_inline simdjson_result<westmere::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
89799
  auto max_len = peek_root_length();
89800
  auto json = peek_root_scalar("number");
89801
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
89802
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
89803
  // number: -0.<fraction>e-308.
89804
  uint8_t tmpbuf[1074+8+1+1];
89805
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
89806
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
89807
    if(numberparsing::check_if_integer(json, max_len)) {
89808
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89809
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
89810
      return number_type::big_integer;
89811
    }
89812
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
89813
    return NUMBER_ERROR;
89814
  }
89815
  auto answer = numberparsing::get_number_type(tmpbuf);
89816
  if (check_trailing && (answer.error() == SUCCESS)  && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89817
  return answer;
89818
}
89819
simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
89820
  auto max_len = peek_root_length();
89821
  auto json = peek_root_scalar("number");
89822
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
89823
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
89824
  // number: -0.<fraction>e-308.
89825
  // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
89826
  uint8_t tmpbuf[1074+8+1+1];
89827
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
89828
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
89829
    if(numberparsing::check_if_integer(json, max_len)) {
89830
      if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89831
      logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
89832
      return BIGINT_ERROR;
89833
    }
89834
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
89835
    return NUMBER_ERROR;
89836
  }
89837
  number num;
89838
  error_code error =  numberparsing::parse_number(tmpbuf, num);
89839
  if(error) { return error; }
89840
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89841
  advance_root_scalar("number");
89842
  return num;
89843
}
89844
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
89845
  return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
89846
}
89847
template <typename string_type>
89848
simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
89849
  std::string_view content;
89850
  auto err = get_root_string(check_trailing, allow_replacement).get(content);
89851
  if (err) { return err; }
89852
  receiver = content;
89853
  return SUCCESS;
89854
}
89855
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
89856
  return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
89857
}
89858
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
89859
  auto json = peek_scalar("string");
89860
  if (*json != '"') { return incorrect_type_error("Not a string"); }
89861
  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89862
  advance_scalar("string");
89863
  return raw_json_string(json+1);
89864
}
89865
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
89866
  auto max_len = peek_root_length();
89867
  auto json = peek_root_scalar("uint64");
89868
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
89869
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
89870
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
89871
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
89872
    return NUMBER_ERROR;
89873
  }
89874
  auto result = numberparsing::parse_unsigned(tmpbuf);
89875
  if(result.error() == SUCCESS) {
89876
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89877
    advance_root_scalar("uint64");
89878
  }
89879
  return result;
89880
}
89881
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
89882
  auto max_len = peek_root_length();
89883
  auto json = peek_root_scalar("uint64");
89884
  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
89885
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
89886
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
89887
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
89888
    return NUMBER_ERROR;
89889
  }
89890
  auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
89891
  if(result.error() == SUCCESS) {
89892
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89893
    advance_root_scalar("uint64");
89894
  }
89895
  return result;
89896
}
89897
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
89898
  auto max_len = peek_root_length();
89899
  auto json = peek_root_scalar("int64");
89900
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
89901
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
89902
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
89903
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
89904
    return NUMBER_ERROR;
89905
  }
89906
89907
  auto result = numberparsing::parse_integer(tmpbuf);
89908
  if(result.error() == SUCCESS) {
89909
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89910
    advance_root_scalar("int64");
89911
  }
89912
  return result;
89913
}
89914
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
89915
  auto max_len = peek_root_length();
89916
  auto json = peek_root_scalar("int64");
89917
  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
89918
  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
89919
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
89920
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
89921
    return NUMBER_ERROR;
89922
  }
89923
89924
  auto result = numberparsing::parse_integer_in_string(tmpbuf);
89925
  if(result.error() == SUCCESS) {
89926
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89927
    advance_root_scalar("int64");
89928
  }
89929
  return result;
89930
}
89931
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
89932
  auto max_len = peek_root_length();
89933
  auto json = peek_root_scalar("double");
89934
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
89935
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
89936
  // number: -0.<fraction>e-308.
89937
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
89938
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
89939
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
89940
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
89941
    return NUMBER_ERROR;
89942
  }
89943
  auto result = numberparsing::parse_double(tmpbuf);
89944
  if(result.error() == SUCCESS) {
89945
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89946
    advance_root_scalar("double");
89947
  }
89948
  return result;
89949
}
89950
89951
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
89952
  auto max_len = peek_root_length();
89953
  auto json = peek_root_scalar("double");
89954
  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
89955
  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
89956
  // number: -0.<fraction>e-308.
89957
  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
89958
  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
89959
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
89960
    logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
89961
    return NUMBER_ERROR;
89962
  }
89963
  auto result = numberparsing::parse_double_in_string(tmpbuf);
89964
  if(result.error() == SUCCESS) {
89965
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89966
    advance_root_scalar("double");
89967
  }
89968
  return result;
89969
}
89970
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
89971
  auto max_len = peek_root_length();
89972
  auto json = peek_root_scalar("bool");
89973
  uint8_t tmpbuf[5+1+1]; // +1 for null termination
89974
  tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
89975
  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
89976
  auto result = parse_bool(tmpbuf);
89977
  if(result.error() == SUCCESS) {
89978
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89979
    advance_root_scalar("bool");
89980
  }
89981
  return result;
89982
}
89983
simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
89984
  auto max_len = peek_root_length();
89985
  auto json = peek_root_scalar("null");
89986
  bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
89987
         (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
89988
  if(result) { // we have something that looks like a null.
89989
    if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
89990
    advance_root_scalar("null");
89991
  }
89992
  return result;
89993
}
89994
89995
simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
89996
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
89997
  SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
89998
89999
  return _json_iter->skip_child(depth());
90000
}
90001
90002
simdjson_inline value_iterator value_iterator::child() const noexcept {
90003
  assert_at_child();
90004
  return { _json_iter, depth()+1, _json_iter->token.position() };
90005
}
90006
90007
// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
90008
// relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
90009
// marked non-inline.
90010
SIMDJSON_PUSH_DISABLE_WARNINGS
90011
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
90012
simdjson_inline bool value_iterator::is_open() const noexcept {
90013
  return _json_iter->depth() >= depth();
90014
}
90015
SIMDJSON_POP_DISABLE_WARNINGS
90016
90017
simdjson_inline bool value_iterator::at_end() const noexcept {
90018
  return _json_iter->at_end();
90019
}
90020
90021
simdjson_inline bool value_iterator::at_start() const noexcept {
90022
  return _json_iter->token.position() == start_position();
90023
}
90024
90025
simdjson_inline bool value_iterator::at_first_field() const noexcept {
90026
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
90027
  return _json_iter->token.position() == start_position() + 1;
90028
}
90029
90030
simdjson_inline void value_iterator::abandon() noexcept {
90031
  _json_iter->abandon();
90032
}
90033
90034
simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
90035
  return _depth;
90036
}
90037
simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
90038
  return _json_iter->error;
90039
}
90040
simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
90041
  return _json_iter->string_buf_loc();
90042
}
90043
simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
90044
  return *_json_iter;
90045
}
90046
simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
90047
  return *_json_iter;
90048
}
90049
90050
simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
90051
  return _json_iter->peek(start_position());
90052
}
90053
simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
90054
  return _json_iter->peek_length(start_position());
90055
}
90056
simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
90057
  return _json_iter->peek_root_length(start_position());
90058
}
90059
90060
simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
90061
  logger::log_value(*_json_iter, start_position(), depth(), type);
90062
  // If we're not at the position anymore, we don't want to advance the cursor.
90063
  if (!is_at_start()) { return peek_start(); }
90064
90065
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
90066
  assert_at_start();
90067
  return _json_iter->peek();
90068
}
90069
90070
simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
90071
  logger::log_value(*_json_iter, start_position(), depth(), type);
90072
  // If we're not at the position anymore, we don't want to advance the cursor.
90073
  if (!is_at_start()) { return; }
90074
90075
  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
90076
  assert_at_start();
90077
  _json_iter->return_current_and_advance();
90078
  _json_iter->ascend_to(depth()-1);
90079
}
90080
90081
simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
90082
  logger::log_start_value(*_json_iter, start_position(), depth(), type);
90083
  // If we're not at the position anymore, we don't want to advance the cursor.
90084
  const uint8_t *json;
90085
  if (!is_at_start()) {
90086
#if SIMDJSON_DEVELOPMENT_CHECKS
90087
    if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
90088
#endif
90089
    json = peek_start();
90090
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
90091
  } else {
90092
    assert_at_start();
90093
    /**
90094
     * We should be prudent. Let us peek. If it is not the right type, we
90095
     * return an error. Only once we have determined that we have the right
90096
     * type are we allowed to advance!
90097
     */
90098
    json = _json_iter->peek();
90099
    if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
90100
    _json_iter->return_current_and_advance();
90101
  }
90102
90103
90104
  return SUCCESS;
90105
}
90106
90107
90108
simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
90109
  logger::log_value(*_json_iter, start_position(), depth(), type);
90110
  if (!is_at_start()) { return peek_start(); }
90111
90112
  assert_at_root();
90113
  return _json_iter->peek();
90114
}
90115
simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
90116
  logger::log_value(*_json_iter, start_position(), depth(), type);
90117
  if (!is_at_start()) { return peek_start(); }
90118
90119
  assert_at_non_root_start();
90120
  return _json_iter->peek();
90121
}
90122
90123
simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
90124
  logger::log_value(*_json_iter, start_position(), depth(), type);
90125
  if (!is_at_start()) { return; }
90126
90127
  assert_at_root();
90128
  _json_iter->return_current_and_advance();
90129
  _json_iter->ascend_to(depth()-1);
90130
}
90131
simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
90132
  logger::log_value(*_json_iter, start_position(), depth(), type);
90133
  if (!is_at_start()) { return; }
90134
90135
  assert_at_non_root_start();
90136
  _json_iter->return_current_and_advance();
90137
  _json_iter->ascend_to(depth()-1);
90138
}
90139
90140
simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
90141
  logger::log_error(*_json_iter, start_position(), depth(), message);
90142
  return INCORRECT_TYPE;
90143
}
90144
90145
simdjson_inline bool value_iterator::is_at_start() const noexcept {
90146
  return position() == start_position();
90147
}
90148
90149
simdjson_inline bool value_iterator::is_at_key() const noexcept {
90150
  // Keys are at the same depth as the object.
90151
  // Note here that we could be safer and check that we are within an object,
90152
  // but we do not.
90153
  return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
90154
}
90155
90156
simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
90157
  // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
90158
  auto delta = position() - start_position();
90159
  return delta == 1 || delta == 2;
90160
}
90161
90162
inline void value_iterator::assert_at_start() const noexcept {
90163
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
90164
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
90165
  SIMDJSON_ASSUME( _depth > 0 );
90166
}
90167
90168
inline void value_iterator::assert_at_container_start() const noexcept {
90169
  SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
90170
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
90171
  SIMDJSON_ASSUME( _depth > 0 );
90172
}
90173
90174
inline void value_iterator::assert_at_next() const noexcept {
90175
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
90176
  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
90177
  SIMDJSON_ASSUME( _depth > 0 );
90178
}
90179
90180
simdjson_inline void value_iterator::move_at_start() noexcept {
90181
  _json_iter->_depth = _depth;
90182
  _json_iter->token.set_position(_start_position);
90183
}
90184
90185
simdjson_inline void value_iterator::move_at_container_start() noexcept {
90186
  _json_iter->_depth = _depth;
90187
  _json_iter->token.set_position(_start_position + 1);
90188
}
90189
90190
simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
90191
  if(error()) { return error(); }
90192
  move_at_container_start();
90193
  return started_array();
90194
}
90195
90196
simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
90197
  if(error()) { return error(); }
90198
  move_at_container_start();
90199
  return started_object();
90200
}
90201
90202
inline void value_iterator::assert_at_child() const noexcept {
90203
  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
90204
  SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
90205
  SIMDJSON_ASSUME( _depth > 0 );
90206
}
90207
90208
inline void value_iterator::assert_at_root() const noexcept {
90209
  assert_at_start();
90210
  SIMDJSON_ASSUME( _depth == 1 );
90211
}
90212
90213
inline void value_iterator::assert_at_non_root_start() const noexcept {
90214
  assert_at_start();
90215
  SIMDJSON_ASSUME( _depth > 1 );
90216
}
90217
90218
inline void value_iterator::assert_is_valid() const noexcept {
90219
  SIMDJSON_ASSUME( _json_iter != nullptr );
90220
}
90221
90222
simdjson_inline bool value_iterator::is_valid() const noexcept {
90223
  return _json_iter != nullptr;
90224
}
90225
90226
simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
90227
  switch (*peek_start()) {
90228
    case '{':
90229
      return json_type::object;
90230
    case '[':
90231
      return json_type::array;
90232
    case '"':
90233
      return json_type::string;
90234
    case 'n':
90235
      return json_type::null;
90236
    case 't': case 'f':
90237
      return json_type::boolean;
90238
    case '-':
90239
    case '0': case '1': case '2': case '3': case '4':
90240
    case '5': case '6': case '7': case '8': case '9':
90241
      return json_type::number;
90242
    default:
90243
      return TAPE_ERROR;
90244
  }
90245
}
90246
90247
simdjson_inline token_position value_iterator::start_position() const noexcept {
90248
  return _start_position;
90249
}
90250
90251
simdjson_inline token_position value_iterator::position() const noexcept {
90252
  return _json_iter->position();
90253
}
90254
90255
simdjson_inline token_position value_iterator::end_position() const noexcept {
90256
  return _json_iter->end_position();
90257
}
90258
90259
simdjson_inline token_position value_iterator::last_position() const noexcept {
90260
  return _json_iter->last_position();
90261
}
90262
90263
simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
90264
  return _json_iter->report_error(error, message);
90265
}
90266
90267
} // namespace ondemand
90268
} // namespace westmere
90269
} // namespace simdjson
90270
90271
namespace simdjson {
90272
90273
simdjson_inline simdjson_result<westmere::ondemand::value_iterator>::simdjson_result(westmere::ondemand::value_iterator &&value) noexcept
90274
    : implementation_simdjson_result_base<westmere::ondemand::value_iterator>(std::forward<westmere::ondemand::value_iterator>(value)) {}
90275
simdjson_inline simdjson_result<westmere::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
90276
    : implementation_simdjson_result_base<westmere::ondemand::value_iterator>(error) {}
90277
90278
} // namespace simdjson
90279
90280
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
90281
/* end file simdjson/generic/ondemand/value_iterator-inl.h for westmere */
90282
/* end file simdjson/generic/ondemand/amalgamated.h for westmere */
90283
/* including simdjson/westmere/end.h: #include "simdjson/westmere/end.h" */
90284
/* begin file simdjson/westmere/end.h */
90285
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
90286
/* amalgamation skipped (editor-only): #include "simdjson/westmere/base.h" */
90287
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
90288
90289
#if !SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
90290
SIMDJSON_UNTARGET_REGION
90291
#endif
90292
90293
/* undefining SIMDJSON_IMPLEMENTATION from "westmere" */
90294
#undef SIMDJSON_IMPLEMENTATION
90295
/* end file simdjson/westmere/end.h */
90296
90297
#endif // SIMDJSON_WESTMERE_IMPLEMENTATION_H
90298
/* end file simdjson/westmere/ondemand.h */
90299
#else
90300
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
90301
#endif
90302
90303
/* undefining SIMDJSON_CONDITIONAL_INCLUDE */
90304
#undef SIMDJSON_CONDITIONAL_INCLUDE
90305
90306
namespace simdjson {
90307
  /**
90308
   * @copydoc simdjson::SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand
90309
   */
90310
  namespace ondemand = SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand;
90311
} // namespace simdjson
90312
90313
#endif // SIMDJSON_BUILTIN_ONDEMAND_H
90314
/* end file simdjson/builtin/ondemand.h */
90315
90316
namespace simdjson {
90317
  /**
90318
   * @copydoc simdjson::builtin::ondemand
90319
   */
90320
  namespace ondemand = builtin::ondemand;
90321
} // namespace simdjson
90322
90323
#endif // SIMDJSON_ONDEMAND_H
90324
/* end file simdjson/ondemand.h */
90325
90326
#endif // SIMDJSON_H
90327
/* end file simdjson.h */