char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
53f925074
char/aliceai-t5-moe
1// __ _____ _____ _____ 2// __| | __| | | | JSON for Modern C++ 3// | | |__ | | | | | | version 3.12.0 4// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5// 6// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 7// SPDX-License-Identifier: MIT 8 9/****************************************************************************\ 10* Note on documentation: The source files contain links to the online * 11* documentation of the public API at https://json.nlohmann.me. This URL * 12* contains the most recent documentation and should also be applicable to * 13* previous versions; documentation for deprecated functions is not * 14* removed, but marked deprecated. See "Generate documentation" section in * 15* file docs/README.md. * 16\****************************************************************************/ 17 18#ifndef INCLUDE_NLOHMANN_JSON_HPP_ 19#define INCLUDE_NLOHMANN_JSON_HPP_ 20 21#include <algorithm> // all_of, find, for_each 22#include <cstddef> // nullptr_t, ptrdiff_t, size_t 23#include <functional> // hash, less 24#include <initializer_list> // initializer_list 25#ifndef JSON_NO_IO 26#include <iosfwd> // istream, ostream 27#endif // JSON_NO_IO 28#include <iterator> // random_access_iterator_tag 29#include <memory> // unique_ptr 30#include <string> // string, stoi, to_string 31#include <utility> // declval, forward, move, pair, swap 32#include <vector> // vector 33 34// #include <nlohmann/adl_serializer.hpp> 35// __ _____ _____ _____ 36// __| | __| | | | JSON for Modern C++ 37// | | |__ | | | | | | version 3.12.0 38// |_____|_____|_____|_|___| https://github.com/nlohmann/json 39// 40// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 41// SPDX-License-Identifier: MIT 42 43 44 45#include <utility> 46 47// #include <nlohmann/detail/abi_macros.hpp> 48// __ _____ _____ _____ 49// __| | __| | | | JSON for Modern C++ 50// | | |__ | | | | | | version 3.12.0 51// |_____|_____|_____|_|___| https://github.com/nlohmann/json 52// 53// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 54// SPDX-License-Identifier: MIT 55 56 57 58// This file contains all macro definitions affecting or depending on the ABI 59 60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK 61#if defined(NLOHMANN_JSON_VERSION_MAJOR )&& defined(NLOHMANN_JSON_VERSION_MINOR )&& defined(NLOHMANN_JSON_VERSION_PATCH ) 62#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0 63#warning "Already included a different version of the library!" 64#endif 65#endif 66#endif 67 68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) 69#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum) 70#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum) 71 72#ifndef JSON_DIAGNOSTICS 73#define JSON_DIAGNOSTICS 0 74#endif 75 76#ifndef JSON_DIAGNOSTIC_POSITIONS 77#define JSON_DIAGNOSTIC_POSITIONS 0 78#endif 79 80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 81#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 82#endif 83 84#if JSON_DIAGNOSTICS 85#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag 86#else 87#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS 88#endif 89 90#if JSON_DIAGNOSTIC_POSITIONS 91#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp 92#else 93#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS 94#endif 95 96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 97#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp 98#else 99#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON 100#endif 101 102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION 103#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 104#endif 105 106// Construct the namespace ABI tags component 107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX (a ,b ,c ) json_abi ## a ## b ## c 108#define NLOHMANN_JSON_ABI_TAGS_CONCAT (a ,b ,c ) \ 109 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) 110 111#define NLOHMANN_JSON_ABI_TAGS \ 112 NLOHMANN_JSON_ABI_TAGS_CONCAT( \ 113 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ 114 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ 115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) 116 117// Construct the namespace version component 118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX (major ,minor ,patch ) \ 119 _v ## major ## _ ## minor ## _ ## patch 120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT (major ,minor ,patch ) \ 121 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) 122 123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION 124#define NLOHMANN_JSON_NAMESPACE_VERSION 125#else 126#define NLOHMANN_JSON_NAMESPACE_VERSION \ 127 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ 128 NLOHMANN_JSON_VERSION_MINOR, \ 129 NLOHMANN_JSON_VERSION_PATCH) 130#endif 131 132// Combine namespace components 133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX (a ,b ) a ## b 134#define NLOHMANN_JSON_NAMESPACE_CONCAT (a ,b ) \ 135 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) 136 137#ifndef NLOHMANN_JSON_NAMESPACE 138#define NLOHMANN_JSON_NAMESPACE \ 139 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ 140 NLOHMANN_JSON_ABI_TAGS, \ 141 NLOHMANN_JSON_NAMESPACE_VERSION) 142#endif 143 144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN 145#define NLOHMANN_JSON_NAMESPACE_BEGIN \ 146 namespace nlohmann \ 147 { \ 148 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ 149 NLOHMANN_JSON_ABI_TAGS, \ 150 NLOHMANN_JSON_NAMESPACE_VERSION) \ 151 { 152#endif 153 154#ifndef NLOHMANN_JSON_NAMESPACE_END 155#define NLOHMANN_JSON_NAMESPACE_END \ 156 }/* namespace (inline namespace) NOLINT(readability/namespace) */ \ 157 }// namespace nlohmann 158#endif 159 160// #include <nlohmann/detail/conversions/from_json.hpp> 161// __ _____ _____ _____ 162// __| | __| | | | JSON for Modern C++ 163// | | |__ | | | | | | version 3.12.0 164// |_____|_____|_____|_|___| https://github.com/nlohmann/json 165// 166// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 167// SPDX-License-Identifier: MIT 168 169 170 171#include <algorithm> // transform 172#include <array> // array 173#include <forward_list> // forward_list 174#include <iterator> // inserter, front_inserter, end 175#include <map> // map 176#ifdef JSON_HAS_CPP_17 177#include <optional> // optional 178#endif 179#include <string> // string 180#include <tuple> // tuple, make_tuple 181#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible 182#include <unordered_map> // unordered_map 183#include <utility> // pair, declval 184#include <valarray> // valarray 185 186// #include <nlohmann/detail/exceptions.hpp> 187// __ _____ _____ _____ 188// __| | __| | | | JSON for Modern C++ 189// | | |__ | | | | | | version 3.12.0 190// |_____|_____|_____|_|___| https://github.com/nlohmann/json 191// 192// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 193// SPDX-License-Identifier: MIT 194 195 196 197#include <cstddef> // nullptr_t 198#include <exception> // exception 199#if JSON_DIAGNOSTICS 200#include <numeric> // accumulate 201#endif 202#include <stdexcept> // runtime_error 203#include <string> // to_string 204#include <vector> // vector 205 206// #include <nlohmann/detail/value_t.hpp> 207// __ _____ _____ _____ 208// __| | __| | | | JSON for Modern C++ 209// | | |__ | | | | | | version 3.12.0 210// |_____|_____|_____|_|___| https://github.com/nlohmann/json 211// 212// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 213// SPDX-License-Identifier: MIT 214 215 216 217#include <array> // array 218#include <cstddef> // size_t 219#include <cstdint> // uint8_t 220#include <string> // string 221 222// #include <nlohmann/detail/macro_scope.hpp> 223// __ _____ _____ _____ 224// __| | __| | | | JSON for Modern C++ 225// | | |__ | | | | | | version 3.12.0 226// |_____|_____|_____|_|___| https://github.com/nlohmann/json 227// 228// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 229// SPDX-License-Identifier: MIT 230 231 232 233#include <utility> // declval, pair 234// #include <nlohmann/detail/meta/detected.hpp> 235// __ _____ _____ _____ 236// __| | __| | | | JSON for Modern C++ 237// | | |__ | | | | | | version 3.12.0 238// |_____|_____|_____|_|___| https://github.com/nlohmann/json 239// 240// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 241// SPDX-License-Identifier: MIT 242 243 244 245#include <type_traits> 246 247// #include <nlohmann/detail/meta/void_t.hpp> 248// __ _____ _____ _____ 249// __| | __| | | | JSON for Modern C++ 250// | | |__ | | | | | | version 3.12.0 251// |_____|_____|_____|_|___| https://github.com/nlohmann/json 252// 253// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 254// SPDX-License-Identifier: MIT 255 256 257 258// #include <nlohmann/detail/abi_macros.hpp> 259 260 261NLOHMANN_JSON_NAMESPACE_BEGIN 262namespace detail 263{ 264 265template < typename ...Ts > struct make_void 266{ 267using type = void ; 268}; 269template < typename ...Ts > using void_t = typename make_void < Ts ...> ::type ; 270 271}// namespace detail 272NLOHMANN_JSON_NAMESPACE_END 273 274 275NLOHMANN_JSON_NAMESPACE_BEGIN 276namespace detail 277{ 278 279// https://en.cppreference.com/w/cpp/experimental/is_detected 280struct nonesuch 281{ 282nonesuch ()= delete ; 283 ~nonesuch ()= delete ; 284nonesuch (nonesuch const & )= delete ; 285nonesuch (nonesuch const && )= delete ; 286void operator= (nonesuch const & )= delete ; 287void operator= (nonesuch && )= delete ; 288}; 289 290template < class Default , 291class AlwaysVoid , 292template < class ...> class Op , 293class ...Args > 294struct detector 295{ 296using value_t = std::false_type ; 297using type = Default ; 298}; 299 300template < class Default ,template < class ...> class Op ,class ...Args > 301struct detector < Default ,void_t < Op < Args ...>> ,Op ,Args ...> 302{ 303using value_t = std::true_type ; 304using type = Op < Args ...> ; 305}; 306 307template < template < class ...> class Op ,class ...Args > 308using is_detected = typename detector < nonesuch ,void ,Op ,Args ...> ::value_t ; 309 310template < template < class ...> class Op ,class ...Args > 311struct is_detected_lazy :is_detected < Op ,Args ...> { }; 312 313template < template < class ...> class Op ,class ...Args > 314using detected_t = typename detector < nonesuch ,void ,Op ,Args ...> ::type ; 315 316template < class Default ,template < class ...> class Op ,class ...Args > 317using detected_or = detector < Default ,void ,Op ,Args ...> ; 318 319template < class Default ,template < class ...> class Op ,class ...Args > 320using detected_or_t = typename detected_or < Default ,Op ,Args ...> ::type ; 321 322template < class Expected ,template < class ...> class Op ,class ...Args > 323using is_detected_exact = std::is_same < Expected ,detected_t < Op ,Args ...>> ; 324 325template < class To ,template < class ...> class Op ,class ...Args > 326using is_detected_convertible = 327 std::is_convertible < detected_t < Op ,Args ...> ,To > ; 328 329}// namespace detail 330NLOHMANN_JSON_NAMESPACE_END 331 332// #include <nlohmann/thirdparty/hedley/hedley.hpp> 333 334 335// __ _____ _____ _____ 336// __| | __| | | | JSON for Modern C++ 337// | | |__ | | | | | | version 3.12.0 338// |_____|_____|_____|_|___| https://github.com/nlohmann/json 339// 340// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 341// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com> 342// SPDX-License-Identifier: MIT 343 344/* Hedley - https://nemequ.github.io/hedley 345* Created by Evan Nemerson <evan@nemerson.com> 346*/ 347 348#if !defined(JSON_HEDLEY_VERSION )|| (JSON_HEDLEY_VERSION < 15 ) 349#if defined(JSON_HEDLEY_VERSION ) 350#undef JSON_HEDLEY_VERSION 351#endif 352#define JSON_HEDLEY_VERSION 15 353 354#if defined(JSON_HEDLEY_STRINGIFY_EX ) 355#undef JSON_HEDLEY_STRINGIFY_EX 356#endif 357#define JSON_HEDLEY_STRINGIFY_EX (x ) #x 358 359#if defined(JSON_HEDLEY_STRINGIFY ) 360#undef JSON_HEDLEY_STRINGIFY 361#endif 362#define JSON_HEDLEY_STRINGIFY (x ) JSON_HEDLEY_STRINGIFY_EX(x) 363 364#if defined(JSON_HEDLEY_CONCAT_EX ) 365#undef JSON_HEDLEY_CONCAT_EX 366#endif 367#define JSON_HEDLEY_CONCAT_EX (a ,b ) a##b 368 369#if defined(JSON_HEDLEY_CONCAT ) 370#undef JSON_HEDLEY_CONCAT 371#endif 372#define JSON_HEDLEY_CONCAT (a ,b ) JSON_HEDLEY_CONCAT_EX(a,b) 373 374#if defined(JSON_HEDLEY_CONCAT3_EX ) 375#undef JSON_HEDLEY_CONCAT3_EX 376#endif 377#define JSON_HEDLEY_CONCAT3_EX (a ,b ,c ) a##b##c 378 379#if defined(JSON_HEDLEY_CONCAT3 ) 380#undef JSON_HEDLEY_CONCAT3 381#endif 382#define JSON_HEDLEY_CONCAT3 (a ,b ,c ) JSON_HEDLEY_CONCAT3_EX(a,b,c) 383 384#if defined(JSON_HEDLEY_VERSION_ENCODE ) 385#undef JSON_HEDLEY_VERSION_ENCODE 386#endif 387#define JSON_HEDLEY_VERSION_ENCODE (major ,minor ,revision ) (((major) * 1000000) + ((minor) * 1000) + (revision)) 388 389#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR ) 390#undef JSON_HEDLEY_VERSION_DECODE_MAJOR 391#endif 392#define JSON_HEDLEY_VERSION_DECODE_MAJOR (version ) ((version) / 1000000) 393 394#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR ) 395#undef JSON_HEDLEY_VERSION_DECODE_MINOR 396#endif 397#define JSON_HEDLEY_VERSION_DECODE_MINOR (version ) (((version) % 1000000) / 1000) 398 399#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION ) 400#undef JSON_HEDLEY_VERSION_DECODE_REVISION 401#endif 402#define JSON_HEDLEY_VERSION_DECODE_REVISION (version ) ((version) % 1000) 403 404#if defined(JSON_HEDLEY_GNUC_VERSION ) 405#undef JSON_HEDLEY_GNUC_VERSION 406#endif 407#if defined(__GNUC__ )&& defined(__GNUC_PATCHLEVEL__ ) 408#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 409#elif defined(__GNUC__ ) 410#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) 411#endif 412 413#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK ) 414#undef JSON_HEDLEY_GNUC_VERSION_CHECK 415#endif 416#if defined(JSON_HEDLEY_GNUC_VERSION ) 417#define JSON_HEDLEY_GNUC_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 418#else 419#define JSON_HEDLEY_GNUC_VERSION_CHECK (major ,minor ,patch ) (0) 420#endif 421 422#if defined(JSON_HEDLEY_MSVC_VERSION ) 423#undef JSON_HEDLEY_MSVC_VERSION 424#endif 425#if defined(_MSC_FULL_VER )&& (_MSC_FULL_VER >=140000000 )&& !defined(__ICL ) 426#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) 427#elif defined(_MSC_FULL_VER )&& !defined(__ICL ) 428#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) 429#elif defined(_MSC_VER )&& !defined(__ICL ) 430#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) 431#endif 432 433#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK ) 434#undef JSON_HEDLEY_MSVC_VERSION_CHECK 435#endif 436#if !defined(JSON_HEDLEY_MSVC_VERSION ) 437#define JSON_HEDLEY_MSVC_VERSION_CHECK (major ,minor ,patch ) (0) 438#elif defined(_MSC_VER )&& (_MSC_VER >=1400 ) 439#define JSON_HEDLEY_MSVC_VERSION_CHECK (major ,minor ,patch ) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) 440#elif defined(_MSC_VER )&& (_MSC_VER >=1200 ) 441#define JSON_HEDLEY_MSVC_VERSION_CHECK (major ,minor ,patch ) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) 442#else 443#define JSON_HEDLEY_MSVC_VERSION_CHECK (major ,minor ,patch ) (_MSC_VER >= ((major * 100) + (minor))) 444#endif 445 446#if defined(JSON_HEDLEY_INTEL_VERSION ) 447#undef JSON_HEDLEY_INTEL_VERSION 448#endif 449#if defined(__INTEL_COMPILER )&& defined(__INTEL_COMPILER_UPDATE )&& !defined(__ICL ) 450#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) 451#elif defined(__INTEL_COMPILER )&& !defined(__ICL ) 452#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) 453#endif 454 455#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK ) 456#undef JSON_HEDLEY_INTEL_VERSION_CHECK 457#endif 458#if defined(JSON_HEDLEY_INTEL_VERSION ) 459#define JSON_HEDLEY_INTEL_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 460#else 461#define JSON_HEDLEY_INTEL_VERSION_CHECK (major ,minor ,patch ) (0) 462#endif 463 464#if defined(JSON_HEDLEY_INTEL_CL_VERSION ) 465#undef JSON_HEDLEY_INTEL_CL_VERSION 466#endif 467#if defined(__INTEL_COMPILER )&& defined(__INTEL_COMPILER_UPDATE )&& defined(__ICL ) 468#define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) 469#endif 470 471#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK ) 472#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 473#endif 474#if defined(JSON_HEDLEY_INTEL_CL_VERSION ) 475#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 476#else 477#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK (major ,minor ,patch ) (0) 478#endif 479 480#if defined(JSON_HEDLEY_PGI_VERSION ) 481#undef JSON_HEDLEY_PGI_VERSION 482#endif 483#if defined(__PGI )&& defined(__PGIC__ )&& defined(__PGIC_MINOR__ )&& defined(__PGIC_PATCHLEVEL__ ) 484#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) 485#endif 486 487#if defined(JSON_HEDLEY_PGI_VERSION_CHECK ) 488#undef JSON_HEDLEY_PGI_VERSION_CHECK 489#endif 490#if defined(JSON_HEDLEY_PGI_VERSION ) 491#define JSON_HEDLEY_PGI_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 492#else 493#define JSON_HEDLEY_PGI_VERSION_CHECK (major ,minor ,patch ) (0) 494#endif 495 496#if defined(JSON_HEDLEY_SUNPRO_VERSION ) 497#undef JSON_HEDLEY_SUNPRO_VERSION 498#endif 499#if defined(__SUNPRO_C )&& (__SUNPRO_C > 0x1000 ) 500#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) 501#elif defined(__SUNPRO_C ) 502#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) 503#elif defined(__SUNPRO_CC )&& (__SUNPRO_CC > 0x1000 ) 504#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) 505#elif defined(__SUNPRO_CC ) 506#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) 507#endif 508 509#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK ) 510#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 511#endif 512#if defined(JSON_HEDLEY_SUNPRO_VERSION ) 513#define JSON_HEDLEY_SUNPRO_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 514#else 515#define JSON_HEDLEY_SUNPRO_VERSION_CHECK (major ,minor ,patch ) (0) 516#endif 517 518#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION ) 519#undef JSON_HEDLEY_EMSCRIPTEN_VERSION 520#endif 521#if defined(__EMSCRIPTEN__ ) 522#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) 523#endif 524 525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK ) 526#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 527#endif 528#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION ) 529#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 530#else 531#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK (major ,minor ,patch ) (0) 532#endif 533 534#if defined(JSON_HEDLEY_ARM_VERSION ) 535#undef JSON_HEDLEY_ARM_VERSION 536#endif 537#if defined(__CC_ARM )&& defined(__ARMCOMPILER_VERSION ) 538#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) 539#elif defined(__CC_ARM )&& defined(__ARMCC_VERSION ) 540#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) 541#endif 542 543#if defined(JSON_HEDLEY_ARM_VERSION_CHECK ) 544#undef JSON_HEDLEY_ARM_VERSION_CHECK 545#endif 546#if defined(JSON_HEDLEY_ARM_VERSION ) 547#define JSON_HEDLEY_ARM_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 548#else 549#define JSON_HEDLEY_ARM_VERSION_CHECK (major ,minor ,patch ) (0) 550#endif 551 552#if defined(JSON_HEDLEY_IBM_VERSION ) 553#undef JSON_HEDLEY_IBM_VERSION 554#endif 555#if defined(__ibmxl__ ) 556#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) 557#elif defined(__xlC__ )&& defined(__xlC_ver__ ) 558#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) 559#elif defined(__xlC__ ) 560#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) 561#endif 562 563#if defined(JSON_HEDLEY_IBM_VERSION_CHECK ) 564#undef JSON_HEDLEY_IBM_VERSION_CHECK 565#endif 566#if defined(JSON_HEDLEY_IBM_VERSION ) 567#define JSON_HEDLEY_IBM_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 568#else 569#define JSON_HEDLEY_IBM_VERSION_CHECK (major ,minor ,patch ) (0) 570#endif 571 572#if defined(JSON_HEDLEY_TI_VERSION ) 573#undef JSON_HEDLEY_TI_VERSION 574#endif 575#if \ 576 defined(__TI_COMPILER_VERSION__ )&& \ 577 ( \ 578 defined(__TMS470__ )|| defined(__TI_ARM__ )|| \ 579 defined(__MSP430__ )|| \ 580 defined(__TMS320C2000__ ) \ 581 ) 582#if (__TI_COMPILER_VERSION__ >=16000000 ) 583#define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 584#endif 585#endif 586 587#if defined(JSON_HEDLEY_TI_VERSION_CHECK ) 588#undef JSON_HEDLEY_TI_VERSION_CHECK 589#endif 590#if defined(JSON_HEDLEY_TI_VERSION ) 591#define JSON_HEDLEY_TI_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 592#else 593#define JSON_HEDLEY_TI_VERSION_CHECK (major ,minor ,patch ) (0) 594#endif 595 596#if defined(JSON_HEDLEY_TI_CL2000_VERSION ) 597#undef JSON_HEDLEY_TI_CL2000_VERSION 598#endif 599#if defined(__TI_COMPILER_VERSION__ )&& defined(__TMS320C2000__ ) 600#define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 601#endif 602 603#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK ) 604#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 605#endif 606#if defined(JSON_HEDLEY_TI_CL2000_VERSION ) 607#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 608#else 609#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK (major ,minor ,patch ) (0) 610#endif 611 612#if defined(JSON_HEDLEY_TI_CL430_VERSION ) 613#undef JSON_HEDLEY_TI_CL430_VERSION 614#endif 615#if defined(__TI_COMPILER_VERSION__ )&& defined(__MSP430__ ) 616#define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 617#endif 618 619#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK ) 620#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 621#endif 622#if defined(JSON_HEDLEY_TI_CL430_VERSION ) 623#define JSON_HEDLEY_TI_CL430_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 624#else 625#define JSON_HEDLEY_TI_CL430_VERSION_CHECK (major ,minor ,patch ) (0) 626#endif 627 628#if defined(JSON_HEDLEY_TI_ARMCL_VERSION ) 629#undef JSON_HEDLEY_TI_ARMCL_VERSION 630#endif 631#if defined(__TI_COMPILER_VERSION__ )&& (defined(__TMS470__ )|| defined(__TI_ARM__ )) 632#define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 633#endif 634 635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK ) 636#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 637#endif 638#if defined(JSON_HEDLEY_TI_ARMCL_VERSION ) 639#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 640#else 641#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (major ,minor ,patch ) (0) 642#endif 643 644#if defined(JSON_HEDLEY_TI_CL6X_VERSION ) 645#undef JSON_HEDLEY_TI_CL6X_VERSION 646#endif 647#if defined(__TI_COMPILER_VERSION__ )&& defined(__TMS320C6X__ ) 648#define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 649#endif 650 651#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK ) 652#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 653#endif 654#if defined(JSON_HEDLEY_TI_CL6X_VERSION ) 655#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 656#else 657#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK (major ,minor ,patch ) (0) 658#endif 659 660#if defined(JSON_HEDLEY_TI_CL7X_VERSION ) 661#undef JSON_HEDLEY_TI_CL7X_VERSION 662#endif 663#if defined(__TI_COMPILER_VERSION__ )&& defined(__C7000__ ) 664#define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 665#endif 666 667#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK ) 668#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 669#endif 670#if defined(JSON_HEDLEY_TI_CL7X_VERSION ) 671#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 672#else 673#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK (major ,minor ,patch ) (0) 674#endif 675 676#if defined(JSON_HEDLEY_TI_CLPRU_VERSION ) 677#undef JSON_HEDLEY_TI_CLPRU_VERSION 678#endif 679#if defined(__TI_COMPILER_VERSION__ )&& defined(__PRU__ ) 680#define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 681#endif 682 683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK ) 684#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 685#endif 686#if defined(JSON_HEDLEY_TI_CLPRU_VERSION ) 687#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 688#else 689#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (major ,minor ,patch ) (0) 690#endif 691 692#if defined(JSON_HEDLEY_CRAY_VERSION ) 693#undef JSON_HEDLEY_CRAY_VERSION 694#endif 695#if defined(_CRAYC ) 696#if defined(_RELEASE_PATCHLEVEL ) 697#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) 698#else 699#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) 700#endif 701#endif 702 703#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK ) 704#undef JSON_HEDLEY_CRAY_VERSION_CHECK 705#endif 706#if defined(JSON_HEDLEY_CRAY_VERSION ) 707#define JSON_HEDLEY_CRAY_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 708#else 709#define JSON_HEDLEY_CRAY_VERSION_CHECK (major ,minor ,patch ) (0) 710#endif 711 712#if defined(JSON_HEDLEY_IAR_VERSION ) 713#undef JSON_HEDLEY_IAR_VERSION 714#endif 715#if defined(__IAR_SYSTEMS_ICC__ ) 716#if __VER__ > 1000 717#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) 718#else 719#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) 720#endif 721#endif 722 723#if defined(JSON_HEDLEY_IAR_VERSION_CHECK ) 724#undef JSON_HEDLEY_IAR_VERSION_CHECK 725#endif 726#if defined(JSON_HEDLEY_IAR_VERSION ) 727#define JSON_HEDLEY_IAR_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 728#else 729#define JSON_HEDLEY_IAR_VERSION_CHECK (major ,minor ,patch ) (0) 730#endif 731 732#if defined(JSON_HEDLEY_TINYC_VERSION ) 733#undef JSON_HEDLEY_TINYC_VERSION 734#endif 735#if defined(__TINYC__ ) 736#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) 737#endif 738 739#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK ) 740#undef JSON_HEDLEY_TINYC_VERSION_CHECK 741#endif 742#if defined(JSON_HEDLEY_TINYC_VERSION ) 743#define JSON_HEDLEY_TINYC_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 744#else 745#define JSON_HEDLEY_TINYC_VERSION_CHECK (major ,minor ,patch ) (0) 746#endif 747 748#if defined(JSON_HEDLEY_DMC_VERSION ) 749#undef JSON_HEDLEY_DMC_VERSION 750#endif 751#if defined(__DMC__ ) 752#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) 753#endif 754 755#if defined(JSON_HEDLEY_DMC_VERSION_CHECK ) 756#undef JSON_HEDLEY_DMC_VERSION_CHECK 757#endif 758#if defined(JSON_HEDLEY_DMC_VERSION ) 759#define JSON_HEDLEY_DMC_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 760#else 761#define JSON_HEDLEY_DMC_VERSION_CHECK (major ,minor ,patch ) (0) 762#endif 763 764#if defined(JSON_HEDLEY_COMPCERT_VERSION ) 765#undef JSON_HEDLEY_COMPCERT_VERSION 766#endif 767#if defined(__COMPCERT_VERSION__ ) 768#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) 769#endif 770 771#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK ) 772#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 773#endif 774#if defined(JSON_HEDLEY_COMPCERT_VERSION ) 775#define JSON_HEDLEY_COMPCERT_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 776#else 777#define JSON_HEDLEY_COMPCERT_VERSION_CHECK (major ,minor ,patch ) (0) 778#endif 779 780#if defined(JSON_HEDLEY_PELLES_VERSION ) 781#undef JSON_HEDLEY_PELLES_VERSION 782#endif 783#if defined(__POCC__ ) 784#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) 785#endif 786 787#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK ) 788#undef JSON_HEDLEY_PELLES_VERSION_CHECK 789#endif 790#if defined(JSON_HEDLEY_PELLES_VERSION ) 791#define JSON_HEDLEY_PELLES_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 792#else 793#define JSON_HEDLEY_PELLES_VERSION_CHECK (major ,minor ,patch ) (0) 794#endif 795 796#if defined(JSON_HEDLEY_MCST_LCC_VERSION ) 797#undef JSON_HEDLEY_MCST_LCC_VERSION 798#endif 799#if defined(__LCC__ )&& defined(__LCC_MINOR__ ) 800#define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) 801#endif 802 803#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK ) 804#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 805#endif 806#if defined(JSON_HEDLEY_MCST_LCC_VERSION ) 807#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 808#else 809#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK (major ,minor ,patch ) (0) 810#endif 811 812#if defined(JSON_HEDLEY_GCC_VERSION ) 813#undef JSON_HEDLEY_GCC_VERSION 814#endif 815#if \ 816 defined(JSON_HEDLEY_GNUC_VERSION )&& \ 817 !defined(__clang__ )&& \ 818 !defined(JSON_HEDLEY_INTEL_VERSION )&& \ 819 !defined(JSON_HEDLEY_PGI_VERSION )&& \ 820 !defined(JSON_HEDLEY_ARM_VERSION )&& \ 821 !defined(JSON_HEDLEY_CRAY_VERSION )&& \ 822 !defined(JSON_HEDLEY_TI_VERSION )&& \ 823 !defined(JSON_HEDLEY_TI_ARMCL_VERSION )&& \ 824 !defined(JSON_HEDLEY_TI_CL430_VERSION )&& \ 825 !defined(JSON_HEDLEY_TI_CL2000_VERSION )&& \ 826 !defined(JSON_HEDLEY_TI_CL6X_VERSION )&& \ 827 !defined(JSON_HEDLEY_TI_CL7X_VERSION )&& \ 828 !defined(JSON_HEDLEY_TI_CLPRU_VERSION )&& \ 829 !defined(__COMPCERT__ )&& \ 830 !defined(JSON_HEDLEY_MCST_LCC_VERSION ) 831#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION 832#endif 833 834#if defined(JSON_HEDLEY_GCC_VERSION_CHECK ) 835#undef JSON_HEDLEY_GCC_VERSION_CHECK 836#endif 837#if defined(JSON_HEDLEY_GCC_VERSION ) 838#define JSON_HEDLEY_GCC_VERSION_CHECK (major ,minor ,patch ) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 839#else 840#define JSON_HEDLEY_GCC_VERSION_CHECK (major ,minor ,patch ) (0) 841#endif 842 843#if defined(JSON_HEDLEY_HAS_ATTRIBUTE ) 844#undef JSON_HEDLEY_HAS_ATTRIBUTE 845#endif 846#if \ 847 defined(__has_attribute )&& \ 848 ( \ 849 (!defined(JSON_HEDLEY_IAR_VERSION )|| JSON_HEDLEY_IAR_VERSION_CHECK (8 ,5 ,9 )) \ 850 ) 851# define JSON_HEDLEY_HAS_ATTRIBUTE (attribute ) __has_attribute(attribute) 852#else 853# define JSON_HEDLEY_HAS_ATTRIBUTE (attribute ) (0) 854#endif 855 856#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE ) 857#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 858#endif 859#if defined(__has_attribute ) 860#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 861#else 862#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 863#endif 864 865#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE ) 866#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 867#endif 868#if defined(__has_attribute ) 869#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 870#else 871#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 872#endif 873 874#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE ) 875#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 876#endif 877#if \ 878 defined(__has_cpp_attribute )&& \ 879 defined(__cplusplus )&& \ 880 (!defined(JSON_HEDLEY_SUNPRO_VERSION )|| JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,15 ,0 )) 881#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE (attribute ) __has_cpp_attribute(attribute) 882#else 883#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE (attribute ) (0) 884#endif 885 886#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS ) 887#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 888#endif 889#if !defined(__cplusplus )|| !defined(__has_cpp_attribute ) 890#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS (ns ,attribute ) (0) 891#elif \ 892 !defined(JSON_HEDLEY_PGI_VERSION )&& \ 893 !defined(JSON_HEDLEY_IAR_VERSION )&& \ 894 (!defined(JSON_HEDLEY_SUNPRO_VERSION )|| JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,15 ,0 ))&& \ 895 (!defined(JSON_HEDLEY_MSVC_VERSION )|| JSON_HEDLEY_MSVC_VERSION_CHECK (19 ,20 ,0 )) 896#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS (ns ,attribute ) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) 897#else 898#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS (ns ,attribute ) (0) 899#endif 900 901#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE ) 902#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 903#endif 904#if defined(__has_cpp_attribute )&& defined(__cplusplus ) 905#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE (attribute ,major ,minor ,patch ) __has_cpp_attribute(attribute) 906#else 907#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 908#endif 909 910#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE ) 911#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 912#endif 913#if defined(__has_cpp_attribute )&& defined(__cplusplus ) 914#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE (attribute ,major ,minor ,patch ) __has_cpp_attribute(attribute) 915#else 916#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 917#endif 918 919#if defined(JSON_HEDLEY_HAS_BUILTIN ) 920#undef JSON_HEDLEY_HAS_BUILTIN 921#endif 922#if defined(__has_builtin ) 923#define JSON_HEDLEY_HAS_BUILTIN (builtin ) __has_builtin(builtin) 924#else 925#define JSON_HEDLEY_HAS_BUILTIN (builtin ) (0) 926#endif 927 928#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN ) 929#undef JSON_HEDLEY_GNUC_HAS_BUILTIN 930#endif 931#if defined(__has_builtin ) 932#define JSON_HEDLEY_GNUC_HAS_BUILTIN (builtin ,major ,minor ,patch ) __has_builtin(builtin) 933#else 934#define JSON_HEDLEY_GNUC_HAS_BUILTIN (builtin ,major ,minor ,patch ) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 935#endif 936 937#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN ) 938#undef JSON_HEDLEY_GCC_HAS_BUILTIN 939#endif 940#if defined(__has_builtin ) 941#define JSON_HEDLEY_GCC_HAS_BUILTIN (builtin ,major ,minor ,patch ) __has_builtin(builtin) 942#else 943#define JSON_HEDLEY_GCC_HAS_BUILTIN (builtin ,major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 944#endif 945 946#if defined(JSON_HEDLEY_HAS_FEATURE ) 947#undef JSON_HEDLEY_HAS_FEATURE 948#endif 949#if defined(__has_feature ) 950#define JSON_HEDLEY_HAS_FEATURE (feature ) __has_feature(feature) 951#else 952#define JSON_HEDLEY_HAS_FEATURE (feature ) (0) 953#endif 954 955#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE ) 956#undef JSON_HEDLEY_GNUC_HAS_FEATURE 957#endif 958#if defined(__has_feature ) 959#define JSON_HEDLEY_GNUC_HAS_FEATURE (feature ,major ,minor ,patch ) __has_feature(feature) 960#else 961#define JSON_HEDLEY_GNUC_HAS_FEATURE (feature ,major ,minor ,patch ) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 962#endif 963 964#if defined(JSON_HEDLEY_GCC_HAS_FEATURE ) 965#undef JSON_HEDLEY_GCC_HAS_FEATURE 966#endif 967#if defined(__has_feature ) 968#define JSON_HEDLEY_GCC_HAS_FEATURE (feature ,major ,minor ,patch ) __has_feature(feature) 969#else 970#define JSON_HEDLEY_GCC_HAS_FEATURE (feature ,major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 971#endif 972 973#if defined(JSON_HEDLEY_HAS_EXTENSION ) 974#undef JSON_HEDLEY_HAS_EXTENSION 975#endif 976#if defined(__has_extension ) 977#define JSON_HEDLEY_HAS_EXTENSION (extension ) __has_extension(extension) 978#else 979#define JSON_HEDLEY_HAS_EXTENSION (extension ) (0) 980#endif 981 982#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION ) 983#undef JSON_HEDLEY_GNUC_HAS_EXTENSION 984#endif 985#if defined(__has_extension ) 986#define JSON_HEDLEY_GNUC_HAS_EXTENSION (extension ,major ,minor ,patch ) __has_extension(extension) 987#else 988#define JSON_HEDLEY_GNUC_HAS_EXTENSION (extension ,major ,minor ,patch ) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 989#endif 990 991#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION ) 992#undef JSON_HEDLEY_GCC_HAS_EXTENSION 993#endif 994#if defined(__has_extension ) 995#define JSON_HEDLEY_GCC_HAS_EXTENSION (extension ,major ,minor ,patch ) __has_extension(extension) 996#else 997#define JSON_HEDLEY_GCC_HAS_EXTENSION (extension ,major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 998#endif 999 1000#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE ) 1001#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 1002#endif 1003#if defined(__has_declspec_attribute ) 1004#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE (attribute ) __has_declspec_attribute(attribute) 1005#else 1006#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE (attribute ) (0) 1007#endif 1008 1009#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE ) 1010#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 1011#endif 1012#if defined(__has_declspec_attribute ) 1013#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE (attribute ,major ,minor ,patch ) __has_declspec_attribute(attribute) 1014#else 1015#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1016#endif 1017 1018#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE ) 1019#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 1020#endif 1021#if defined(__has_declspec_attribute ) 1022#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE (attribute ,major ,minor ,patch ) __has_declspec_attribute(attribute) 1023#else 1024#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE (attribute ,major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1025#endif 1026 1027#if defined(JSON_HEDLEY_HAS_WARNING ) 1028#undef JSON_HEDLEY_HAS_WARNING 1029#endif 1030#if defined(__has_warning ) 1031#define JSON_HEDLEY_HAS_WARNING (warning ) __has_warning(warning) 1032#else 1033#define JSON_HEDLEY_HAS_WARNING (warning ) (0) 1034#endif 1035 1036#if defined(JSON_HEDLEY_GNUC_HAS_WARNING ) 1037#undef JSON_HEDLEY_GNUC_HAS_WARNING 1038#endif 1039#if defined(__has_warning ) 1040#define JSON_HEDLEY_GNUC_HAS_WARNING (warning ,major ,minor ,patch ) __has_warning(warning) 1041#else 1042#define JSON_HEDLEY_GNUC_HAS_WARNING (warning ,major ,minor ,patch ) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1043#endif 1044 1045#if defined(JSON_HEDLEY_GCC_HAS_WARNING ) 1046#undef JSON_HEDLEY_GCC_HAS_WARNING 1047#endif 1048#if defined(__has_warning ) 1049#define JSON_HEDLEY_GCC_HAS_WARNING (warning ,major ,minor ,patch ) __has_warning(warning) 1050#else 1051#define JSON_HEDLEY_GCC_HAS_WARNING (warning ,major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1052#endif 1053 1054#if \ 1055 (defined(__STDC_VERSION__ )&& (__STDC_VERSION__ >=199901L ))|| \ 1056 defined(__clang__ )|| \ 1057JSON_HEDLEY_GCC_VERSION_CHECK (3 ,0 ,0 )|| \ 1058JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1059JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 )|| \ 1060JSON_HEDLEY_PGI_VERSION_CHECK (18 ,4 ,0 )|| \ 1061JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1062JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1063JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,7 ,0 )|| \ 1064JSON_HEDLEY_TI_CL430_VERSION_CHECK (2 ,0 ,1 )|| \ 1065JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,1 ,0 )|| \ 1066JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,0 ,0 )|| \ 1067JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1068JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1069JSON_HEDLEY_CRAY_VERSION_CHECK (5 ,0 ,0 )|| \ 1070JSON_HEDLEY_TINYC_VERSION_CHECK (0 ,9 ,17 )|| \ 1071JSON_HEDLEY_SUNPRO_VERSION_CHECK (8 ,0 ,0 )|| \ 1072 (JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )&& defined(__C99_PRAGMA_OPERATOR )) 1073#define JSON_HEDLEY_PRAGMA (value ) _Pragma(#value) 1074#elif JSON_HEDLEY_MSVC_VERSION_CHECK (15 ,0 ,0 ) 1075#define JSON_HEDLEY_PRAGMA (value ) __pragma(value) 1076#else 1077#define JSON_HEDLEY_PRAGMA (value ) 1078#endif 1079 1080#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH ) 1081#undef JSON_HEDLEY_DIAGNOSTIC_PUSH 1082#endif 1083#if defined(JSON_HEDLEY_DIAGNOSTIC_POP ) 1084#undef JSON_HEDLEY_DIAGNOSTIC_POP 1085#endif 1086#if defined(__clang__ ) 1087#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") 1088#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") 1089#elif JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 ) 1090#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1091#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1092#elif JSON_HEDLEY_GCC_VERSION_CHECK (4 ,6 ,0 ) 1093#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") 1094#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") 1095#elif \ 1096JSON_HEDLEY_MSVC_VERSION_CHECK (15 ,0 ,0 )|| \ 1097JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1098#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) 1099#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) 1100#elif JSON_HEDLEY_ARM_VERSION_CHECK (5 ,6 ,0 ) 1101#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") 1102#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") 1103#elif \ 1104JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1105JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1106JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,4 ,0 )|| \ 1107JSON_HEDLEY_TI_CL6X_VERSION_CHECK (8 ,1 ,0 )|| \ 1108JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1109JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 ) 1110#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") 1111#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") 1112#elif JSON_HEDLEY_PELLES_VERSION_CHECK (2 ,90 ,0 ) 1113#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1114#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1115#else 1116#define JSON_HEDLEY_DIAGNOSTIC_PUSH 1117#define JSON_HEDLEY_DIAGNOSTIC_POP 1118#endif 1119 1120/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for 1121HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 1122#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ ) 1123#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 1124#endif 1125#if defined(__cplusplus ) 1126# if JSON_HEDLEY_HAS_WARNING ("- Wc + +98 - compat ") 1127# if JSON_HEDLEY_HAS_WARNING ("- Wc + +17 - extensions ") 1128# if JSON_HEDLEY_HAS_WARNING ("- Wc + +1z - extensions ") 1129# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ (xpr ) \ 1130 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1131 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1132 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1133 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ 1134 xpr \ 1135 JSON_HEDLEY_DIAGNOSTIC_POP 1136# else 1137# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ (xpr ) \ 1138 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1139 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1140 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1141 xpr \ 1142 JSON_HEDLEY_DIAGNOSTIC_POP 1143# endif 1144# else 1145# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ (xpr ) \ 1146 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1147 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1148 xpr \ 1149 JSON_HEDLEY_DIAGNOSTIC_POP 1150# endif 1151# endif 1152#endif 1153#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ ) 1154#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ (x ) x 1155#endif 1156 1157#if defined(JSON_HEDLEY_CONST_CAST ) 1158#undef JSON_HEDLEY_CONST_CAST 1159#endif 1160#if defined(__cplusplus ) 1161# define JSON_HEDLEY_CONST_CAST (T ,expr ) (const_cast<T>(expr)) 1162#elif \ 1163JSON_HEDLEY_HAS_WARNING ("- Wcast - qual ")|| \ 1164JSON_HEDLEY_GCC_VERSION_CHECK (4 ,6 ,0 )|| \ 1165JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 ) 1166# define JSON_HEDLEY_CONST_CAST (T ,expr ) (__extension__ ({ \ 1167 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1168 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ 1169 ((T) (expr)); \ 1170 JSON_HEDLEY_DIAGNOSTIC_POP \ 1171 })) 1172#else 1173# define JSON_HEDLEY_CONST_CAST (T ,expr ) ((T) (expr)) 1174#endif 1175 1176#if defined(JSON_HEDLEY_REINTERPRET_CAST ) 1177#undef JSON_HEDLEY_REINTERPRET_CAST 1178#endif 1179#if defined(__cplusplus ) 1180#define JSON_HEDLEY_REINTERPRET_CAST (T ,expr ) (reinterpret_cast<T>(expr)) 1181#else 1182#define JSON_HEDLEY_REINTERPRET_CAST (T ,expr ) ((T) (expr)) 1183#endif 1184 1185#if defined(JSON_HEDLEY_STATIC_CAST ) 1186#undef JSON_HEDLEY_STATIC_CAST 1187#endif 1188#if defined(__cplusplus ) 1189#define JSON_HEDLEY_STATIC_CAST (T ,expr ) (static_cast<T>(expr)) 1190#else 1191#define JSON_HEDLEY_STATIC_CAST (T ,expr ) ((T) (expr)) 1192#endif 1193 1194#if defined(JSON_HEDLEY_CPP_CAST ) 1195#undef JSON_HEDLEY_CPP_CAST 1196#endif 1197#if defined(__cplusplus ) 1198# if JSON_HEDLEY_HAS_WARNING ("- Wold - style - cast ") 1199# define JSON_HEDLEY_CPP_CAST (T ,expr ) \ 1200 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1201 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ 1202 ((T) (expr)) \ 1203 JSON_HEDLEY_DIAGNOSTIC_POP 1204# elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,3 ,0 ) 1205# define JSON_HEDLEY_CPP_CAST (T ,expr ) \ 1206 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1207 _Pragma("diag_suppress=Pe137") \ 1208 JSON_HEDLEY_DIAGNOSTIC_POP 1209# else 1210# define JSON_HEDLEY_CPP_CAST (T ,expr ) ((T) (expr)) 1211# endif 1212#else 1213# define JSON_HEDLEY_CPP_CAST (T ,expr ) (expr) 1214#endif 1215 1216#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED ) 1217#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1218#endif 1219#if JSON_HEDLEY_HAS_WARNING ("- Wdeprecated - declarations ") 1220#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") 1221#elif JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 ) 1222#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") 1223#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1224#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) 1225#elif JSON_HEDLEY_PGI_VERSION_CHECK (20 ,7 ,0 ) 1226#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") 1227#elif JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 ) 1228#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1229#elif JSON_HEDLEY_GCC_VERSION_CHECK (4 ,3 ,0 ) 1230#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1231#elif JSON_HEDLEY_MSVC_VERSION_CHECK (15 ,0 ,0 ) 1232#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) 1233#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1234#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1235#elif \ 1236JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1237 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1238JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1239 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1240JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1241 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1242JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1243 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1244JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1245JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1246JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 ) 1247#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") 1248#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,13 ,0 )&& !defined(__cplusplus ) 1249#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") 1250#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,13 ,0 )&& defined(__cplusplus ) 1251#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") 1252#elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 1253#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") 1254#elif JSON_HEDLEY_PELLES_VERSION_CHECK (2 ,90 ,0 ) 1255#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") 1256#else 1257#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1258#endif 1259 1260#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS ) 1261#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1262#endif 1263#if JSON_HEDLEY_HAS_WARNING ("- Wunknown - pragmas ") 1264#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") 1265#elif JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 ) 1266#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") 1267#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1268#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) 1269#elif JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 ) 1270#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") 1271#elif JSON_HEDLEY_GCC_VERSION_CHECK (4 ,3 ,0 ) 1272#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") 1273#elif JSON_HEDLEY_MSVC_VERSION_CHECK (15 ,0 ,0 ) 1274#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) 1275#elif \ 1276JSON_HEDLEY_TI_VERSION_CHECK (16 ,9 ,0 )|| \ 1277JSON_HEDLEY_TI_CL6X_VERSION_CHECK (8 ,0 ,0 )|| \ 1278JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1279JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,3 ,0 ) 1280#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1281#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK (8 ,0 ,0 ) 1282#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1283#elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 1284#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") 1285#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1286#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") 1287#else 1288#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1289#endif 1290 1291#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES ) 1292#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1293#endif 1294#if JSON_HEDLEY_HAS_WARNING ("- Wunknown - attributes ") 1295#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") 1296#elif JSON_HEDLEY_GCC_VERSION_CHECK (4 ,6 ,0 ) 1297#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1298#elif JSON_HEDLEY_INTEL_VERSION_CHECK (17 ,0 ,0 ) 1299#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") 1300#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1301#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) 1302#elif JSON_HEDLEY_MSVC_VERSION_CHECK (19 ,0 ,0 ) 1303#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) 1304#elif JSON_HEDLEY_PGI_VERSION_CHECK (20 ,7 ,0 ) 1305#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") 1306#elif JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 ) 1307#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1308#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,14 ,0 )&& defined(__cplusplus ) 1309#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") 1310#elif \ 1311JSON_HEDLEY_TI_VERSION_CHECK (18 ,1 ,0 )|| \ 1312JSON_HEDLEY_TI_CL6X_VERSION_CHECK (8 ,3 ,0 )|| \ 1313JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 ) 1314#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") 1315#elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 1316#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") 1317#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1318#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1319#else 1320#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1321#endif 1322 1323#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL ) 1324#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1325#endif 1326#if JSON_HEDLEY_HAS_WARNING ("- Wcast - qual ") 1327#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") 1328#elif JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 ) 1329#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") 1330#elif JSON_HEDLEY_GCC_VERSION_CHECK (3 ,0 ,0 ) 1331#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") 1332#else 1333#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1334#endif 1335 1336#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION ) 1337#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1338#endif 1339#if JSON_HEDLEY_HAS_WARNING ("- Wunused - function ") 1340#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") 1341#elif JSON_HEDLEY_GCC_VERSION_CHECK (3 ,4 ,0 ) 1342#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") 1343#elif JSON_HEDLEY_MSVC_VERSION_CHECK (1 ,0 ,0 ) 1344#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) 1345#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1346#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") 1347#else 1348#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1349#endif 1350 1351#if defined(JSON_HEDLEY_DEPRECATED ) 1352#undef JSON_HEDLEY_DEPRECATED 1353#endif 1354#if defined(JSON_HEDLEY_DEPRECATED_FOR ) 1355#undef JSON_HEDLEY_DEPRECATED_FOR 1356#endif 1357#if \ 1358JSON_HEDLEY_MSVC_VERSION_CHECK (14 ,0 ,0 )|| \ 1359JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1360#define JSON_HEDLEY_DEPRECATED (since ) __declspec(deprecated("Since " # since)) 1361#define JSON_HEDLEY_DEPRECATED_FOR (since ,replacement ) __declspec(deprecated("Since " #since "; use " #replacement)) 1362#elif \ 1363 (JSON_HEDLEY_HAS_EXTENSION (attribute_deprecated_with_message )&& !defined(JSON_HEDLEY_IAR_VERSION ))|| \ 1364JSON_HEDLEY_GCC_VERSION_CHECK (4 ,5 ,0 )|| \ 1365JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1366JSON_HEDLEY_ARM_VERSION_CHECK (5 ,6 ,0 )|| \ 1367JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,13 ,0 )|| \ 1368JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 )|| \ 1369JSON_HEDLEY_TI_VERSION_CHECK (18 ,1 ,0 )|| \ 1370JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (18 ,1 ,0 )|| \ 1371JSON_HEDLEY_TI_CL6X_VERSION_CHECK (8 ,3 ,0 )|| \ 1372JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1373JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,3 ,0 )|| \ 1374JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1375#define JSON_HEDLEY_DEPRECATED (since ) __attribute__((__deprecated__("Since " #since))) 1376#define JSON_HEDLEY_DEPRECATED_FOR (since ,replacement ) __attribute__((__deprecated__("Since " #since "; use " #replacement))) 1377#elif defined(__cplusplus )&& (__cplusplus >=201402L ) 1378#define JSON_HEDLEY_DEPRECATED (since ) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) 1379#define JSON_HEDLEY_DEPRECATED_FOR (since ,replacement ) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) 1380#elif \ 1381JSON_HEDLEY_HAS_ATTRIBUTE (deprecated )|| \ 1382JSON_HEDLEY_GCC_VERSION_CHECK (3 ,1 ,0 )|| \ 1383JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1384JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1385 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1386JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1387 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1388JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1389 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1390JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1391 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1392JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1393JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1394JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1395JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 )|| \ 1396JSON_HEDLEY_IAR_VERSION_CHECK (8 ,10 ,0 ) 1397#define JSON_HEDLEY_DEPRECATED (since ) __attribute__((__deprecated__)) 1398#define JSON_HEDLEY_DEPRECATED_FOR (since ,replacement ) __attribute__((__deprecated__)) 1399#elif \ 1400JSON_HEDLEY_MSVC_VERSION_CHECK (13 ,10 ,0 )|| \ 1401JSON_HEDLEY_PELLES_VERSION_CHECK (6 ,50 ,0 )|| \ 1402JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1403#define JSON_HEDLEY_DEPRECATED (since ) __declspec(deprecated) 1404#define JSON_HEDLEY_DEPRECATED_FOR (since ,replacement ) __declspec(deprecated) 1405#elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 1406#define JSON_HEDLEY_DEPRECATED (since ) _Pragma("deprecated") 1407#define JSON_HEDLEY_DEPRECATED_FOR (since ,replacement ) _Pragma("deprecated") 1408#else 1409#define JSON_HEDLEY_DEPRECATED (since ) 1410#define JSON_HEDLEY_DEPRECATED_FOR (since ,replacement ) 1411#endif 1412 1413#if defined(JSON_HEDLEY_UNAVAILABLE ) 1414#undef JSON_HEDLEY_UNAVAILABLE 1415#endif 1416#if \ 1417JSON_HEDLEY_HAS_ATTRIBUTE (warning )|| \ 1418JSON_HEDLEY_GCC_VERSION_CHECK (4 ,3 ,0 )|| \ 1419JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1420JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1421#define JSON_HEDLEY_UNAVAILABLE (available_since ) __attribute__((__warning__("Not available until " #available_since))) 1422#else 1423#define JSON_HEDLEY_UNAVAILABLE (available_since ) 1424#endif 1425 1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT ) 1427#undef JSON_HEDLEY_WARN_UNUSED_RESULT 1428#endif 1429#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG ) 1430#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 1431#endif 1432#if \ 1433JSON_HEDLEY_HAS_ATTRIBUTE (warn_unused_result )|| \ 1434JSON_HEDLEY_GCC_VERSION_CHECK (3 ,4 ,0 )|| \ 1435JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1436JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1437 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1438JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1439 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1440JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1441 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1442JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1443 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1444JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1445JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1446JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1447 (JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,15 ,0 )&& defined(__cplusplus ))|| \ 1448JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 )|| \ 1449JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1450#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) 1451#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG (msg ) __attribute__((__warn_unused_result__)) 1452#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE (nodiscard ) >=201907L ) 1453#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1454#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG (msg ) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) 1455#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE (nodiscard ) 1456#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1457#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG (msg ) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1458#elif defined(_Check_return_ )/* SAL */ 1459#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ 1460#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG (msg ) _Check_return_ 1461#else 1462#define JSON_HEDLEY_WARN_UNUSED_RESULT 1463#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG (msg ) 1464#endif 1465 1466#if defined(JSON_HEDLEY_SENTINEL ) 1467#undef JSON_HEDLEY_SENTINEL 1468#endif 1469#if \ 1470JSON_HEDLEY_HAS_ATTRIBUTE (sentinel )|| \ 1471JSON_HEDLEY_GCC_VERSION_CHECK (4 ,0 ,0 )|| \ 1472JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1473JSON_HEDLEY_ARM_VERSION_CHECK (5 ,4 ,0 )|| \ 1474JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1475#define JSON_HEDLEY_SENTINEL (position ) __attribute__((__sentinel__(position))) 1476#else 1477#define JSON_HEDLEY_SENTINEL (position ) 1478#endif 1479 1480#if defined(JSON_HEDLEY_NO_RETURN ) 1481#undef JSON_HEDLEY_NO_RETURN 1482#endif 1483#if JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 1484#define JSON_HEDLEY_NO_RETURN __noreturn 1485#elif \ 1486JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1487JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1488#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1489#elif defined(__STDC_VERSION__ )&& __STDC_VERSION__ >=201112L 1490#define JSON_HEDLEY_NO_RETURN _Noreturn 1491#elif defined(__cplusplus )&& (__cplusplus >=201103L ) 1492#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) 1493#elif \ 1494JSON_HEDLEY_HAS_ATTRIBUTE (noreturn )|| \ 1495JSON_HEDLEY_GCC_VERSION_CHECK (3 ,2 ,0 )|| \ 1496JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,11 ,0 )|| \ 1497JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1498JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1499JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1500 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1501JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1502 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1503JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1504 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1505JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1506 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1507JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1508JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1509JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1510JSON_HEDLEY_IAR_VERSION_CHECK (8 ,10 ,0 ) 1511#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1512#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,10 ,0 ) 1513#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") 1514#elif \ 1515JSON_HEDLEY_MSVC_VERSION_CHECK (13 ,10 ,0 )|| \ 1516JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1517#define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1518#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK (6 ,0 ,0 )&& defined(__cplusplus ) 1519#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") 1520#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK (3 ,2 ,0 ) 1521#define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) 1522#elif JSON_HEDLEY_PELLES_VERSION_CHECK (9 ,0 ,0 ) 1523#define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1524#else 1525#define JSON_HEDLEY_NO_RETURN 1526#endif 1527 1528#if defined(JSON_HEDLEY_NO_ESCAPE ) 1529#undef JSON_HEDLEY_NO_ESCAPE 1530#endif 1531#if JSON_HEDLEY_HAS_ATTRIBUTE (noescape ) 1532#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) 1533#else 1534#define JSON_HEDLEY_NO_ESCAPE 1535#endif 1536 1537#if defined(JSON_HEDLEY_UNREACHABLE ) 1538#undef JSON_HEDLEY_UNREACHABLE 1539#endif 1540#if defined(JSON_HEDLEY_UNREACHABLE_RETURN ) 1541#undef JSON_HEDLEY_UNREACHABLE_RETURN 1542#endif 1543#if defined(JSON_HEDLEY_ASSUME ) 1544#undef JSON_HEDLEY_ASSUME 1545#endif 1546#if \ 1547JSON_HEDLEY_MSVC_VERSION_CHECK (13 ,10 ,0 )|| \ 1548JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1549JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1550#define JSON_HEDLEY_ASSUME (expr ) __assume(expr) 1551#elif JSON_HEDLEY_HAS_BUILTIN (__builtin_assume ) 1552#define JSON_HEDLEY_ASSUME (expr ) __builtin_assume(expr) 1553#elif \ 1554JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,2 ,0 )|| \ 1555JSON_HEDLEY_TI_CL6X_VERSION_CHECK (4 ,0 ,0 ) 1556#if defined(__cplusplus ) 1557#define JSON_HEDLEY_ASSUME (expr ) std::_nassert(expr) 1558#else 1559#define JSON_HEDLEY_ASSUME (expr ) _nassert(expr) 1560#endif 1561#endif 1562#if \ 1563 (JSON_HEDLEY_HAS_BUILTIN (__builtin_unreachable )&& (!defined(JSON_HEDLEY_ARM_VERSION )))|| \ 1564JSON_HEDLEY_GCC_VERSION_CHECK (4 ,5 ,0 )|| \ 1565JSON_HEDLEY_PGI_VERSION_CHECK (18 ,10 ,0 )|| \ 1566JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1567JSON_HEDLEY_IBM_VERSION_CHECK (13 ,1 ,5 )|| \ 1568JSON_HEDLEY_CRAY_VERSION_CHECK (10 ,0 ,0 )|| \ 1569JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1570#define JSON_HEDLEY_UNREACHABLE () __builtin_unreachable() 1571#elif defined(JSON_HEDLEY_ASSUME ) 1572#define JSON_HEDLEY_UNREACHABLE () JSON_HEDLEY_ASSUME(0) 1573#endif 1574#if !defined(JSON_HEDLEY_ASSUME ) 1575#if defined(JSON_HEDLEY_UNREACHABLE ) 1576#define JSON_HEDLEY_ASSUME (expr ) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) 1577#else 1578#define JSON_HEDLEY_ASSUME (expr ) JSON_HEDLEY_STATIC_CAST(void, expr) 1579#endif 1580#endif 1581#if defined(JSON_HEDLEY_UNREACHABLE ) 1582#if \ 1583JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,2 ,0 )|| \ 1584JSON_HEDLEY_TI_CL6X_VERSION_CHECK (4 ,0 ,0 ) 1585#define JSON_HEDLEY_UNREACHABLE_RETURN (value ) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) 1586#else 1587#define JSON_HEDLEY_UNREACHABLE_RETURN (value ) JSON_HEDLEY_UNREACHABLE() 1588#endif 1589#else 1590#define JSON_HEDLEY_UNREACHABLE_RETURN (value ) return (value) 1591#endif 1592#if !defined(JSON_HEDLEY_UNREACHABLE ) 1593#define JSON_HEDLEY_UNREACHABLE () JSON_HEDLEY_ASSUME(0) 1594#endif 1595 1596JSON_HEDLEY_DIAGNOSTIC_PUSH 1597#if JSON_HEDLEY_HAS_WARNING ("-Wpedantic" ) 1598#pragma clang diagnostic ignored "-Wpedantic" 1599#endif 1600#if JSON_HEDLEY_HAS_WARNING ("- Wc + +98 - compat - pedantic ")&& defined(__cplusplus ) 1601#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 1602#endif 1603#if JSON_HEDLEY_GCC_HAS_WARNING ("- Wvariadic - macros ",4 ,0 ,0 ) 1604#if defined(__clang__ ) 1605#pragma clang diagnostic ignored "-Wvariadic-macros" 1606#elif defined(JSON_HEDLEY_GCC_VERSION ) 1607#pragma GCC diagnostic ignored "-Wvariadic-macros" 1608#endif 1609#endif 1610#if defined(JSON_HEDLEY_NON_NULL ) 1611#undef JSON_HEDLEY_NON_NULL 1612#endif 1613#if \ 1614JSON_HEDLEY_HAS_ATTRIBUTE (nonnull )|| \ 1615JSON_HEDLEY_GCC_VERSION_CHECK (3 ,3 ,0 )|| \ 1616JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1617JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 ) 1618#define JSON_HEDLEY_NON_NULL (...) __attribute__((__nonnull__(__VA_ARGS__))) 1619#else 1620#define JSON_HEDLEY_NON_NULL (...) 1621#endif 1622JSON_HEDLEY_DIAGNOSTIC_POP 1623 1624#if defined(JSON_HEDLEY_PRINTF_FORMAT ) 1625#undef JSON_HEDLEY_PRINTF_FORMAT 1626#endif 1627#if defined(__MINGW32__ )&& JSON_HEDLEY_GCC_HAS_ATTRIBUTE (format ,4 ,4 ,0 )&& !defined(__USE_MINGW_ANSI_STDIO ) 1628#define JSON_HEDLEY_PRINTF_FORMAT (string_idx ,first_to_check ) __attribute__((__format__(ms_printf, string_idx, first_to_check))) 1629#elif defined(__MINGW32__ )&& JSON_HEDLEY_GCC_HAS_ATTRIBUTE (format ,4 ,4 ,0 )&& defined(__USE_MINGW_ANSI_STDIO ) 1630#define JSON_HEDLEY_PRINTF_FORMAT (string_idx ,first_to_check ) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) 1631#elif \ 1632JSON_HEDLEY_HAS_ATTRIBUTE (format )|| \ 1633JSON_HEDLEY_GCC_VERSION_CHECK (3 ,1 ,0 )|| \ 1634JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1635JSON_HEDLEY_ARM_VERSION_CHECK (5 ,6 ,0 )|| \ 1636JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1637JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1638 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1639JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1640 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1641JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1642 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1643JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1644 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1645JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1646JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1647JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1648JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1649#define JSON_HEDLEY_PRINTF_FORMAT (string_idx ,first_to_check ) __attribute__((__format__(__printf__, string_idx, first_to_check))) 1650#elif JSON_HEDLEY_PELLES_VERSION_CHECK (6 ,0 ,0 ) 1651#define JSON_HEDLEY_PRINTF_FORMAT (string_idx ,first_to_check ) __declspec(vaformat(printf,string_idx,first_to_check)) 1652#else 1653#define JSON_HEDLEY_PRINTF_FORMAT (string_idx ,first_to_check ) 1654#endif 1655 1656#if defined(JSON_HEDLEY_CONSTEXPR ) 1657#undef JSON_HEDLEY_CONSTEXPR 1658#endif 1659#if defined(__cplusplus ) 1660#if __cplusplus >=201103L 1661#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) 1662#endif 1663#endif 1664#if !defined(JSON_HEDLEY_CONSTEXPR ) 1665#define JSON_HEDLEY_CONSTEXPR 1666#endif 1667 1668#if defined(JSON_HEDLEY_PREDICT ) 1669#undef JSON_HEDLEY_PREDICT 1670#endif 1671#if defined(JSON_HEDLEY_LIKELY ) 1672#undef JSON_HEDLEY_LIKELY 1673#endif 1674#if defined(JSON_HEDLEY_UNLIKELY ) 1675#undef JSON_HEDLEY_UNLIKELY 1676#endif 1677#if defined(JSON_HEDLEY_UNPREDICTABLE ) 1678#undef JSON_HEDLEY_UNPREDICTABLE 1679#endif 1680#if JSON_HEDLEY_HAS_BUILTIN (__builtin_unpredictable ) 1681#define JSON_HEDLEY_UNPREDICTABLE (expr ) __builtin_unpredictable((expr)) 1682#endif 1683#if \ 1684 (JSON_HEDLEY_HAS_BUILTIN (__builtin_expect_with_probability )&& !defined(JSON_HEDLEY_PGI_VERSION ))|| \ 1685JSON_HEDLEY_GCC_VERSION_CHECK (9 ,0 ,0 )|| \ 1686JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1687# define JSON_HEDLEY_PREDICT (expr ,value ,probability ) __builtin_expect_with_probability( (expr), (value), (probability)) 1688# define JSON_HEDLEY_PREDICT_TRUE (expr ,probability ) __builtin_expect_with_probability(!!(expr), 1 , (probability)) 1689# define JSON_HEDLEY_PREDICT_FALSE (expr ,probability ) __builtin_expect_with_probability(!!(expr), 0 , (probability)) 1690# define JSON_HEDLEY_LIKELY (expr ) __builtin_expect (!!(expr), 1 ) 1691# define JSON_HEDLEY_UNLIKELY (expr ) __builtin_expect (!!(expr), 0 ) 1692#elif \ 1693 (JSON_HEDLEY_HAS_BUILTIN (__builtin_expect )&& !defined(JSON_HEDLEY_INTEL_CL_VERSION ))|| \ 1694JSON_HEDLEY_GCC_VERSION_CHECK (3 ,0 ,0 )|| \ 1695JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1696 (JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,15 ,0 )&& defined(__cplusplus ))|| \ 1697JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1698JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1699JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1700JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,7 ,0 )|| \ 1701JSON_HEDLEY_TI_CL430_VERSION_CHECK (3 ,1 ,0 )|| \ 1702JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,1 ,0 )|| \ 1703JSON_HEDLEY_TI_CL6X_VERSION_CHECK (6 ,1 ,0 )|| \ 1704JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1705JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1706JSON_HEDLEY_TINYC_VERSION_CHECK (0 ,9 ,27 )|| \ 1707JSON_HEDLEY_CRAY_VERSION_CHECK (8 ,1 ,0 )|| \ 1708JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1709# define JSON_HEDLEY_PREDICT (expr ,expected ,probability ) \ 1710 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) 1711# define JSON_HEDLEY_PREDICT_TRUE (expr ,probability ) \ 1712 (__extension__ ({ \ 1713 double hedley_probability_ = (probability); \ 1714 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ 1715 })) 1716# define JSON_HEDLEY_PREDICT_FALSE (expr ,probability ) \ 1717 (__extension__ ({ \ 1718 double hedley_probability_ = (probability); \ 1719 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ 1720 })) 1721# define JSON_HEDLEY_LIKELY (expr ) __builtin_expect(!!(expr), 1) 1722# define JSON_HEDLEY_UNLIKELY (expr ) __builtin_expect(!!(expr), 0) 1723#else 1724# define JSON_HEDLEY_PREDICT (expr ,expected ,probability ) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) 1725# define JSON_HEDLEY_PREDICT_TRUE (expr ,probability ) (!!(expr)) 1726# define JSON_HEDLEY_PREDICT_FALSE (expr ,probability ) (!!(expr)) 1727# define JSON_HEDLEY_LIKELY (expr ) (!!(expr)) 1728# define JSON_HEDLEY_UNLIKELY (expr ) (!!(expr)) 1729#endif 1730#if !defined(JSON_HEDLEY_UNPREDICTABLE ) 1731#define JSON_HEDLEY_UNPREDICTABLE (expr ) JSON_HEDLEY_PREDICT(expr, 1, 0.5) 1732#endif 1733 1734#if defined(JSON_HEDLEY_MALLOC ) 1735#undef JSON_HEDLEY_MALLOC 1736#endif 1737#if \ 1738JSON_HEDLEY_HAS_ATTRIBUTE (malloc )|| \ 1739JSON_HEDLEY_GCC_VERSION_CHECK (3 ,1 ,0 )|| \ 1740JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1741JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,11 ,0 )|| \ 1742JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1743JSON_HEDLEY_IBM_VERSION_CHECK (12 ,1 ,0 )|| \ 1744JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1745 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1746JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1747 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1748JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1749 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1750JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1751 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1752JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1753JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1754JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1755JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1756#define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) 1757#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,10 ,0 ) 1758#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") 1759#elif \ 1760JSON_HEDLEY_MSVC_VERSION_CHECK (14 ,0 ,0 )|| \ 1761JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1762#define JSON_HEDLEY_MALLOC __declspec(restrict) 1763#else 1764#define JSON_HEDLEY_MALLOC 1765#endif 1766 1767#if defined(JSON_HEDLEY_PURE ) 1768#undef JSON_HEDLEY_PURE 1769#endif 1770#if \ 1771JSON_HEDLEY_HAS_ATTRIBUTE (pure )|| \ 1772JSON_HEDLEY_GCC_VERSION_CHECK (2 ,96 ,0 )|| \ 1773JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1774JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,11 ,0 )|| \ 1775JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1776JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1777JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1778 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1779JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1780 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1781JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1782 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1783JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1784 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1785JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1786JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1787JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1788JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 )|| \ 1789JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1790# define JSON_HEDLEY_PURE __attribute__((__pure__)) 1791#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,10 ,0 ) 1792# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") 1793#elif defined(__cplusplus )&& \ 1794 ( \ 1795JSON_HEDLEY_TI_CL430_VERSION_CHECK (2 ,0 ,1 )|| \ 1796JSON_HEDLEY_TI_CL6X_VERSION_CHECK (4 ,0 ,0 )|| \ 1797JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 ) \ 1798 ) 1799# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") 1800#else 1801# define JSON_HEDLEY_PURE 1802#endif 1803 1804#if defined(JSON_HEDLEY_CONST ) 1805#undef JSON_HEDLEY_CONST 1806#endif 1807#if \ 1808JSON_HEDLEY_HAS_ATTRIBUTE (const )|| \ 1809JSON_HEDLEY_GCC_VERSION_CHECK (2 ,5 ,0 )|| \ 1810JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1811JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,11 ,0 )|| \ 1812JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1813JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1814JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1815 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1816JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1817 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1818JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1819 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1820JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1821 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1822JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1823JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1824JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1825JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 )|| \ 1826JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1827#define JSON_HEDLEY_CONST __attribute__((__const__)) 1828#elif \ 1829JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,10 ,0 ) 1830#define JSON_HEDLEY_CONST _Pragma("no_side_effect") 1831#else 1832#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE 1833#endif 1834 1835#if defined(JSON_HEDLEY_RESTRICT ) 1836#undef JSON_HEDLEY_RESTRICT 1837#endif 1838#if defined(__STDC_VERSION__ )&& (__STDC_VERSION__ >=199901L )&& !defined(__cplusplus ) 1839#define JSON_HEDLEY_RESTRICT restrict 1840#elif \ 1841JSON_HEDLEY_GCC_VERSION_CHECK (3 ,1 ,0 )|| \ 1842JSON_HEDLEY_MSVC_VERSION_CHECK (14 ,0 ,0 )|| \ 1843JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1844JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 )|| \ 1845JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1846JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1847JSON_HEDLEY_PGI_VERSION_CHECK (17 ,10 ,0 )|| \ 1848JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1849JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,2 ,4 )|| \ 1850JSON_HEDLEY_TI_CL6X_VERSION_CHECK (8 ,1 ,0 )|| \ 1851JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1852 (JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,14 ,0 )&& defined(__cplusplus ))|| \ 1853JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 )|| \ 1854 defined(__clang__ )|| \ 1855JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1856#define JSON_HEDLEY_RESTRICT __restrict 1857#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,3 ,0 )&& !defined(__cplusplus ) 1858#define JSON_HEDLEY_RESTRICT _Restrict 1859#else 1860#define JSON_HEDLEY_RESTRICT 1861#endif 1862 1863#if defined(JSON_HEDLEY_INLINE ) 1864#undef JSON_HEDLEY_INLINE 1865#endif 1866#if \ 1867 (defined(__STDC_VERSION__ )&& (__STDC_VERSION__ >=199901L ))|| \ 1868 (defined(__cplusplus )&& (__cplusplus >=199711L )) 1869#define JSON_HEDLEY_INLINE inline 1870#elif \ 1871 defined(JSON_HEDLEY_GCC_VERSION )|| \ 1872JSON_HEDLEY_ARM_VERSION_CHECK (6 ,2 ,0 ) 1873#define JSON_HEDLEY_INLINE __inline__ 1874#elif \ 1875JSON_HEDLEY_MSVC_VERSION_CHECK (12 ,0 ,0 )|| \ 1876JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 )|| \ 1877JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1878JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,1 ,0 )|| \ 1879JSON_HEDLEY_TI_CL430_VERSION_CHECK (3 ,1 ,0 )|| \ 1880JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,2 ,0 )|| \ 1881JSON_HEDLEY_TI_CL6X_VERSION_CHECK (8 ,0 ,0 )|| \ 1882JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1883JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1884JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 1885#define JSON_HEDLEY_INLINE __inline 1886#else 1887#define JSON_HEDLEY_INLINE 1888#endif 1889 1890#if defined(JSON_HEDLEY_ALWAYS_INLINE ) 1891#undef JSON_HEDLEY_ALWAYS_INLINE 1892#endif 1893#if \ 1894JSON_HEDLEY_HAS_ATTRIBUTE (always_inline )|| \ 1895JSON_HEDLEY_GCC_VERSION_CHECK (4 ,0 ,0 )|| \ 1896JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1897JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,11 ,0 )|| \ 1898JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1899JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1900JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1901 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1902JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1903 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1904JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1905 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1906JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1907 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1908JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1909JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1910JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1911JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 )|| \ 1912JSON_HEDLEY_IAR_VERSION_CHECK (8 ,10 ,0 ) 1913# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE 1914#elif \ 1915JSON_HEDLEY_MSVC_VERSION_CHECK (12 ,0 ,0 )|| \ 1916JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1917# define JSON_HEDLEY_ALWAYS_INLINE __forceinline 1918#elif defined(__cplusplus )&& \ 1919 ( \ 1920JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1921JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1922JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1923JSON_HEDLEY_TI_CL6X_VERSION_CHECK (6 ,1 ,0 )|| \ 1924JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1925JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 ) \ 1926 ) 1927# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") 1928#elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 1929# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") 1930#else 1931# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE 1932#endif 1933 1934#if defined(JSON_HEDLEY_NEVER_INLINE ) 1935#undef JSON_HEDLEY_NEVER_INLINE 1936#endif 1937#if \ 1938JSON_HEDLEY_HAS_ATTRIBUTE (noinline )|| \ 1939JSON_HEDLEY_GCC_VERSION_CHECK (4 ,0 ,0 )|| \ 1940JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1941JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,11 ,0 )|| \ 1942JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1943JSON_HEDLEY_IBM_VERSION_CHECK (10 ,1 ,0 )|| \ 1944JSON_HEDLEY_TI_VERSION_CHECK (15 ,12 ,0 )|| \ 1945 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (4 ,8 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1946JSON_HEDLEY_TI_ARMCL_VERSION_CHECK (5 ,2 ,0 )|| \ 1947 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1948JSON_HEDLEY_TI_CL2000_VERSION_CHECK (6 ,4 ,0 )|| \ 1949 (JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,0 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1950JSON_HEDLEY_TI_CL430_VERSION_CHECK (4 ,3 ,0 )|| \ 1951 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 1952JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 )|| \ 1953JSON_HEDLEY_TI_CL7X_VERSION_CHECK (1 ,2 ,0 )|| \ 1954JSON_HEDLEY_TI_CLPRU_VERSION_CHECK (2 ,1 ,0 )|| \ 1955JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 )|| \ 1956JSON_HEDLEY_IAR_VERSION_CHECK (8 ,10 ,0 ) 1957#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) 1958#elif \ 1959JSON_HEDLEY_MSVC_VERSION_CHECK (13 ,10 ,0 )|| \ 1960JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 1961#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1962#elif JSON_HEDLEY_PGI_VERSION_CHECK (10 ,2 ,0 ) 1963#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") 1964#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK (6 ,0 ,0 )&& defined(__cplusplus ) 1965#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") 1966#elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 1967#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") 1968#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK (3 ,2 ,0 ) 1969#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) 1970#elif JSON_HEDLEY_PELLES_VERSION_CHECK (9 ,0 ,0 ) 1971#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1972#else 1973#define JSON_HEDLEY_NEVER_INLINE 1974#endif 1975 1976#if defined(JSON_HEDLEY_PRIVATE ) 1977#undef JSON_HEDLEY_PRIVATE 1978#endif 1979#if defined(JSON_HEDLEY_PUBLIC ) 1980#undef JSON_HEDLEY_PUBLIC 1981#endif 1982#if defined(JSON_HEDLEY_IMPORT ) 1983#undef JSON_HEDLEY_IMPORT 1984#endif 1985#if defined(_WIN32 )|| defined(__CYGWIN__ ) 1986# define JSON_HEDLEY_PRIVATE 1987# define JSON_HEDLEY_PUBLIC __declspec(dllexport) 1988# define JSON_HEDLEY_IMPORT __declspec(dllimport) 1989#else 1990# if \ 1991JSON_HEDLEY_HAS_ATTRIBUTE (visibility )|| \ 1992JSON_HEDLEY_GCC_VERSION_CHECK (3 ,3 ,0 )|| \ 1993JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,11 ,0 )|| \ 1994JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 1995JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 1996JSON_HEDLEY_IBM_VERSION_CHECK (13 ,1 ,0 )|| \ 1997 ( \ 1998 defined(__TI_EABI__ )&& \ 1999 ( \ 2000 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,2 ,0 )&& defined(__TI_GNU_ATTRIBUTE_SUPPORT__ ))|| \ 2001JSON_HEDLEY_TI_CL6X_VERSION_CHECK (7 ,5 ,0 ) \ 2002 ) \ 2003 )|| \ 2004JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 2005# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) 2006# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) 2007# else 2008# define JSON_HEDLEY_PRIVATE 2009# define JSON_HEDLEY_PUBLIC 2010# endif 2011# define JSON_HEDLEY_IMPORT extern 2012#endif 2013 2014#if defined(JSON_HEDLEY_NO_THROW ) 2015#undef JSON_HEDLEY_NO_THROW 2016#endif 2017#if \ 2018JSON_HEDLEY_HAS_ATTRIBUTE (nothrow )|| \ 2019JSON_HEDLEY_GCC_VERSION_CHECK (3 ,3 ,0 )|| \ 2020JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 2021JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 2022#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) 2023#elif \ 2024JSON_HEDLEY_MSVC_VERSION_CHECK (13 ,1 ,0 )|| \ 2025JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 )|| \ 2026JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 ) 2027#define JSON_HEDLEY_NO_THROW __declspec(nothrow) 2028#else 2029#define JSON_HEDLEY_NO_THROW 2030#endif 2031 2032#if defined(JSON_HEDLEY_FALL_THROUGH ) 2033#undef JSON_HEDLEY_FALL_THROUGH 2034#endif 2035#if \ 2036JSON_HEDLEY_HAS_ATTRIBUTE (fallthrough )|| \ 2037JSON_HEDLEY_GCC_VERSION_CHECK (7 ,0 ,0 )|| \ 2038JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 2039#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) 2040#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS (clang ,fallthrough ) 2041#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) 2042#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE (fallthrough ) 2043#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) 2044#elif defined(__fallthrough )/* SAL */ 2045#define JSON_HEDLEY_FALL_THROUGH __fallthrough 2046#else 2047#define JSON_HEDLEY_FALL_THROUGH 2048#endif 2049 2050#if defined(JSON_HEDLEY_RETURNS_NON_NULL ) 2051#undef JSON_HEDLEY_RETURNS_NON_NULL 2052#endif 2053#if \ 2054JSON_HEDLEY_HAS_ATTRIBUTE (returns_nonnull )|| \ 2055JSON_HEDLEY_GCC_VERSION_CHECK (4 ,9 ,0 )|| \ 2056JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 2057#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) 2058#elif defined(_Ret_notnull_ )/* SAL */ 2059#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ 2060#else 2061#define JSON_HEDLEY_RETURNS_NON_NULL 2062#endif 2063 2064#if defined(JSON_HEDLEY_ARRAY_PARAM ) 2065#undef JSON_HEDLEY_ARRAY_PARAM 2066#endif 2067#if \ 2068 defined(__STDC_VERSION__ )&& (__STDC_VERSION__ >=199901L )&& \ 2069 !defined(__STDC_NO_VLA__ )&& \ 2070 !defined(__cplusplus )&& \ 2071 !defined(JSON_HEDLEY_PGI_VERSION )&& \ 2072 !defined(JSON_HEDLEY_TINYC_VERSION ) 2073#define JSON_HEDLEY_ARRAY_PARAM (name ) (name) 2074#else 2075#define JSON_HEDLEY_ARRAY_PARAM (name ) 2076#endif 2077 2078#if defined(JSON_HEDLEY_IS_CONSTANT ) 2079#undef JSON_HEDLEY_IS_CONSTANT 2080#endif 2081#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR ) 2082#undef JSON_HEDLEY_REQUIRE_CONSTEXPR 2083#endif 2084/* JSON_HEDLEY_IS_CONSTEXPR_ is for 2085HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 2086#if defined(JSON_HEDLEY_IS_CONSTEXPR_ ) 2087#undef JSON_HEDLEY_IS_CONSTEXPR_ 2088#endif 2089#if \ 2090JSON_HEDLEY_HAS_BUILTIN (__builtin_constant_p )|| \ 2091JSON_HEDLEY_GCC_VERSION_CHECK (3 ,4 ,0 )|| \ 2092JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 2093JSON_HEDLEY_TINYC_VERSION_CHECK (0 ,9 ,19 )|| \ 2094JSON_HEDLEY_ARM_VERSION_CHECK (4 ,1 ,0 )|| \ 2095JSON_HEDLEY_IBM_VERSION_CHECK (13 ,1 ,0 )|| \ 2096JSON_HEDLEY_TI_CL6X_VERSION_CHECK (6 ,1 ,0 )|| \ 2097 (JSON_HEDLEY_SUNPRO_VERSION_CHECK (5 ,10 ,0 )&& !defined(__cplusplus ))|| \ 2098JSON_HEDLEY_CRAY_VERSION_CHECK (8 ,1 ,0 )|| \ 2099JSON_HEDLEY_MCST_LCC_VERSION_CHECK (1 ,25 ,10 ) 2100#define JSON_HEDLEY_IS_CONSTANT (expr ) __builtin_constant_p(expr) 2101#endif 2102#if !defined(__cplusplus ) 2103# if \ 2104JSON_HEDLEY_HAS_BUILTIN (__builtin_types_compatible_p )|| \ 2105JSON_HEDLEY_GCC_VERSION_CHECK (3 ,4 ,0 )|| \ 2106JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 2107JSON_HEDLEY_IBM_VERSION_CHECK (13 ,1 ,0 )|| \ 2108JSON_HEDLEY_CRAY_VERSION_CHECK (8 ,1 ,0 )|| \ 2109JSON_HEDLEY_ARM_VERSION_CHECK (5 ,4 ,0 )|| \ 2110JSON_HEDLEY_TINYC_VERSION_CHECK (0 ,9 ,24 ) 2111#if defined(__INTPTR_TYPE__ ) 2112#define JSON_HEDLEY_IS_CONSTEXPR_ (expr ) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) 2113#else 2114#include <stdint.h> 2115#define JSON_HEDLEY_IS_CONSTEXPR_ (expr ) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) 2116#endif 2117# elif \ 2118 ( \ 2119 defined(__STDC_VERSION__ )&& (__STDC_VERSION__ >=201112L )&& \ 2120 !defined(JSON_HEDLEY_SUNPRO_VERSION )&& \ 2121 !defined(JSON_HEDLEY_PGI_VERSION )&& \ 2122 !defined(JSON_HEDLEY_IAR_VERSION ))|| \ 2123 (JSON_HEDLEY_HAS_EXTENSION (c_generic_selections )&& !defined(JSON_HEDLEY_IAR_VERSION ))|| \ 2124JSON_HEDLEY_GCC_VERSION_CHECK (4 ,9 ,0 )|| \ 2125JSON_HEDLEY_INTEL_VERSION_CHECK (17 ,0 ,0 )|| \ 2126JSON_HEDLEY_IBM_VERSION_CHECK (12 ,1 ,0 )|| \ 2127JSON_HEDLEY_ARM_VERSION_CHECK (5 ,3 ,0 ) 2128#if defined(__INTPTR_TYPE__ ) 2129#define JSON_HEDLEY_IS_CONSTEXPR_ (expr ) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) 2130#else 2131#include <stdint.h> 2132#define JSON_HEDLEY_IS_CONSTEXPR_ (expr ) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) 2133#endif 2134# elif \ 2135 defined(JSON_HEDLEY_GCC_VERSION )|| \ 2136 defined(JSON_HEDLEY_INTEL_VERSION )|| \ 2137 defined(JSON_HEDLEY_TINYC_VERSION )|| \ 2138 defined(JSON_HEDLEY_TI_ARMCL_VERSION )|| \ 2139JSON_HEDLEY_TI_CL430_VERSION_CHECK (18 ,12 ,0 )|| \ 2140 defined(JSON_HEDLEY_TI_CL2000_VERSION )|| \ 2141 defined(JSON_HEDLEY_TI_CL6X_VERSION )|| \ 2142 defined(JSON_HEDLEY_TI_CL7X_VERSION )|| \ 2143 defined(JSON_HEDLEY_TI_CLPRU_VERSION )|| \ 2144 defined(__clang__ ) 2145# define JSON_HEDLEY_IS_CONSTEXPR_ (expr ) ( \ 2146 sizeof(void) != \ 2147 sizeof(*( \ 2148 1 ? \ 2149 ((void*) ((expr) * 0L) ) : \ 2150((struct { char v[sizeof(void) * 2]; } *) 1) \ 2151 ) \ 2152 ) \ 2153 ) 2154# endif 2155#endif 2156#if defined(JSON_HEDLEY_IS_CONSTEXPR_ ) 2157#if !defined(JSON_HEDLEY_IS_CONSTANT ) 2158#define JSON_HEDLEY_IS_CONSTANT (expr ) JSON_HEDLEY_IS_CONSTEXPR_(expr) 2159#endif 2160#define JSON_HEDLEY_REQUIRE_CONSTEXPR (expr ) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) 2161#else 2162#if !defined(JSON_HEDLEY_IS_CONSTANT ) 2163#define JSON_HEDLEY_IS_CONSTANT (expr ) (0) 2164#endif 2165#define JSON_HEDLEY_REQUIRE_CONSTEXPR (expr ) (expr) 2166#endif 2167 2168#if defined(JSON_HEDLEY_BEGIN_C_DECLS ) 2169#undef JSON_HEDLEY_BEGIN_C_DECLS 2170#endif 2171#if defined(JSON_HEDLEY_END_C_DECLS ) 2172#undef JSON_HEDLEY_END_C_DECLS 2173#endif 2174#if defined(JSON_HEDLEY_C_DECL ) 2175#undef JSON_HEDLEY_C_DECL 2176#endif 2177#if defined(__cplusplus ) 2178#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { 2179#define JSON_HEDLEY_END_C_DECLS } 2180#define JSON_HEDLEY_C_DECL extern "C" 2181#else 2182#define JSON_HEDLEY_BEGIN_C_DECLS 2183#define JSON_HEDLEY_END_C_DECLS 2184#define JSON_HEDLEY_C_DECL 2185#endif 2186 2187#if defined(JSON_HEDLEY_STATIC_ASSERT ) 2188#undef JSON_HEDLEY_STATIC_ASSERT 2189#endif 2190#if \ 2191 !defined(__cplusplus )&& ( \ 2192 (defined(__STDC_VERSION__ )&& (__STDC_VERSION__ >=201112L ))|| \ 2193 (JSON_HEDLEY_HAS_FEATURE (c_static_assert )&& !defined(JSON_HEDLEY_INTEL_CL_VERSION ))|| \ 2194JSON_HEDLEY_GCC_VERSION_CHECK (6 ,0 ,0 )|| \ 2195JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 )|| \ 2196 defined(_Static_assert ) \ 2197 ) 2198# define JSON_HEDLEY_STATIC_ASSERT (expr ,message ) _Static_assert(expr, message) 2199#elif \ 2200 (defined(__cplusplus )&& (__cplusplus >=201103L ))|| \ 2201JSON_HEDLEY_MSVC_VERSION_CHECK (16 ,0 ,0 )|| \ 2202JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 2203# define JSON_HEDLEY_STATIC_ASSERT (expr ,message ) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) 2204#else 2205# define JSON_HEDLEY_STATIC_ASSERT (expr ,message ) 2206#endif 2207 2208#if defined(JSON_HEDLEY_NULL ) 2209#undef JSON_HEDLEY_NULL 2210#endif 2211#if defined(__cplusplus ) 2212#if __cplusplus >=201103L 2213#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) 2214#elif defined(NULL ) 2215#define JSON_HEDLEY_NULL NULL 2216#else 2217#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) 2218#endif 2219#elif defined(NULL ) 2220#define JSON_HEDLEY_NULL NULL 2221#else 2222#define JSON_HEDLEY_NULL ((void*) 0) 2223#endif 2224 2225#if defined(JSON_HEDLEY_MESSAGE ) 2226#undef JSON_HEDLEY_MESSAGE 2227#endif 2228#if JSON_HEDLEY_HAS_WARNING ("- Wunknown - pragmas ") 2229# define JSON_HEDLEY_MESSAGE (msg ) \ 2230 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2231 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2232 JSON_HEDLEY_PRAGMA(message msg) \ 2233 JSON_HEDLEY_DIAGNOSTIC_POP 2234#elif \ 2235JSON_HEDLEY_GCC_VERSION_CHECK (4 ,4 ,0 )|| \ 2236JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 ) 2237# define JSON_HEDLEY_MESSAGE (msg ) JSON_HEDLEY_PRAGMA(message msg) 2238#elif JSON_HEDLEY_CRAY_VERSION_CHECK (5 ,0 ,0 ) 2239# define JSON_HEDLEY_MESSAGE (msg ) JSON_HEDLEY_PRAGMA(_CRI message msg) 2240#elif JSON_HEDLEY_IAR_VERSION_CHECK (8 ,0 ,0 ) 2241# define JSON_HEDLEY_MESSAGE (msg ) JSON_HEDLEY_PRAGMA(message(msg)) 2242#elif JSON_HEDLEY_PELLES_VERSION_CHECK (2 ,0 ,0 ) 2243# define JSON_HEDLEY_MESSAGE (msg ) JSON_HEDLEY_PRAGMA(message(msg)) 2244#else 2245# define JSON_HEDLEY_MESSAGE (msg ) 2246#endif 2247 2248#if defined(JSON_HEDLEY_WARNING ) 2249#undef JSON_HEDLEY_WARNING 2250#endif 2251#if JSON_HEDLEY_HAS_WARNING ("- Wunknown - pragmas ") 2252# define JSON_HEDLEY_WARNING (msg ) \ 2253 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2254 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2255 JSON_HEDLEY_PRAGMA(clang warning msg) \ 2256 JSON_HEDLEY_DIAGNOSTIC_POP 2257#elif \ 2258JSON_HEDLEY_GCC_VERSION_CHECK (4 ,8 ,0 )|| \ 2259JSON_HEDLEY_PGI_VERSION_CHECK (18 ,4 ,0 )|| \ 2260JSON_HEDLEY_INTEL_VERSION_CHECK (13 ,0 ,0 ) 2261# define JSON_HEDLEY_WARNING (msg ) JSON_HEDLEY_PRAGMA(GCC warning msg) 2262#elif \ 2263JSON_HEDLEY_MSVC_VERSION_CHECK (15 ,0 ,0 )|| \ 2264JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 2265# define JSON_HEDLEY_WARNING (msg ) JSON_HEDLEY_PRAGMA(message(msg)) 2266#else 2267# define JSON_HEDLEY_WARNING (msg ) JSON_HEDLEY_MESSAGE(msg) 2268#endif 2269 2270#if defined(JSON_HEDLEY_REQUIRE ) 2271#undef JSON_HEDLEY_REQUIRE 2272#endif 2273#if defined(JSON_HEDLEY_REQUIRE_MSG ) 2274#undef JSON_HEDLEY_REQUIRE_MSG 2275#endif 2276#if JSON_HEDLEY_HAS_ATTRIBUTE (diagnose_if ) 2277# if JSON_HEDLEY_HAS_WARNING ("- Wgcc - compat ") 2278# define JSON_HEDLEY_REQUIRE (expr ) \ 2279 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2280 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2281 __attribute__((diagnose_if(!(expr), #expr, "error"))) \ 2282 JSON_HEDLEY_DIAGNOSTIC_POP 2283# define JSON_HEDLEY_REQUIRE_MSG (expr ,msg ) \ 2284 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2285 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2286 __attribute__((diagnose_if(!(expr), msg, "error"))) \ 2287 JSON_HEDLEY_DIAGNOSTIC_POP 2288# else 2289# define JSON_HEDLEY_REQUIRE (expr ) __attribute__((diagnose_if(!(expr), #expr, "error"))) 2290# define JSON_HEDLEY_REQUIRE_MSG (expr ,msg ) __attribute__((diagnose_if(!(expr), msg, "error"))) 2291# endif 2292#else 2293# define JSON_HEDLEY_REQUIRE (expr ) 2294# define JSON_HEDLEY_REQUIRE_MSG (expr ,msg ) 2295#endif 2296 2297#if defined(JSON_HEDLEY_FLAGS ) 2298#undef JSON_HEDLEY_FLAGS 2299#endif 2300#if JSON_HEDLEY_HAS_ATTRIBUTE (flag_enum )&& (!defined(__cplusplus )|| JSON_HEDLEY_HAS_WARNING ("- Wbitfield - enum - conversion ")) 2301#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) 2302#else 2303#define JSON_HEDLEY_FLAGS 2304#endif 2305 2306#if defined(JSON_HEDLEY_FLAGS_CAST ) 2307#undef JSON_HEDLEY_FLAGS_CAST 2308#endif 2309#if JSON_HEDLEY_INTEL_VERSION_CHECK (19 ,0 ,0 ) 2310# define JSON_HEDLEY_FLAGS_CAST (T ,expr ) (__extension__ ({ \ 2311 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2312 _Pragma("warning(disable:188)") \ 2313 ((T) (expr)); \ 2314 JSON_HEDLEY_DIAGNOSTIC_POP \ 2315 })) 2316#else 2317# define JSON_HEDLEY_FLAGS_CAST (T ,expr ) JSON_HEDLEY_STATIC_CAST(T, expr) 2318#endif 2319 2320#if defined(JSON_HEDLEY_EMPTY_BASES ) 2321#undef JSON_HEDLEY_EMPTY_BASES 2322#endif 2323#if \ 2324 (JSON_HEDLEY_MSVC_VERSION_CHECK (19 ,0 ,23918 )&& !JSON_HEDLEY_MSVC_VERSION_CHECK (20 ,0 ,0 ))|| \ 2325JSON_HEDLEY_INTEL_CL_VERSION_CHECK (2021 ,1 ,0 ) 2326#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) 2327#else 2328#define JSON_HEDLEY_EMPTY_BASES 2329#endif 2330 2331/* Remaining macros are deprecated. */ 2332 2333#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK ) 2334#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 2335#endif 2336#if defined(__clang__ ) 2337#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK (major ,minor ,patch ) (0) 2338#else 2339#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK (major ,minor ,patch ) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 2340#endif 2341 2342#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE ) 2343#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 2344#endif 2345#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE (attribute ) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 2346 2347#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE ) 2348#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 2349#endif 2350#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE (attribute ) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) 2351 2352#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN ) 2353#undef JSON_HEDLEY_CLANG_HAS_BUILTIN 2354#endif 2355#define JSON_HEDLEY_CLANG_HAS_BUILTIN (builtin ) JSON_HEDLEY_HAS_BUILTIN(builtin) 2356 2357#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE ) 2358#undef JSON_HEDLEY_CLANG_HAS_FEATURE 2359#endif 2360#define JSON_HEDLEY_CLANG_HAS_FEATURE (feature ) JSON_HEDLEY_HAS_FEATURE(feature) 2361 2362#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION ) 2363#undef JSON_HEDLEY_CLANG_HAS_EXTENSION 2364#endif 2365#define JSON_HEDLEY_CLANG_HAS_EXTENSION (extension ) JSON_HEDLEY_HAS_EXTENSION(extension) 2366 2367#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE ) 2368#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 2369#endif 2370#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE (attribute ) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) 2371 2372#if defined(JSON_HEDLEY_CLANG_HAS_WARNING ) 2373#undef JSON_HEDLEY_CLANG_HAS_WARNING 2374#endif 2375#define JSON_HEDLEY_CLANG_HAS_WARNING (warning ) JSON_HEDLEY_HAS_WARNING(warning) 2376 2377#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ 2378 2379 2380// This file contains all internal macro definitions (except those affecting ABI) 2381// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them 2382 2383// #include <nlohmann/detail/abi_macros.hpp> 2384 2385 2386// exclude unsupported compilers 2387#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK ) 2388#if defined(__clang__ ) 2389#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__ )< 30400 2390#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 2391#endif 2392#elif defined(__GNUC__ )&& !(defined(__ICC )|| defined(__INTEL_COMPILER )) 2393#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ )< 40800 2394#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 2395#endif 2396#endif 2397#endif 2398 2399// C++ language standard detection 2400// if the user manually specified the used c++ version this is skipped 2401#if !defined(JSON_HAS_CPP_23 )&& !defined(JSON_HAS_CPP_20 )&& !defined(JSON_HAS_CPP_17 )&& !defined(JSON_HAS_CPP_14 )&& !defined(JSON_HAS_CPP_11 ) 2402#if (defined(__cplusplus )&& __cplusplus > 202002L )|| (defined(_MSVC_LANG )&& _MSVC_LANG > 202002L ) 2403#define JSON_HAS_CPP_23 2404#define JSON_HAS_CPP_20 2405#define JSON_HAS_CPP_17 2406#define JSON_HAS_CPP_14 2407#elif (defined(__cplusplus )&& __cplusplus > 201703L )|| (defined(_MSVC_LANG )&& _MSVC_LANG > 201703L ) 2408#define JSON_HAS_CPP_20 2409#define JSON_HAS_CPP_17 2410#define JSON_HAS_CPP_14 2411#elif (defined(__cplusplus )&& __cplusplus > 201402L )|| (defined(_HAS_CXX17 )&& _HAS_CXX17 == 1 )// fix for issue #464 2412#define JSON_HAS_CPP_17 2413#define JSON_HAS_CPP_14 2414#elif (defined(__cplusplus )&& __cplusplus > 201103L )|| (defined(_HAS_CXX14 )&& _HAS_CXX14 == 1 ) 2415#define JSON_HAS_CPP_14 2416#endif 2417// the cpp 11 flag is always specified because it is the minimal required version 2418#define JSON_HAS_CPP_11 2419#endif 2420 2421#ifdef __has_include 2422#if __has_include (< version > ) 2423#include <version> 2424#endif 2425#endif 2426 2427#if !defined(JSON_HAS_FILESYSTEM )&& !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM ) 2428#ifdef JSON_HAS_CPP_17 2429#if defined(__cpp_lib_filesystem ) 2430#define JSON_HAS_FILESYSTEM 1 2431#elif defined(__cpp_lib_experimental_filesystem ) 2432#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2433#elif !defined(__has_include ) 2434#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2435#elif __has_include (< filesystem > ) 2436#define JSON_HAS_FILESYSTEM 1 2437#elif __has_include (< experimental /filesystem > ) 2438#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2439#endif 2440 2441// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ 2442#if defined(__MINGW32__ )&& defined(__GNUC__ )&& __GNUC__ == 8 2443#undef JSON_HAS_FILESYSTEM 2444#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2445#endif 2446 2447// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support 2448#if defined(__GNUC__ )&& !defined(__clang__ )&& __GNUC__ < 8 2449#undef JSON_HAS_FILESYSTEM 2450#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2451#endif 2452 2453// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support 2454#if defined(__clang_major__ )&& __clang_major__ < 7 2455#undef JSON_HAS_FILESYSTEM 2456#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2457#endif 2458 2459// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support 2460#if defined(_MSC_VER )&& _MSC_VER < 1914 2461#undef JSON_HAS_FILESYSTEM 2462#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2463#endif 2464 2465// no filesystem support before iOS 13 2466#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED )&& __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 2467#undef JSON_HAS_FILESYSTEM 2468#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2469#endif 2470 2471// no filesystem support before macOS Catalina 2472#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED )&& __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 2473#undef JSON_HAS_FILESYSTEM 2474#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2475#endif 2476#endif 2477#endif 2478 2479#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2480#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 2481#endif 2482 2483#ifndef JSON_HAS_FILESYSTEM 2484#define JSON_HAS_FILESYSTEM 0 2485#endif 2486 2487#ifndef JSON_HAS_THREE_WAY_COMPARISON 2488#if defined(__cpp_impl_three_way_comparison )&& __cpp_impl_three_way_comparison >=201907L \ 2489&& defined(__cpp_lib_three_way_comparison )&& __cpp_lib_three_way_comparison >=201907L 2490#define JSON_HAS_THREE_WAY_COMPARISON 1 2491#else 2492#define JSON_HAS_THREE_WAY_COMPARISON 0 2493#endif 2494#endif 2495 2496#ifndef JSON_HAS_RANGES 2497// ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error 2498#if defined(__GLIBCXX__ )&& __GLIBCXX__ == 20210427 2499#define JSON_HAS_RANGES 0 2500#elif defined(__cpp_lib_ranges ) 2501#define JSON_HAS_RANGES 1 2502#else 2503#define JSON_HAS_RANGES 0 2504#endif 2505#endif 2506 2507#ifndef JSON_HAS_STATIC_RTTI 2508#if !defined(_HAS_STATIC_RTTI )|| _HAS_STATIC_RTTI != 0 2509#define JSON_HAS_STATIC_RTTI 1 2510#else 2511#define JSON_HAS_STATIC_RTTI 0 2512#endif 2513#endif 2514 2515#ifdef JSON_HAS_CPP_17 2516#define JSON_INLINE_VARIABLE inline 2517#else 2518#define JSON_INLINE_VARIABLE 2519#endif 2520 2521#if JSON_HEDLEY_HAS_ATTRIBUTE (no_unique_address ) 2522#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] 2523#else 2524#define JSON_NO_UNIQUE_ADDRESS 2525#endif 2526 2527// disable documentation warnings on clang 2528#if defined(__clang__ ) 2529#pragma clang diagnostic push 2530#pragma clang diagnostic ignored "-Wdocumentation" 2531#pragma clang diagnostic ignored "-Wdocumentation-unknown-command" 2532#endif 2533 2534// allow disabling exceptions 2535#if (defined(__cpp_exceptions )|| defined(__EXCEPTIONS )|| defined(_CPPUNWIND ))&& !defined(JSON_NOEXCEPTION ) 2536#define JSON_THROW (exception ) throw exception 2537#define JSON_TRY try 2538#define JSON_CATCH (exception ) catch(exception) 2539#define JSON_INTERNAL_CATCH (exception ) catch(exception) 2540#else 2541#include <cstdlib> 2542#define JSON_THROW (exception ) std::abort() 2543#define JSON_TRY if(true) 2544#define JSON_CATCH (exception ) if(false) 2545#define JSON_INTERNAL_CATCH (exception ) if(false) 2546#endif 2547 2548// override exception macros 2549#if defined(JSON_THROW_USER ) 2550#undef JSON_THROW 2551#define JSON_THROW JSON_THROW_USER 2552#endif 2553#if defined(JSON_TRY_USER ) 2554#undef JSON_TRY 2555#define JSON_TRY JSON_TRY_USER 2556#endif 2557#if defined(JSON_CATCH_USER ) 2558#undef JSON_CATCH 2559#define JSON_CATCH JSON_CATCH_USER 2560#undef JSON_INTERNAL_CATCH 2561#define JSON_INTERNAL_CATCH JSON_CATCH_USER 2562#endif 2563#if defined(JSON_INTERNAL_CATCH_USER ) 2564#undef JSON_INTERNAL_CATCH 2565#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER 2566#endif 2567 2568// allow overriding assert 2569#if !defined(JSON_ASSERT ) 2570#include <cassert> // assert 2571#define JSON_ASSERT (x ) assert(x) 2572#endif 2573 2574// allow to access some private functions (needed by the test suite) 2575#if defined(JSON_TESTS_PRIVATE ) 2576#define JSON_PRIVATE_UNLESS_TESTED public 2577#else 2578#define JSON_PRIVATE_UNLESS_TESTED private 2579#endif 2580 2581/*! 2582@brief macro to briefly define a mapping between an enum and JSON 2583@def NLOHMANN_JSON_SERIALIZE_ENUM 2584@since version 3.4.0 2585*/ 2586#define NLOHMANN_JSON_SERIALIZE_ENUM (ENUM_TYPE , ...) \ 2587 template<typename BasicJsonType> \ 2588 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ 2589 { \ 2590/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ 2591 static_assert(std::is_enum < ENUM_TYPE > ::value ,#ENUM_TYPE " must be an enum!" ); \ 2592/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \ 2593static const std::pair < ENUM_TYPE ,BasicJsonType > m []= __VA_ARGS__ ; \ 2594auto it = std::find_if (std::begin (m ), std::end (m ), \ 2595 [e ](const std::pair < ENUM_TYPE ,BasicJsonType >& ej_pair )-> bool \ 2596 { \ 2597return ej_pair .first == e ; \ 2598 }); \ 2599j = ((it != std::end (m )) ?it : std::begin (m ))-> second ; \ 2600 } \ 2601template < typename BasicJsonType > \ 2602inline void from_json (const BasicJsonType & j ,ENUM_TYPE & e ) \ 2603 { \ 2604/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ 2605 static_assert(std::is_enum < ENUM_TYPE > ::value ,#ENUM_TYPE " must be an enum!" ); \ 2606/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \ 2607static const std::pair < ENUM_TYPE ,BasicJsonType > m []= __VA_ARGS__ ; \ 2608auto it = std::find_if (std::begin (m ), std::end (m ), \ 2609 [& j ](const std::pair < ENUM_TYPE ,BasicJsonType >& ej_pair )-> bool \ 2610 { \ 2611return ej_pair .second == j ; \ 2612 }); \ 2613e = ((it != std::end (m )) ?it : std::begin (m ))-> first ; \ 2614 } 2615 2616// Ugly macros to avoid uglier copy-paste when specializing basic_json. They 2617// may be removed in the future once the class is split. 2618 2619#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ 2620 template<template<typename, typename, typename...> class ObjectType, \ 2621 template<typename, typename...> class ArrayType, \ 2622 class StringType, class BooleanType, class NumberIntegerType, \ 2623 class NumberUnsignedType, class NumberFloatType, \ 2624 template<typename> class AllocatorType, \ 2625 template<typename, typename = void> class JSONSerializer, \ 2626 class BinaryType, \ 2627 class CustomBaseClass> 2628 2629#define NLOHMANN_BASIC_JSON_TPL \ 2630 basic_json<ObjectType, ArrayType, StringType, BooleanType, \ 2631 NumberIntegerType, NumberUnsignedType, NumberFloatType, \ 2632 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> 2633 2634// Macros to simplify conversion from/to types 2635 2636#define NLOHMANN_JSON_EXPAND (x ) x 2637#define NLOHMANN_JSON_GET_MACRO (_1 ,_2 ,_3 ,_4 ,_5 ,_6 ,_7 ,_8 ,_9 ,_10 ,_11 ,_12 ,_13 ,_14 ,_15 ,_16 ,_17 ,_18 ,_19 ,_20 ,_21 ,_22 ,_23 ,_24 ,_25 ,_26 ,_27 ,_28 ,_29 ,_30 ,_31 ,_32 ,_33 ,_34 ,_35 ,_36 ,_37 ,_38 ,_39 ,_40 ,_41 ,_42 ,_43 ,_44 ,_45 ,_46 ,_47 ,_48 ,_49 ,_50 ,_51 ,_52 ,_53 ,_54 ,_55 ,_56 ,_57 ,_58 ,_59 ,_60 ,_61 ,_62 ,_63 ,_64 ,NAME ,...) NAME 2638#define NLOHMANN_JSON_PASTE (...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ 2639 NLOHMANN_JSON_PASTE64, \ 2640 NLOHMANN_JSON_PASTE63, \ 2641 NLOHMANN_JSON_PASTE62, \ 2642 NLOHMANN_JSON_PASTE61, \ 2643 NLOHMANN_JSON_PASTE60, \ 2644 NLOHMANN_JSON_PASTE59, \ 2645 NLOHMANN_JSON_PASTE58, \ 2646 NLOHMANN_JSON_PASTE57, \ 2647 NLOHMANN_JSON_PASTE56, \ 2648 NLOHMANN_JSON_PASTE55, \ 2649 NLOHMANN_JSON_PASTE54, \ 2650 NLOHMANN_JSON_PASTE53, \ 2651 NLOHMANN_JSON_PASTE52, \ 2652 NLOHMANN_JSON_PASTE51, \ 2653 NLOHMANN_JSON_PASTE50, \ 2654 NLOHMANN_JSON_PASTE49, \ 2655 NLOHMANN_JSON_PASTE48, \ 2656 NLOHMANN_JSON_PASTE47, \ 2657 NLOHMANN_JSON_PASTE46, \ 2658 NLOHMANN_JSON_PASTE45, \ 2659 NLOHMANN_JSON_PASTE44, \ 2660 NLOHMANN_JSON_PASTE43, \ 2661 NLOHMANN_JSON_PASTE42, \ 2662 NLOHMANN_JSON_PASTE41, \ 2663 NLOHMANN_JSON_PASTE40, \ 2664 NLOHMANN_JSON_PASTE39, \ 2665 NLOHMANN_JSON_PASTE38, \ 2666 NLOHMANN_JSON_PASTE37, \ 2667 NLOHMANN_JSON_PASTE36, \ 2668 NLOHMANN_JSON_PASTE35, \ 2669 NLOHMANN_JSON_PASTE34, \ 2670 NLOHMANN_JSON_PASTE33, \ 2671 NLOHMANN_JSON_PASTE32, \ 2672 NLOHMANN_JSON_PASTE31, \ 2673 NLOHMANN_JSON_PASTE30, \ 2674 NLOHMANN_JSON_PASTE29, \ 2675 NLOHMANN_JSON_PASTE28, \ 2676 NLOHMANN_JSON_PASTE27, \ 2677 NLOHMANN_JSON_PASTE26, \ 2678 NLOHMANN_JSON_PASTE25, \ 2679 NLOHMANN_JSON_PASTE24, \ 2680 NLOHMANN_JSON_PASTE23, \ 2681 NLOHMANN_JSON_PASTE22, \ 2682 NLOHMANN_JSON_PASTE21, \ 2683 NLOHMANN_JSON_PASTE20, \ 2684 NLOHMANN_JSON_PASTE19, \ 2685 NLOHMANN_JSON_PASTE18, \ 2686 NLOHMANN_JSON_PASTE17, \ 2687 NLOHMANN_JSON_PASTE16, \ 2688 NLOHMANN_JSON_PASTE15, \ 2689 NLOHMANN_JSON_PASTE14, \ 2690 NLOHMANN_JSON_PASTE13, \ 2691 NLOHMANN_JSON_PASTE12, \ 2692 NLOHMANN_JSON_PASTE11, \ 2693 NLOHMANN_JSON_PASTE10, \ 2694 NLOHMANN_JSON_PASTE9, \ 2695 NLOHMANN_JSON_PASTE8, \ 2696 NLOHMANN_JSON_PASTE7, \ 2697 NLOHMANN_JSON_PASTE6, \ 2698 NLOHMANN_JSON_PASTE5, \ 2699 NLOHMANN_JSON_PASTE4, \ 2700 NLOHMANN_JSON_PASTE3, \ 2701 NLOHMANN_JSON_PASTE2, \ 2702 NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) 2703#define NLOHMANN_JSON_PASTE2 (func ,v1 ) func(v1) 2704#define NLOHMANN_JSON_PASTE3 (func ,v1 ,v2 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) 2705#define NLOHMANN_JSON_PASTE4 (func ,v1 ,v2 ,v3 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) 2706#define NLOHMANN_JSON_PASTE5 (func ,v1 ,v2 ,v3 ,v4 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) 2707#define NLOHMANN_JSON_PASTE6 (func ,v1 ,v2 ,v3 ,v4 ,v5 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) 2708#define NLOHMANN_JSON_PASTE7 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) 2709#define NLOHMANN_JSON_PASTE8 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) 2710#define NLOHMANN_JSON_PASTE9 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) 2711#define NLOHMANN_JSON_PASTE10 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) 2712#define NLOHMANN_JSON_PASTE11 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) 2713#define NLOHMANN_JSON_PASTE12 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) 2714#define NLOHMANN_JSON_PASTE13 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) 2715#define NLOHMANN_JSON_PASTE14 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) 2716#define NLOHMANN_JSON_PASTE15 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) 2717#define NLOHMANN_JSON_PASTE16 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) 2718#define NLOHMANN_JSON_PASTE17 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) 2719#define NLOHMANN_JSON_PASTE18 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) 2720#define NLOHMANN_JSON_PASTE19 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) 2721#define NLOHMANN_JSON_PASTE20 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) 2722#define NLOHMANN_JSON_PASTE21 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) 2723#define NLOHMANN_JSON_PASTE22 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) 2724#define NLOHMANN_JSON_PASTE23 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) 2725#define NLOHMANN_JSON_PASTE24 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) 2726#define NLOHMANN_JSON_PASTE25 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) 2727#define NLOHMANN_JSON_PASTE26 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) 2728#define NLOHMANN_JSON_PASTE27 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) 2729#define NLOHMANN_JSON_PASTE28 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) 2730#define NLOHMANN_JSON_PASTE29 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) 2731#define NLOHMANN_JSON_PASTE30 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) 2732#define NLOHMANN_JSON_PASTE31 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) 2733#define NLOHMANN_JSON_PASTE32 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) 2734#define NLOHMANN_JSON_PASTE33 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) 2735#define NLOHMANN_JSON_PASTE34 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) 2736#define NLOHMANN_JSON_PASTE35 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) 2737#define NLOHMANN_JSON_PASTE36 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) 2738#define NLOHMANN_JSON_PASTE37 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) 2739#define NLOHMANN_JSON_PASTE38 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) 2740#define NLOHMANN_JSON_PASTE39 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) 2741#define NLOHMANN_JSON_PASTE40 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) 2742#define NLOHMANN_JSON_PASTE41 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) 2743#define NLOHMANN_JSON_PASTE42 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) 2744#define NLOHMANN_JSON_PASTE43 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) 2745#define NLOHMANN_JSON_PASTE44 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) 2746#define NLOHMANN_JSON_PASTE45 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) 2747#define NLOHMANN_JSON_PASTE46 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) 2748#define NLOHMANN_JSON_PASTE47 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) 2749#define NLOHMANN_JSON_PASTE48 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) 2750#define NLOHMANN_JSON_PASTE49 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) 2751#define NLOHMANN_JSON_PASTE50 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) 2752#define NLOHMANN_JSON_PASTE51 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) 2753#define NLOHMANN_JSON_PASTE52 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) 2754#define NLOHMANN_JSON_PASTE53 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) 2755#define NLOHMANN_JSON_PASTE54 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) 2756#define NLOHMANN_JSON_PASTE55 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) 2757#define NLOHMANN_JSON_PASTE56 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) 2758#define NLOHMANN_JSON_PASTE57 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) 2759#define NLOHMANN_JSON_PASTE58 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ,v57 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) 2760#define NLOHMANN_JSON_PASTE59 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ,v57 ,v58 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) 2761#define NLOHMANN_JSON_PASTE60 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ,v57 ,v58 ,v59 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) 2762#define NLOHMANN_JSON_PASTE61 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ,v57 ,v58 ,v59 ,v60 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) 2763#define NLOHMANN_JSON_PASTE62 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ,v57 ,v58 ,v59 ,v60 ,v61 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) 2764#define NLOHMANN_JSON_PASTE63 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ,v57 ,v58 ,v59 ,v60 ,v61 ,v62 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) 2765#define NLOHMANN_JSON_PASTE64 (func ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10 ,v11 ,v12 ,v13 ,v14 ,v15 ,v16 ,v17 ,v18 ,v19 ,v20 ,v21 ,v22 ,v23 ,v24 ,v25 ,v26 ,v27 ,v28 ,v29 ,v30 ,v31 ,v32 ,v33 ,v34 ,v35 ,v36 ,v37 ,v38 ,v39 ,v40 ,v41 ,v42 ,v43 ,v44 ,v45 ,v46 ,v47 ,v48 ,v49 ,v50 ,v51 ,v52 ,v53 ,v54 ,v55 ,v56 ,v57 ,v58 ,v59 ,v60 ,v61 ,v62 ,v63 ) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) 2766 2767#define NLOHMANN_JSON_TO (v1 ) nlohmann_json_j[#v1] = nlohmann_json_t.v1; 2768#define NLOHMANN_JSON_FROM (v1 ) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); 2769#define NLOHMANN_JSON_FROM_WITH_DEFAULT (v1 ) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; 2770 2771/*! 2772@brief macro 2773@def NLOHMANN_DEFINE_TYPE_INTRUSIVE 2774@since version 3.9.0 2775@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ 2776*/ 2777#define NLOHMANN_DEFINE_TYPE_INTRUSIVE (Type , ...) \ 2778 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2779 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2780 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2781 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2782 2783/*! 2784@brief macro 2785@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT 2786@since version 3.11.0 2787@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ 2788*/ 2789#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT (Type , ...) \ 2790 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2791 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2792 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2793 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2794 2795/*! 2796@brief macro 2797@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE 2798@since version 3.11.3 2799@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ 2800*/ 2801#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE (Type , ...) \ 2802 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2803 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } 2804 2805/*! 2806@brief macro 2807@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE 2808@since version 3.9.0 2809@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ 2810*/ 2811#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE (Type , ...) \ 2812 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2813 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2814 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2815 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2816 2817/*! 2818@brief macro 2819@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT 2820@since version 3.11.0 2821@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ 2822*/ 2823#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (Type , ...) \ 2824 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2825 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2826 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2827 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2828 2829/*! 2830@brief macro 2831@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE 2832@since version 3.11.3 2833@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ 2834*/ 2835#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE (Type , ...) \ 2836 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2837 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } 2838 2839/*! 2840@brief macro 2841@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE 2842@since version 3.12.0 2843@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ 2844*/ 2845#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE (Type ,BaseType , ...) \ 2846 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2847 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2848 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2849 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2850 2851/*! 2852@brief macro 2853@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT 2854@since version 3.12.0 2855@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ 2856*/ 2857#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT (Type ,BaseType , ...) \ 2858 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2859 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2860 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2861 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2862 2863/*! 2864@brief macro 2865@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE 2866@since version 3.12.0 2867@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ 2868*/ 2869#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE (Type ,BaseType , ...) \ 2870 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2871 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } 2872 2873/*! 2874@brief macro 2875@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE 2876@since version 3.12.0 2877@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ 2878*/ 2879#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE (Type ,BaseType , ...) \ 2880 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2881 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2882 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2883 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2884 2885/*! 2886@brief macro 2887@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT 2888@since version 3.12.0 2889@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ 2890*/ 2891#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT (Type ,BaseType , ...) \ 2892 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2893 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2894 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2895 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2896 2897/*! 2898@brief macro 2899@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE 2900@since version 3.12.0 2901@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ 2902*/ 2903#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE (Type ,BaseType , ...) \ 2904 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \ 2905 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } 2906 2907// inspired from https://stackoverflow.com/a/26745591 2908// allows calling any std function as if (e.g., with begin): 2909// using std::begin; begin(x); 2910// 2911// it allows using the detected idiom to retrieve the return type 2912// of such an expression 2913#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL (std_name ) \ 2914 namespace detail { \ 2915 using std::std_name; \ 2916 \ 2917 template<typename... T> \ 2918 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2919 } \ 2920 \ 2921 namespace detail2 { \ 2922 struct std_name##_tag \ 2923 { \ 2924 }; \ 2925 \ 2926 template<typename... T> \ 2927 std_name##_tag std_name(T&&...); \ 2928 \ 2929 template<typename... T> \ 2930 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2931 \ 2932 template<typename... T> \ 2933 struct would_call_std_##std_name \ 2934 { \ 2935 static constexpr auto const value = ::nlohmann::detail:: \ 2936 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \ 2937 }; \ 2938 }/* namespace detail2 */ \ 2939 \ 2940template < typename ...T > \ 2941struct would_call_std_ ##std_name : detail2::would_call_std_##std_name<T...> \ 2942 { \ 2943 } 2944 2945#ifndef JSON_USE_IMPLICIT_CONVERSIONS 2946#define JSON_USE_IMPLICIT_CONVERSIONS 1 2947#endif 2948 2949#if JSON_USE_IMPLICIT_CONVERSIONS 2950#define JSON_EXPLICIT 2951#else 2952#define JSON_EXPLICIT explicit 2953#endif 2954 2955#ifndef JSON_DISABLE_ENUM_SERIALIZATION 2956#define JSON_DISABLE_ENUM_SERIALIZATION 0 2957#endif 2958 2959#ifndef JSON_USE_GLOBAL_UDLS 2960#define JSON_USE_GLOBAL_UDLS 1 2961#endif 2962 2963#if JSON_HAS_THREE_WAY_COMPARISON 2964#include <compare> // partial_ordering 2965#endif 2966 2967NLOHMANN_JSON_NAMESPACE_BEGIN 2968namespace detail 2969{ 2970 2971/////////////////////////// 2972// JSON type enumeration // 2973/////////////////////////// 2974 2975/*! 2976@brief the JSON type enumeration 2977 2978This enumeration collects the different JSON types. It is internally used to 2979distinguish the stored values, and the functions @ref basic_json::is_null(), 2980@ref basic_json::is_object(), @ref basic_json::is_array(), 2981@ref basic_json::is_string(), @ref basic_json::is_boolean(), 2982@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), 2983@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), 2984@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and 2985@ref basic_json::is_structured() rely on it. 2986 2987@note There are three enumeration entries (number_integer, number_unsigned, and 2988number_float), because the library distinguishes these three types for numbers: 2989@ref basic_json::number_unsigned_t is used for unsigned integers, 2990@ref basic_json::number_integer_t is used for signed integers, and 2991@ref basic_json::number_float_t is used for floating-point numbers or to 2992approximate integers which do not fit in the limits of their respective type. 2993 2994@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON 2995value with the default value for a given type 2996 2997@since version 1.0.0 2998*/ 2999enum class value_t : std::uint8_t 3000{ 3001null ,///< null value 3002object ,///< object (unordered set of name/value pairs) 3003array ,///< array (ordered collection of values) 3004string ,///< string value 3005boolean ,///< boolean value 3006number_integer ,///< number value (signed integer) 3007number_unsigned ,///< number value (unsigned integer) 3008number_float ,///< number value (floating-point) 3009binary ,///< binary array (ordered collection of bytes) 3010discarded ///< discarded by the parser callback function 3011}; 3012 3013/*! 3014@brief comparison operator for JSON types 3015 3016Returns an ordering that is similar to Python: 3017- order: null < boolean < number < object < array < string < binary 3018- furthermore, each type is not smaller than itself 3019- discarded values are not comparable 3020- binary is represented as a b"" string in python and directly comparable to a 3021string; however, making a binary array directly comparable with a string would 3022be surprising behavior in a JSON file. 3023 3024@since version 1.0.0 3025*/ 3026#if JSON_HAS_THREE_WAY_COMPARISON 3027inline std::partial_ordering operator<=>(const value_t lhs ,const value_t rhs )noexcept // *NOPAD* 3028#else 3029inline bool operator< (const value_t lhs ,const value_t rhs )noexcept 3030#endif 3031{ 3032static constexpr std::array < std::uint8_t ,9 > order = {{ 30330 /* null */ ,3 /* object */ ,4 /* array */ ,5 /* string */ , 30341 /* boolean */ ,2 /* integer */ ,2 /* unsigned */ ,2 /* float */ , 30356 /* binary */ 3036 } 3037 }; 3038 3039const auto l_index = static_cast < std::size_t > (lhs ); 3040const auto r_index = static_cast < std::size_t > (rhs ); 3041#if JSON_HAS_THREE_WAY_COMPARISON 3042if (l_index < order .size ()&& r_index < order .size ()) 3043 { 3044return order [l_index ] <=>order [r_index ];// *NOPAD* 3045 } 3046return std::partial_ordering::unordered ; 3047#else 3048return l_index < order .size ()&& r_index < order .size ()&& order [l_index ]< order [r_index ]; 3049#endif 3050} 3051 3052// GCC selects the built-in operator< over an operator rewritten from 3053// a user-defined spaceship operator 3054// Clang, MSVC, and ICC select the rewritten candidate 3055// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) 3056#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__ ) 3057inline bool operator< (const value_t lhs ,const value_t rhs )noexcept 3058{ 3059return std::is_lt (lhs <=>rhs );// *NOPAD* 3060} 3061#endif 3062 3063}// namespace detail 3064NLOHMANN_JSON_NAMESPACE_END 3065 3066// #include <nlohmann/detail/string_escape.hpp> 3067// __ _____ _____ _____ 3068// __| | __| | | | JSON for Modern C++ 3069// | | |__ | | | | | | version 3.12.0 3070// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3071// 3072// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3073// SPDX-License-Identifier: MIT 3074 3075 3076 3077// #include <nlohmann/detail/abi_macros.hpp> 3078 3079 3080NLOHMANN_JSON_NAMESPACE_BEGIN 3081namespace detail 3082{ 3083 3084/*! 3085@brief replace all occurrences of a substring by another string 3086 3087@param[in,out] s the string to manipulate; changed so that all 3088occurrences of @a f are replaced with @a t 3089@param[in] f the substring to replace with @a t 3090@param[in] t the string to replace @a f 3091 3092@pre The search string @a f must not be empty. **This precondition is 3093enforced with an assertion.** 3094 3095@since version 2.0.0 3096*/ 3097template < typename StringType > 3098inline void replace_substring (StringType & s ,const StringType & f , 3099const StringType & t ) 3100{ 3101JSON_ASSERT (!f .empty ()); 3102for (auto pos = s .find (f );// find first occurrence of f 3103pos != StringType ::npos ;// make sure f was found 3104s .replace (pos ,f .size (),t ),// replace with t, and 3105pos = s .find (f ,pos + t .size ()))// find next occurrence of f 3106 {} 3107} 3108 3109/*! 3110* @brief string escaping as described in RFC 6901 (Sect. 4) 3111* @param[in] s string to escape 3112* @return escaped string 3113* 3114* Note the order of escaping "~" to "~0" and "/" to "~1" is important. 3115*/ 3116template < typename StringType > 3117inline StringType escape (StringType s ) 3118{ 3119replace_substring (s ,StringType {"~" },StringType {"~0" }); 3120replace_substring (s ,StringType {"/" },StringType {"~1" }); 3121return s ; 3122} 3123 3124/*! 3125* @brief string unescaping as described in RFC 6901 (Sect. 4) 3126* @param[in] s string to unescape 3127* @return unescaped string 3128* 3129* Note the order of escaping "~1" to "/" and "~0" to "~" is important. 3130*/ 3131template < typename StringType > 3132static void unescape (StringType & s ) 3133{ 3134replace_substring (s ,StringType {"~1" },StringType {"/" }); 3135replace_substring (s ,StringType {"~0" },StringType {"~" }); 3136} 3137 3138}// namespace detail 3139NLOHMANN_JSON_NAMESPACE_END 3140 3141// #include <nlohmann/detail/input/position_t.hpp> 3142// __ _____ _____ _____ 3143// __| | __| | | | JSON for Modern C++ 3144// | | |__ | | | | | | version 3.12.0 3145// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3146// 3147// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3148// SPDX-License-Identifier: MIT 3149 3150 3151 3152#include <cstddef> // size_t 3153 3154// #include <nlohmann/detail/abi_macros.hpp> 3155 3156 3157NLOHMANN_JSON_NAMESPACE_BEGIN 3158namespace detail 3159{ 3160 3161/// struct to capture the start position of the current token 3162struct position_t 3163{ 3164/// the total number of characters read 3165 std::size_t chars_read_total = 0 ; 3166/// the number of characters read in the current line 3167 std::size_t chars_read_current_line = 0 ; 3168/// the number of lines read 3169 std::size_t lines_read = 0 ; 3170 3171/// conversion to size_t to preserve SAX interface 3172constexpr operatorsize_t ()const 3173 { 3174return chars_read_total ; 3175 } 3176}; 3177 3178}// namespace detail 3179NLOHMANN_JSON_NAMESPACE_END 3180 3181// #include <nlohmann/detail/macro_scope.hpp> 3182 3183// #include <nlohmann/detail/meta/cpp_future.hpp> 3184// __ _____ _____ _____ 3185// __| | __| | | | JSON for Modern C++ 3186// | | |__ | | | | | | version 3.12.0 3187// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3188// 3189// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3190// SPDX-FileCopyrightText: 2018 The Abseil Authors 3191// SPDX-License-Identifier: MIT 3192 3193 3194 3195#include <array> // array 3196#include <cstddef> // size_t 3197#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type 3198#include <utility> // index_sequence, make_index_sequence, index_sequence_for 3199 3200// #include <nlohmann/detail/macro_scope.hpp> 3201 3202 3203NLOHMANN_JSON_NAMESPACE_BEGIN 3204namespace detail 3205{ 3206 3207template < typename T > 3208using uncvref_t = typename std::remove_cv < typename std::remove_reference < T > ::type > ::type ; 3209 3210#ifdef JSON_HAS_CPP_14 3211 3212// the following utilities are natively available in C++14 3213using std::enable_if_t ; 3214using std::index_sequence ; 3215using std::make_index_sequence ; 3216using std::index_sequence_for ; 3217 3218#else 3219 3220// alias templates to reduce boilerplate 3221template < bool B ,typename T = void > 3222using enable_if_t = typename std::enable_if < B ,T > ::type ; 3223 3224// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h 3225// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. 3226 3227//// START OF CODE FROM GOOGLE ABSEIL 3228 3229// integer_sequence 3230// 3231// Class template representing a compile-time integer sequence. An instantiation 3232// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its 3233// type through its template arguments (which is a common need when 3234// working with C++11 variadic templates). `absl::integer_sequence` is designed 3235// to be a drop-in replacement for C++14's `std::integer_sequence`. 3236// 3237// Example: 3238// 3239// template< class T, T... Ints > 3240// void user_function(integer_sequence<T, Ints...>); 3241// 3242// int main() 3243// { 3244// // user_function's `T` will be deduced to `int` and `Ints...` 3245// // will be deduced to `0, 1, 2, 3, 4`. 3246// user_function(make_integer_sequence<int, 5>()); 3247// } 3248template < typename T ,T ...Ints > 3249struct integer_sequence 3250{ 3251using value_type = T ; 3252static constexpr std::size_t size ()noexcept 3253 { 3254return sizeof ...(Ints ); 3255 } 3256}; 3257 3258// index_sequence 3259// 3260// A helper template for an `integer_sequence` of `size_t`, 3261// `absl::index_sequence` is designed to be a drop-in replacement for C++14's 3262// `std::index_sequence`. 3263template < size_t ...Ints > 3264using index_sequence = integer_sequence < size_t ,Ints ...> ; 3265 3266namespace utility_internal 3267{ 3268 3269template < typename Seq ,size_t SeqSize ,size_t Rem > 3270struct Extend ; 3271 3272// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. 3273template < typename T ,T ...Ints ,size_t SeqSize > 3274struct Extend < integer_sequence < T ,Ints ...> ,SeqSize ,0 > 3275{ 3276using type = integer_sequence < T ,Ints ..., (Ints + SeqSize )...> ; 3277}; 3278 3279template < typename T ,T ...Ints ,size_t SeqSize > 3280struct Extend < integer_sequence < T ,Ints ...> ,SeqSize ,1 > 3281{ 3282using type = integer_sequence < T ,Ints ..., (Ints + SeqSize )...,2 * SeqSize > ; 3283}; 3284 3285// Recursion helper for 'make_integer_sequence<T, N>'. 3286// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. 3287template < typename T ,size_t N > 3288struct Gen 3289{ 3290using type = 3291typename Extend < typename Gen < T ,N /2 > ::type ,N /2 ,N %2 > ::type ; 3292}; 3293 3294template < typename T > 3295struct Gen < T ,0 > 3296{ 3297using type = integer_sequence < T > ; 3298}; 3299 3300}// namespace utility_internal 3301 3302// Compile-time sequences of integers 3303 3304// make_integer_sequence 3305// 3306// This template alias is equivalent to 3307// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in 3308// replacement for C++14's `std::make_integer_sequence`. 3309template < typename T ,T N > 3310using make_integer_sequence = typename utility_internal::Gen < T ,N > ::type ; 3311 3312// make_index_sequence 3313// 3314// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, 3315// and is designed to be a drop-in replacement for C++14's 3316// `std::make_index_sequence`. 3317template < size_t N > 3318using make_index_sequence = make_integer_sequence < size_t ,N > ; 3319 3320// index_sequence_for 3321// 3322// Converts a typename pack into an index sequence of the same length, and 3323// is designed to be a drop-in replacement for C++14's 3324// `std::index_sequence_for()` 3325template < typename ...Ts > 3326using index_sequence_for = make_index_sequence < sizeof ...(Ts )> ; 3327 3328//// END OF CODE FROM GOOGLE ABSEIL 3329 3330#endif 3331 3332// dispatch utility (taken from ranges-v3) 3333template < unsigned N > struct priority_tag :priority_tag < N - 1 > {}; 3334template <> struct priority_tag < 0 > {}; 3335 3336// taken from ranges-v3 3337template < typename T > 3338struct static_const 3339{ 3340static JSON_INLINE_VARIABLE constexpr T value {}; 3341}; 3342 3343#ifndef JSON_HAS_CPP_17 3344template < typename T > 3345constexpr T static_const < T > ::value ; 3346#endif 3347 3348template < typename T ,typename ...Args > 3349constexpr std::array < T ,sizeof ...(Args )> make_array (Args && ...args ) 3350{ 3351return std::array < T ,sizeof ...(Args )> {{static_cast < T > (std::forward < Args > (args ))...}}; 3352} 3353 3354}// namespace detail 3355NLOHMANN_JSON_NAMESPACE_END 3356 3357// #include <nlohmann/detail/meta/type_traits.hpp> 3358// __ _____ _____ _____ 3359// __| | __| | | | JSON for Modern C++ 3360// | | |__ | | | | | | version 3.12.0 3361// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3362// 3363// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3364// SPDX-License-Identifier: MIT 3365 3366 3367 3368#include <limits> // numeric_limits 3369#include <string> // char_traits 3370#include <tuple> // tuple 3371#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type 3372#include <utility> // declval 3373 3374// #include <nlohmann/detail/iterators/iterator_traits.hpp> 3375// __ _____ _____ _____ 3376// __| | __| | | | JSON for Modern C++ 3377// | | |__ | | | | | | version 3.12.0 3378// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3379// 3380// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3381// SPDX-License-Identifier: MIT 3382 3383 3384 3385#include <iterator> // random_access_iterator_tag 3386 3387// #include <nlohmann/detail/abi_macros.hpp> 3388 3389// #include <nlohmann/detail/meta/void_t.hpp> 3390 3391// #include <nlohmann/detail/meta/cpp_future.hpp> 3392 3393 3394NLOHMANN_JSON_NAMESPACE_BEGIN 3395namespace detail 3396{ 3397 3398template < typename It ,typename = void > 3399struct iterator_types {}; 3400 3401template < typename It > 3402struct iterator_types < 3403It , 3404void_t < typename It ::difference_type ,typename It ::value_type ,typename It ::pointer , 3405typename It ::reference ,typename It ::iterator_category >> 3406{ 3407using difference_type = typename It ::difference_type ; 3408using value_type = typename It ::value_type ; 3409using pointer = typename It ::pointer ; 3410using reference = typename It ::reference ; 3411using iterator_category = typename It ::iterator_category ; 3412}; 3413 3414// This is required as some compilers implement std::iterator_traits in a way that 3415// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. 3416template < typename T ,typename = void > 3417struct iterator_traits 3418{ 3419}; 3420 3421template < typename T > 3422struct iterator_traits < T ,enable_if_t < !std::is_pointer < T > ::value >> 3423 :iterator_types < T > 3424{ 3425}; 3426 3427template < typename T > 3428struct iterator_traits < T * ,enable_if_t < std::is_object < T > ::value >> 3429{ 3430using iterator_category = std::random_access_iterator_tag ; 3431using value_type = T ; 3432using difference_type = ptrdiff_t ; 3433using pointer = T * ; 3434using reference = T & ; 3435}; 3436 3437}// namespace detail 3438NLOHMANN_JSON_NAMESPACE_END 3439 3440// #include <nlohmann/detail/macro_scope.hpp> 3441 3442// #include <nlohmann/detail/meta/call_std/begin.hpp> 3443// __ _____ _____ _____ 3444// __| | __| | | | JSON for Modern C++ 3445// | | |__ | | | | | | version 3.12.0 3446// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3447// 3448// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3449// SPDX-License-Identifier: MIT 3450 3451 3452 3453// #include <nlohmann/detail/macro_scope.hpp> 3454 3455 3456NLOHMANN_JSON_NAMESPACE_BEGIN 3457 3458NLOHMANN_CAN_CALL_STD_FUNC_IMPL (begin ); 3459 3460NLOHMANN_JSON_NAMESPACE_END 3461 3462// #include <nlohmann/detail/meta/call_std/end.hpp> 3463// __ _____ _____ _____ 3464// __| | __| | | | JSON for Modern C++ 3465// | | |__ | | | | | | version 3.12.0 3466// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3467// 3468// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3469// SPDX-License-Identifier: MIT 3470 3471 3472 3473// #include <nlohmann/detail/macro_scope.hpp> 3474 3475 3476NLOHMANN_JSON_NAMESPACE_BEGIN 3477 3478NLOHMANN_CAN_CALL_STD_FUNC_IMPL (end ); 3479 3480NLOHMANN_JSON_NAMESPACE_END 3481 3482// #include <nlohmann/detail/meta/cpp_future.hpp> 3483 3484// #include <nlohmann/detail/meta/detected.hpp> 3485 3486// #include <nlohmann/json_fwd.hpp> 3487// __ _____ _____ _____ 3488// __| | __| | | | JSON for Modern C++ 3489// | | |__ | | | | | | version 3.12.0 3490// |_____|_____|_____|_|___| https://github.com/nlohmann/json 3491// 3492// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 3493// SPDX-License-Identifier: MIT 3494 3495#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3496#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3497 3498#include <cstdint> // int64_t, uint64_t 3499#include <map> // map 3500#include <memory> // allocator 3501#include <string> // string 3502#include <vector> // vector 3503 3504// #include <nlohmann/detail/abi_macros.hpp> 3505 3506 3507/*! 3508@brief namespace for Niels Lohmann 3509@see https://github.com/nlohmann 3510@since version 1.0.0 3511*/ 3512NLOHMANN_JSON_NAMESPACE_BEGIN 3513 3514/*! 3515@brief default JSONSerializer template argument 3516 3517This serializer ignores the template arguments and uses ADL 3518([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) 3519for serialization. 3520*/ 3521template < typename T = void ,typename SFINAE = void > 3522struct adl_serializer ; 3523 3524/// a class to store JSON values 3525/// @sa https://json.nlohmann.me/api/basic_json/ 3526template < template < typename U ,typename V ,typename ...Args > class ObjectType = 3527std ::map , 3528template < typename U ,typename ...Args > class ArrayType = std ::vector , 3529class StringType = std::string ,class BooleanType = bool , 3530class NumberIntegerType = std::int64_t , 3531class NumberUnsignedType = std::uint64_t , 3532class NumberFloatType = double , 3533template < typename U > class AllocatorType = std::allocator , 3534template < typename T ,typename SFINAE = void > class JSONSerializer = 3535adl_serializer , 3536class BinaryType = std ::vector < std::uint8_t > ,// cppcheck-suppress syntaxError 3537class CustomBaseClass = void > 3538class basic_json ; 3539 3540/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 3541/// @sa https://json.nlohmann.me/api/json_pointer/ 3542template < typename RefStringType > 3543class json_pointer ; 3544 3545/*! 3546@brief default specialization 3547@sa https://json.nlohmann.me/api/json/ 3548*/ 3549using json = basic_json <> ; 3550 3551/// @brief a minimal map-like container that preserves insertion order 3552/// @sa https://json.nlohmann.me/api/ordered_map/ 3553template < class Key ,class T ,class IgnoredLess ,class Allocator > 3554struct ordered_map ; 3555 3556/// @brief specialization that maintains the insertion order of object keys 3557/// @sa https://json.nlohmann.me/api/ordered_json/ 3558using ordered_json = basic_json < nlohmann::ordered_map > ; 3559 3560NLOHMANN_JSON_NAMESPACE_END 3561 3562#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3563 3564 3565NLOHMANN_JSON_NAMESPACE_BEGIN 3566/*! 3567@brief detail namespace with internal helper functions 3568 3569This namespace collects functions that should not be exposed, 3570implementations of some @ref basic_json methods, and meta-programming helpers. 3571 3572@since version 2.1.0 3573*/ 3574namespace detail 3575{ 3576 3577///////////// 3578// helpers // 3579///////////// 3580 3581// Note to maintainers: 3582// 3583// Every trait in this file expects a non CV-qualified type. 3584// The only exceptions are in the 'aliases for detected' section 3585// (i.e. those of the form: decltype(T::member_function(std::declval<T>()))) 3586// 3587// In this case, T has to be properly CV-qualified to constraint the function arguments 3588// (e.g. to_json(BasicJsonType&, const T&)) 3589 3590template < typename > struct is_basic_json : std::false_type {}; 3591 3592NLOHMANN_BASIC_JSON_TPL_DECLARATION 3593struct is_basic_json < NLOHMANN_BASIC_JSON_TPL > : std::true_type {}; 3594 3595// used by exceptions create() member functions 3596// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t 3597// false_type otherwise 3598template < typename BasicJsonContext > 3599struct is_basic_json_context : 3600 std::integral_constant < bool , 3601is_basic_json < typename std::remove_cv < typename std::remove_pointer < BasicJsonContext > ::type > ::type > ::value 3602|| std::is_same < BasicJsonContext , std::nullptr_t > ::value > 3603{}; 3604 3605////////////////////// 3606// json_ref helpers // 3607////////////////////// 3608 3609template < typename > 3610class json_ref ; 3611 3612template < typename > 3613struct is_json_ref : std::false_type {}; 3614 3615template < typename T > 3616struct is_json_ref < json_ref < T >> : std::true_type {}; 3617 3618////////////////////////// 3619// aliases for detected // 3620////////////////////////// 3621 3622template < typename T > 3623using mapped_type_t = typename T ::mapped_type ; 3624 3625template < typename T > 3626using key_type_t = typename T ::key_type ; 3627 3628template < typename T > 3629using value_type_t = typename T ::value_type ; 3630 3631template < typename T > 3632using difference_type_t = typename T ::difference_type ; 3633 3634template < typename T > 3635using pointer_t = typename T ::pointer ; 3636 3637template < typename T > 3638using reference_t = typename T ::reference ; 3639 3640template < typename T > 3641using iterator_category_t = typename T ::iterator_category ; 3642 3643template < typename T ,typename ...Args > 3644using to_json_function = decltype(T ::to_json (std::declval < Args > ()...)); 3645 3646template < typename T ,typename ...Args > 3647using from_json_function = decltype(T ::from_json (std::declval < Args > ()...)); 3648 3649template < typename T ,typename U > 3650using get_template_function = decltype(std::declval < T > ().template get < U > ()); 3651 3652// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists 3653template < typename BasicJsonType ,typename T ,typename = void > 3654struct has_from_json : std::false_type {}; 3655 3656// trait checking if j.get<T> is valid 3657// use this trait instead of std::is_constructible or std::is_convertible, 3658// both rely on, or make use of implicit conversions, and thus fail when T 3659// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) 3660template < typename BasicJsonType ,typename T > 3661struct is_getable 3662{ 3663static constexpr bool value = is_detected < get_template_function ,const BasicJsonType & ,T > ::value ; 3664}; 3665 3666template < typename BasicJsonType ,typename T > 3667struct has_from_json < BasicJsonType ,T ,enable_if_t < !is_basic_json < T > ::value >> 3668{ 3669using serializer = typename BasicJsonType ::template json_serializer < T ,void > ; 3670 3671static constexpr bool value = 3672is_detected_exact < void ,from_json_function ,serializer , 3673const BasicJsonType & ,T &> ::value ; 3674}; 3675 3676// This trait checks if JSONSerializer<T>::from_json(json const&) exists 3677// this overload is used for non-default-constructible user-defined-types 3678template < typename BasicJsonType ,typename T ,typename = void > 3679struct has_non_default_from_json : std::false_type {}; 3680 3681template < typename BasicJsonType ,typename T > 3682struct has_non_default_from_json < BasicJsonType ,T ,enable_if_t < !is_basic_json < T > ::value >> 3683{ 3684using serializer = typename BasicJsonType ::template json_serializer < T ,void > ; 3685 3686static constexpr bool value = 3687is_detected_exact < T ,from_json_function ,serializer , 3688const BasicJsonType &> ::value ; 3689}; 3690 3691// This trait checks if BasicJsonType::json_serializer<T>::to_json exists 3692// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. 3693template < typename BasicJsonType ,typename T ,typename = void > 3694struct has_to_json : std::false_type {}; 3695 3696template < typename BasicJsonType ,typename T > 3697struct has_to_json < BasicJsonType ,T ,enable_if_t < !is_basic_json < T > ::value >> 3698{ 3699using serializer = typename BasicJsonType ::template json_serializer < T ,void > ; 3700 3701static constexpr bool value = 3702is_detected_exact < void ,to_json_function ,serializer ,BasicJsonType & , 3703T > ::value ; 3704}; 3705 3706template < typename T > 3707using detect_key_compare = typename T ::key_compare ; 3708 3709template < typename T > 3710struct has_key_compare : std::integral_constant < bool ,is_detected < detect_key_compare ,T > ::value > {}; 3711 3712// obtains the actual object key comparator 3713template < typename BasicJsonType > 3714struct actual_object_comparator 3715{ 3716using object_t = typename BasicJsonType ::object_t ; 3717using object_comparator_t = typename BasicJsonType ::default_object_comparator_t ; 3718using type = typename std::conditional < has_key_compare < object_t > ::value , 3719typename object_t::key_compare ,object_comparator_t > ::type ; 3720}; 3721 3722template < typename BasicJsonType > 3723using actual_object_comparator_t = typename actual_object_comparator < BasicJsonType > ::type ; 3724 3725///////////////// 3726// char_traits // 3727///////////////// 3728 3729// Primary template of char_traits calls std char_traits 3730template < typename T > 3731struct char_traits : std::char_traits < T > 3732{}; 3733 3734// Explicitly define char traits for unsigned char since it is not standard 3735template <> 3736struct char_traits < unsigned char > : std::char_traits < char > 3737{ 3738using char_type = unsigned char ; 3739using int_type = uint64_t ; 3740 3741// Redefine to_int_type function 3742static int_type to_int_type (char_type c )noexcept 3743 { 3744return static_cast < int_type > (c ); 3745 } 3746 3747static char_type to_char_type (int_type i )noexcept 3748 { 3749return static_cast < char_type > (i ); 3750 } 3751 3752static constexpr int_type eof ()noexcept 3753 { 3754return static_cast < int_type > (std::char_traits < char > ::eof ()); 3755 } 3756}; 3757 3758// Explicitly define char traits for signed char since it is not standard 3759template <> 3760struct char_traits < signed char > : std::char_traits < char > 3761{ 3762using char_type = signed char ; 3763using int_type = uint64_t ; 3764 3765// Redefine to_int_type function 3766static int_type to_int_type (char_type c )noexcept 3767 { 3768return static_cast < int_type > (c ); 3769 } 3770 3771static char_type to_char_type (int_type i )noexcept 3772 { 3773return static_cast < char_type > (i ); 3774 } 3775 3776static constexpr int_type eof ()noexcept 3777 { 3778return static_cast < int_type > (std::char_traits < char > ::eof ()); 3779 } 3780}; 3781 3782/////////////////// 3783// is_ functions // 3784/////////////////// 3785 3786// https://en.cppreference.com/w/cpp/types/conjunction 3787template < class ...> struct conjunction : std::true_type { }; 3788template < class B > struct conjunction < B > :B { }; 3789template < class B ,class ...Bn > 3790struct conjunction < B ,Bn ...> 3791: std::conditional < static_cast < bool > (B ::value ),conjunction < Bn ...> ,B > ::type {}; 3792 3793// https://en.cppreference.com/w/cpp/types/negation 3794template < class B > struct negation : std::integral_constant < bool , !B ::value > { }; 3795 3796// Reimplementation of is_constructible and is_default_constructible, due to them being broken for 3797// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). 3798// This causes compile errors in e.g. clang 3.5 or gcc 4.9. 3799template < typename T > 3800struct is_default_constructible : std::is_default_constructible < T > {}; 3801 3802template < typename T1 ,typename T2 > 3803struct is_default_constructible < std::pair < T1 ,T2 >> 3804 :conjunction < is_default_constructible < T1 > ,is_default_constructible < T2 >> {}; 3805 3806template < typename T1 ,typename T2 > 3807struct is_default_constructible < const std::pair < T1 ,T2 >> 3808 :conjunction < is_default_constructible < T1 > ,is_default_constructible < T2 >> {}; 3809 3810template < typename ...Ts > 3811struct is_default_constructible < std::tuple < Ts ...>> 3812 :conjunction < is_default_constructible < Ts > ...> {}; 3813 3814template < typename ...Ts > 3815struct is_default_constructible < const std::tuple < Ts ...>> 3816 :conjunction < is_default_constructible < Ts > ...> {}; 3817 3818template < typename T ,typename ...Args > 3819struct is_constructible : std::is_constructible < T ,Args ...> {}; 3820 3821template < typename T1 ,typename T2 > 3822struct is_constructible < std::pair < T1 ,T2 >> :is_default_constructible < std::pair < T1 ,T2 >> {}; 3823 3824template < typename T1 ,typename T2 > 3825struct is_constructible < const std::pair < T1 ,T2 >> :is_default_constructible < const std::pair < T1 ,T2 >> {}; 3826 3827template < typename ...Ts > 3828struct is_constructible < std::tuple < Ts ...>> :is_default_constructible < std::tuple < Ts ...>> {}; 3829 3830template < typename ...Ts > 3831struct is_constructible < const std::tuple < Ts ...>> :is_default_constructible < const std::tuple < Ts ...>> {}; 3832 3833template < typename T ,typename = void > 3834struct is_iterator_traits : std::false_type {}; 3835 3836template < typename T > 3837struct is_iterator_traits < iterator_traits < T >> 3838{ 3839private : 3840using traits = iterator_traits < T > ; 3841 3842public : 3843static constexpr auto value = 3844is_detected < value_type_t ,traits > ::value && 3845is_detected < difference_type_t ,traits > ::value && 3846is_detected < pointer_t ,traits > ::value && 3847is_detected < iterator_category_t ,traits > ::value && 3848is_detected < reference_t ,traits > ::value ; 3849}; 3850 3851template < typename T > 3852struct is_range 3853{ 3854private : 3855using t_ref = typename std::add_lvalue_reference < T > ::type ; 3856 3857using iterator = detected_t < result_of_begin ,t_ref > ; 3858using sentinel = detected_t < result_of_end ,t_ref > ; 3859 3860// to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator 3861// and https://en.cppreference.com/w/cpp/iterator/sentinel_for 3862// but reimplementing these would be too much work, as a lot of other concepts are used underneath 3863static constexpr auto is_iterator_begin = 3864is_iterator_traits < iterator_traits < iterator >> ::value ; 3865 3866public : 3867static constexpr bool value = !std::is_same < iterator ,nonesuch > ::value && !std::is_same < sentinel ,nonesuch > ::value && is_iterator_begin ; 3868}; 3869 3870template < typename R > 3871using iterator_t = enable_if_t < is_range < R > ::value ,result_of_begin < decltype(std::declval < R &> ())>> ; 3872 3873template < typename T > 3874using range_value_t = value_type_t < iterator_traits < iterator_t < T >>> ; 3875 3876// The following implementation of is_complete_type is taken from 3877// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ 3878// and is written by Xiang Fan who agreed to using it in this library. 3879 3880template < typename T ,typename = void > 3881struct is_complete_type : std::false_type {}; 3882 3883template < typename T > 3884struct is_complete_type < T , decltype(void (sizeof (T )))> : std::true_type {}; 3885 3886template < typename BasicJsonType ,typename CompatibleObjectType , 3887typename = void > 3888struct is_compatible_object_type_impl : std::false_type {}; 3889 3890template < typename BasicJsonType ,typename CompatibleObjectType > 3891struct is_compatible_object_type_impl < 3892BasicJsonType ,CompatibleObjectType , 3893enable_if_t < is_detected < mapped_type_t ,CompatibleObjectType > ::value && 3894is_detected < key_type_t ,CompatibleObjectType > ::value >> 3895{ 3896using object_t = typename BasicJsonType ::object_t ; 3897 3898// macOS's is_constructible does not play well with nonesuch... 3899static constexpr bool value = 3900is_constructible < typename object_t::key_type , 3901typename CompatibleObjectType ::key_type > ::value && 3902is_constructible < typename object_t::mapped_type , 3903typename CompatibleObjectType ::mapped_type > ::value ; 3904}; 3905 3906template < typename BasicJsonType ,typename CompatibleObjectType > 3907struct is_compatible_object_type 3908 :is_compatible_object_type_impl < BasicJsonType ,CompatibleObjectType > {}; 3909 3910template < typename BasicJsonType ,typename ConstructibleObjectType , 3911typename = void > 3912struct is_constructible_object_type_impl : std::false_type {}; 3913 3914template < typename BasicJsonType ,typename ConstructibleObjectType > 3915struct is_constructible_object_type_impl < 3916BasicJsonType ,ConstructibleObjectType , 3917enable_if_t < is_detected < mapped_type_t ,ConstructibleObjectType > ::value && 3918is_detected < key_type_t ,ConstructibleObjectType > ::value >> 3919{ 3920using object_t = typename BasicJsonType ::object_t ; 3921 3922static constexpr bool value = 3923 (is_default_constructible < ConstructibleObjectType > ::value && 3924 (std::is_move_assignable < ConstructibleObjectType > ::value || 3925 std::is_copy_assignable < ConstructibleObjectType > ::value )&& 3926 (is_constructible < typename ConstructibleObjectType ::key_type , 3927typename object_t::key_type > ::value && 3928 std::is_same < 3929typename object_t::mapped_type , 3930typename ConstructibleObjectType ::mapped_type > ::value ))|| 3931 (has_from_json < BasicJsonType , 3932typename ConstructibleObjectType ::mapped_type > ::value || 3933has_non_default_from_json < 3934BasicJsonType , 3935typename ConstructibleObjectType ::mapped_type > ::value ); 3936}; 3937 3938template < typename BasicJsonType ,typename ConstructibleObjectType > 3939struct is_constructible_object_type 3940 :is_constructible_object_type_impl < BasicJsonType , 3941ConstructibleObjectType > {}; 3942 3943template < typename BasicJsonType ,typename CompatibleStringType > 3944struct is_compatible_string_type 3945{ 3946static constexpr auto value = 3947is_constructible < typename BasicJsonType ::string_t ,CompatibleStringType > ::value ; 3948}; 3949 3950template < typename BasicJsonType ,typename ConstructibleStringType > 3951struct is_constructible_string_type 3952{ 3953// launder type through decltype() to fix compilation failure on ICPC 3954#ifdef __INTEL_COMPILER 3955using laundered_type = decltype(std::declval < ConstructibleStringType > ()); 3956#else 3957using laundered_type = ConstructibleStringType ; 3958#endif 3959 3960static constexpr auto value = 3961conjunction < 3962is_constructible < laundered_type ,typename BasicJsonType ::string_t > , 3963is_detected_exact < typename BasicJsonType ::string_t::value_type , 3964value_type_t ,laundered_type >> ::value ; 3965}; 3966 3967template < typename BasicJsonType ,typename CompatibleArrayType ,typename = void > 3968struct is_compatible_array_type_impl : std::false_type {}; 3969 3970template < typename BasicJsonType ,typename CompatibleArrayType > 3971struct is_compatible_array_type_impl < 3972BasicJsonType ,CompatibleArrayType , 3973enable_if_t < 3974is_detected < iterator_t ,CompatibleArrayType > ::value && 3975is_iterator_traits < iterator_traits < detected_t < iterator_t ,CompatibleArrayType >>> ::value && 3976// special case for types like std::filesystem::path whose iterator's value_type are themselves 3977// c.f. https://github.com/nlohmann/json/pull/3073 3978 !std::is_same < CompatibleArrayType ,detected_t < range_value_t ,CompatibleArrayType >> ::value >> 3979{ 3980static constexpr bool value = 3981is_constructible < BasicJsonType , 3982range_value_t < CompatibleArrayType >> ::value ; 3983}; 3984 3985template < typename BasicJsonType ,typename CompatibleArrayType > 3986struct is_compatible_array_type 3987 :is_compatible_array_type_impl < BasicJsonType ,CompatibleArrayType > {}; 3988 3989template < typename BasicJsonType ,typename ConstructibleArrayType ,typename = void > 3990struct is_constructible_array_type_impl : std::false_type {}; 3991 3992template < typename BasicJsonType ,typename ConstructibleArrayType > 3993struct is_constructible_array_type_impl < 3994BasicJsonType ,ConstructibleArrayType , 3995enable_if_t < std::is_same < ConstructibleArrayType , 3996typename BasicJsonType ::value_type > ::value >> 3997 : std::true_type {}; 3998 3999template < typename BasicJsonType ,typename ConstructibleArrayType > 4000struct is_constructible_array_type_impl < 4001BasicJsonType ,ConstructibleArrayType , 4002enable_if_t < !std::is_same < ConstructibleArrayType , 4003typename BasicJsonType ::value_type > ::value && 4004 !is_compatible_string_type < BasicJsonType ,ConstructibleArrayType > ::value && 4005is_default_constructible < ConstructibleArrayType > ::value && 4006(std::is_move_assignable < ConstructibleArrayType > ::value || 4007 std::is_copy_assignable < ConstructibleArrayType > ::value )&& 4008is_detected < iterator_t ,ConstructibleArrayType > ::value && 4009is_iterator_traits < iterator_traits < detected_t < iterator_t ,ConstructibleArrayType >>> ::value && 4010is_detected < range_value_t ,ConstructibleArrayType > ::value && 4011// special case for types like std::filesystem::path whose iterator's value_type are themselves 4012// c.f. https://github.com/nlohmann/json/pull/3073 4013!std::is_same < ConstructibleArrayType ,detected_t < range_value_t ,ConstructibleArrayType >> ::value && 4014is_complete_type < 4015detected_t < range_value_t ,ConstructibleArrayType >> ::value >> 4016{ 4017using value_type = range_value_t < ConstructibleArrayType > ; 4018 4019static constexpr bool value = 4020 std::is_same < value_type , 4021typename BasicJsonType ::array_t::value_type > ::value || 4022has_from_json < BasicJsonType , 4023value_type > ::value || 4024has_non_default_from_json < 4025BasicJsonType , 4026value_type > ::value ; 4027}; 4028 4029template < typename BasicJsonType ,typename ConstructibleArrayType > 4030struct is_constructible_array_type 4031 :is_constructible_array_type_impl < BasicJsonType ,ConstructibleArrayType > {}; 4032 4033template < typename RealIntegerType ,typename CompatibleNumberIntegerType , 4034typename = void > 4035struct is_compatible_integer_type_impl : std::false_type {}; 4036 4037template < typename RealIntegerType ,typename CompatibleNumberIntegerType > 4038struct is_compatible_integer_type_impl < 4039RealIntegerType ,CompatibleNumberIntegerType , 4040enable_if_t < std::is_integral < RealIntegerType > ::value && 4041 std::is_integral < CompatibleNumberIntegerType > ::value && 4042 !std::is_same < bool ,CompatibleNumberIntegerType > ::value >> 4043{ 4044// is there an assert somewhere on overflows? 4045using RealLimits = std::numeric_limits < RealIntegerType > ; 4046using CompatibleLimits = std::numeric_limits < CompatibleNumberIntegerType > ; 4047 4048static constexpr auto value = 4049is_constructible < RealIntegerType , 4050CompatibleNumberIntegerType > ::value && 4051CompatibleLimits ::is_integer && 4052RealLimits ::is_signed == CompatibleLimits ::is_signed ; 4053}; 4054 4055template < typename RealIntegerType ,typename CompatibleNumberIntegerType > 4056struct is_compatible_integer_type 4057 :is_compatible_integer_type_impl < RealIntegerType , 4058CompatibleNumberIntegerType > {}; 4059 4060template < typename BasicJsonType ,typename CompatibleType ,typename = void > 4061struct is_compatible_type_impl : std::false_type {}; 4062 4063template < typename BasicJsonType ,typename CompatibleType > 4064struct is_compatible_type_impl < 4065BasicJsonType ,CompatibleType , 4066enable_if_t < is_complete_type < CompatibleType > ::value >> 4067{ 4068static constexpr bool value = 4069has_to_json < BasicJsonType ,CompatibleType > ::value ; 4070}; 4071 4072template < typename BasicJsonType ,typename CompatibleType > 4073struct is_compatible_type 4074 :is_compatible_type_impl < BasicJsonType ,CompatibleType > {}; 4075 4076template < typename T1 ,typename T2 > 4077struct is_constructible_tuple : std::false_type {}; 4078 4079template < typename T1 ,typename ...Args > 4080struct is_constructible_tuple < T1 , std::tuple < Args ...>> :conjunction < is_constructible < T1 ,Args > ...> {}; 4081 4082template < typename BasicJsonType ,typename T > 4083struct is_json_iterator_of : std::false_type {}; 4084 4085template < typename BasicJsonType > 4086struct is_json_iterator_of < BasicJsonType ,typename BasicJsonType ::iterator > : std::true_type {}; 4087 4088template < typename BasicJsonType > 4089struct is_json_iterator_of < BasicJsonType ,typename BasicJsonType ::const_iterator > : std::true_type 4090{}; 4091 4092// checks if a given type T is a template specialization of Primary 4093template < template < typename ...> class Primary ,typename T > 4094struct is_specialization_of : std::false_type {}; 4095 4096template < template < typename ...> class Primary ,typename ...Args > 4097struct is_specialization_of < Primary ,Primary < Args ...>> : std::true_type {}; 4098 4099template < typename T > 4100using is_json_pointer = is_specialization_of < ::nlohmann::json_pointer ,uncvref_t < T >> ; 4101 4102// checks if A and B are comparable using Compare functor 4103template < typename Compare ,typename A ,typename B ,typename = void > 4104struct is_comparable : std::false_type {}; 4105 4106template < typename Compare ,typename A ,typename B > 4107struct is_comparable < Compare ,A ,B ,void_t < 4108decltype(std::declval < Compare > ()(std::declval < A > (), std::declval < B > ())), 4109decltype(std::declval < Compare > ()(std::declval < B > (), std::declval < A > ())) 4110>> : std::true_type {}; 4111 4112template < typename T > 4113using detect_is_transparent = typename T ::is_transparent ; 4114 4115// type trait to check if KeyType can be used as object key (without a BasicJsonType) 4116// see is_usable_as_basic_json_key_type below 4117template < typename Comparator ,typename ObjectKeyType ,typename KeyTypeCVRef ,bool RequireTransparentComparator = true, 4118bool ExcludeObjectKeyType = RequireTransparentComparator ,typename KeyType = uncvref_t < KeyTypeCVRef >> 4119using is_usable_as_key_type = typename std::conditional < 4120is_comparable < Comparator ,ObjectKeyType ,KeyTypeCVRef > ::value 4121&& !(ExcludeObjectKeyType && std::is_same < KeyType , 4122ObjectKeyType > ::value ) 4123&& (!RequireTransparentComparator 4124|| is_detected < detect_is_transparent ,Comparator > ::value ) 4125&& !is_json_pointer < KeyType > ::value , 4126 std::true_type , 4127 std::false_type > ::type ; 4128 4129// type trait to check if KeyType can be used as object key 4130// true if: 4131// - KeyType is comparable with BasicJsonType::object_t::key_type 4132// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type 4133// - the comparator is transparent or RequireTransparentComparator is false 4134// - KeyType is not a JSON iterator or json_pointer 4135template < typename BasicJsonType ,typename KeyTypeCVRef ,bool RequireTransparentComparator = true, 4136bool ExcludeObjectKeyType = RequireTransparentComparator ,typename KeyType = uncvref_t < KeyTypeCVRef >> 4137using is_usable_as_basic_json_key_type = typename std::conditional < 4138is_usable_as_key_type < typename BasicJsonType ::object_comparator_t , 4139typename BasicJsonType ::object_t::key_type ,KeyTypeCVRef , 4140RequireTransparentComparator ,ExcludeObjectKeyType > ::value 4141&& !is_json_iterator_of < BasicJsonType ,KeyType > ::value , 4142 std::true_type , 4143 std::false_type > ::type ; 4144 4145template < typename ObjectType ,typename KeyType > 4146using detect_erase_with_key_type = decltype(std::declval < ObjectType &> ().erase (std::declval < KeyType > ())); 4147 4148// type trait to check if object_t has an erase() member functions accepting KeyType 4149template < typename BasicJsonType ,typename KeyType > 4150using has_erase_with_key_type = typename std::conditional < 4151is_detected < 4152detect_erase_with_key_type , 4153typename BasicJsonType ::object_t ,KeyType > ::value , 4154 std::true_type , 4155 std::false_type > ::type ; 4156 4157// a naive helper to check if a type is an ordered_map (exploits the fact that 4158// ordered_map inherits capacity() from std::vector) 4159template < typename T > 4160struct is_ordered_map 4161{ 4162using one = char ; 4163 4164struct two 4165 { 4166char x [2 ];// NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4167 }; 4168 4169template < typename C > static one test ( decltype(& C ::capacity ) ) ; 4170template < typename C > static two test (...); 4171 4172enum {value = sizeof (test < T > (nullptr ))== sizeof (char ) };// NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 4173}; 4174 4175// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) 4176template < typename T ,typename U ,enable_if_t < !std::is_same < T ,U > ::value ,int > = 0 > 4177T conditional_static_cast (U value ) 4178{ 4179return static_cast < T > (value ); 4180} 4181 4182template < typename T ,typename U ,enable_if_t < std::is_same < T ,U > ::value ,int > = 0 > 4183T conditional_static_cast (U value ) 4184{ 4185return value ; 4186} 4187 4188template < typename ...Types > 4189using all_integral = conjunction < std::is_integral < Types > ...> ; 4190 4191template < typename ...Types > 4192using all_signed = conjunction < std::is_signed < Types > ...> ; 4193 4194template < typename ...Types > 4195using all_unsigned = conjunction < std::is_unsigned < Types > ...> ; 4196 4197// there's a disjunction trait in another PR; replace when merged 4198template < typename ...Types > 4199using same_sign = std::integral_constant < bool , 4200all_signed < Types ...> ::value || all_unsigned < Types ...> ::value > ; 4201 4202template < typename OfType ,typename T > 4203using never_out_of_range = std::integral_constant < bool , 4204 (std::is_signed < OfType > ::value && (sizeof (T )< sizeof (OfType ))) 4205|| (same_sign < OfType ,T > ::value && sizeof (OfType )== sizeof (T ))> ; 4206 4207template < typename OfType ,typename T , 4208bool OfTypeSigned = std::is_signed < OfType > ::value , 4209bool TSigned = std::is_signed < T > ::value > 4210struct value_in_range_of_impl2 ; 4211 4212template < typename OfType ,typename T > 4213struct value_in_range_of_impl2 < OfType ,T , false, false> 4214{ 4215static constexpr bool test (T val ) 4216 { 4217using CommonType = typename std::common_type < OfType ,T > ::type ; 4218return static_cast < CommonType > (val ) <=static_cast < CommonType > ((std::numeric_limits < OfType > ::max )()); 4219 } 4220}; 4221 4222template < typename OfType ,typename T > 4223struct value_in_range_of_impl2 < OfType ,T , true, false> 4224{ 4225static constexpr bool test (T val ) 4226 { 4227using CommonType = typename std::common_type < OfType ,T > ::type ; 4228return static_cast < CommonType > (val ) <=static_cast < CommonType > ((std::numeric_limits < OfType > ::max )()); 4229 } 4230}; 4231 4232template < typename OfType ,typename T > 4233struct value_in_range_of_impl2 < OfType ,T , false, true> 4234{ 4235static constexpr bool test (T val ) 4236 { 4237using CommonType = typename std::common_type < OfType ,T > ::type ; 4238return val >=0 && static_cast < CommonType > (val ) <=static_cast < CommonType > ((std::numeric_limits < OfType > ::max )()); 4239 } 4240}; 4241 4242template < typename OfType ,typename T > 4243struct value_in_range_of_impl2 < OfType ,T , true, true> 4244{ 4245static constexpr bool test (T val ) 4246 { 4247using CommonType = typename std::common_type < OfType ,T > ::type ; 4248return static_cast < CommonType > (val ) >=static_cast < CommonType > ((std::numeric_limits < OfType > ::min )()) 4249&& static_cast < CommonType > (val ) <=static_cast < CommonType > ((std::numeric_limits < OfType > ::max )()); 4250 } 4251}; 4252 4253template < typename OfType ,typename T , 4254bool NeverOutOfRange = never_out_of_range < OfType ,T > ::value , 4255typename = detail::enable_if_t < all_integral < OfType ,T > ::value >> 4256struct value_in_range_of_impl1 ; 4257 4258template < typename OfType ,typename T > 4259struct value_in_range_of_impl1 < OfType ,T , false> 4260{ 4261static constexpr bool test (T val ) 4262 { 4263return value_in_range_of_impl2 < OfType ,T > ::test (val ); 4264 } 4265}; 4266 4267template < typename OfType ,typename T > 4268struct value_in_range_of_impl1 < OfType ,T , true> 4269{ 4270static constexpr bool test (T /*val*/ ) 4271 { 4272return true; 4273 } 4274}; 4275 4276template < typename OfType ,typename T > 4277constexpr bool value_in_range_of (T val ) 4278{ 4279return value_in_range_of_impl1 < OfType ,T > ::test (val ); 4280} 4281 4282template < bool Value > 4283using bool_constant = std::integral_constant < bool ,Value > ; 4284 4285/////////////////////////////////////////////////////////////////////////////// 4286// is_c_string 4287/////////////////////////////////////////////////////////////////////////////// 4288 4289namespace impl 4290{ 4291 4292template < typename T > 4293constexpr bool is_c_string () 4294{ 4295using TUnExt = typename std::remove_extent < T > ::type ; 4296using TUnCVExt = typename std::remove_cv < TUnExt > ::type ; 4297using TUnPtr = typename std::remove_pointer < T > ::type ; 4298using TUnCVPtr = typename std::remove_cv < TUnPtr > ::type ; 4299return 4300 (std::is_array < T > ::value && std::is_same < TUnCVExt ,char > ::value ) 4301|| (std::is_pointer < T > ::value && std::is_same < TUnCVPtr ,char > ::value ); 4302} 4303 4304}// namespace impl 4305 4306// checks whether T is a [cv] char */[cv] char[] C string 4307template < typename T > 4308struct is_c_string :bool_constant < impl::is_c_string < T > ()> {}; 4309 4310template < typename T > 4311using is_c_string_uncvref = is_c_string < uncvref_t < T >> ; 4312 4313/////////////////////////////////////////////////////////////////////////////// 4314// is_transparent 4315/////////////////////////////////////////////////////////////////////////////// 4316 4317namespace impl 4318{ 4319 4320template < typename T > 4321constexpr bool is_transparent () 4322{ 4323return is_detected < detect_is_transparent ,T > ::value ; 4324} 4325 4326}// namespace impl 4327 4328// checks whether T has a member named is_transparent 4329template < typename T > 4330struct is_transparent :bool_constant < impl::is_transparent < T > ()> {}; 4331 4332/////////////////////////////////////////////////////////////////////////////// 4333 4334}// namespace detail 4335NLOHMANN_JSON_NAMESPACE_END 4336 4337// #include <nlohmann/detail/string_concat.hpp> 4338// __ _____ _____ _____ 4339// __| | __| | | | JSON for Modern C++ 4340// | | |__ | | | | | | version 3.12.0 4341// |_____|_____|_____|_|___| https://github.com/nlohmann/json 4342// 4343// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 4344// SPDX-License-Identifier: MIT 4345 4346 4347 4348#include <cstring> // strlen 4349#include <string> // string 4350#include <utility> // forward 4351 4352// #include <nlohmann/detail/meta/cpp_future.hpp> 4353 4354// #include <nlohmann/detail/meta/detected.hpp> 4355 4356 4357NLOHMANN_JSON_NAMESPACE_BEGIN 4358namespace detail 4359{ 4360 4361inline std::size_t concat_length () 4362{ 4363return 0 ; 4364} 4365 4366template < typename ...Args > 4367inline std::size_t concat_length (const char * cstr ,const Args & ...rest ); 4368 4369template < typename StringType ,typename ...Args > 4370inline std::size_t concat_length (const StringType & str ,const Args & ...rest ); 4371 4372template < typename ...Args > 4373inline std::size_t concat_length (const char /*c*/ ,const Args & ...rest ) 4374{ 4375return 1 + concat_length (rest ...); 4376} 4377 4378template < typename ...Args > 4379inline std::size_t concat_length (const char * cstr ,const Args & ...rest ) 4380{ 4381// cppcheck-suppress ignoredReturnValue 4382return ::strlen (cstr )+ concat_length (rest ...); 4383} 4384 4385template < typename StringType ,typename ...Args > 4386inline std::size_t concat_length (const StringType & str ,const Args & ...rest ) 4387{ 4388return str .size ()+ concat_length (rest ...); 4389} 4390 4391template < typename OutStringType > 4392inline void concat_into (OutStringType & /*out*/ ) 4393{} 4394 4395template < typename StringType ,typename Arg > 4396using string_can_append = decltype(std::declval < StringType &> ().append (std::declval < Arg && > ())); 4397 4398template < typename StringType ,typename Arg > 4399using detect_string_can_append = is_detected < string_can_append ,StringType ,Arg > ; 4400 4401template < typename StringType ,typename Arg > 4402using string_can_append_op = decltype(std::declval < StringType &> ()+= std::declval < Arg && > ()); 4403 4404template < typename StringType ,typename Arg > 4405using detect_string_can_append_op = is_detected < string_can_append_op ,StringType ,Arg > ; 4406 4407template < typename StringType ,typename Arg > 4408using string_can_append_iter = decltype(std::declval < StringType &> ().append (std::declval < const Arg &> ().begin (), std::declval < const Arg &> ().end ())); 4409 4410template < typename StringType ,typename Arg > 4411using detect_string_can_append_iter = is_detected < string_can_append_iter ,StringType ,Arg > ; 4412 4413template < typename StringType ,typename Arg > 4414using string_can_append_data = decltype(std::declval < StringType &> ().append (std::declval < const Arg &> ().data (), std::declval < const Arg &> ().size ())); 4415 4416template < typename StringType ,typename Arg > 4417using detect_string_can_append_data = is_detected < string_can_append_data ,StringType ,Arg > ; 4418 4419template < typename OutStringType ,typename Arg ,typename ...Args , 4420enable_if_t < !detect_string_can_append < OutStringType ,Arg > ::value 4421&& detect_string_can_append_op < OutStringType ,Arg > ::value ,int > = 0 > 4422inline void concat_into (OutStringType & out ,Arg && arg ,Args && ...rest ); 4423 4424template < typename OutStringType ,typename Arg ,typename ...Args , 4425enable_if_t < !detect_string_can_append < OutStringType ,Arg > ::value 4426&& !detect_string_can_append_op < OutStringType ,Arg > ::value 4427&& detect_string_can_append_iter < OutStringType ,Arg > ::value ,int > = 0 > 4428inline void concat_into (OutStringType & out ,const Arg & arg ,Args && ...rest ); 4429 4430template < typename OutStringType ,typename Arg ,typename ...Args , 4431enable_if_t < !detect_string_can_append < OutStringType ,Arg > ::value 4432&& !detect_string_can_append_op < OutStringType ,Arg > ::value 4433&& !detect_string_can_append_iter < OutStringType ,Arg > ::value 4434&& detect_string_can_append_data < OutStringType ,Arg > ::value ,int > = 0 > 4435inline void concat_into (OutStringType & out ,const Arg & arg ,Args && ...rest ); 4436 4437template < typename OutStringType ,typename Arg ,typename ...Args , 4438enable_if_t < detect_string_can_append < OutStringType ,Arg > ::value ,int > = 0 > 4439inline void concat_into (OutStringType & out ,Arg && arg ,Args && ...rest ) 4440{ 4441out .append (std::forward < Arg > (arg )); 4442concat_into (out , std::forward < Args > (rest )...); 4443} 4444 4445template < typename OutStringType ,typename Arg ,typename ...Args , 4446enable_if_t < !detect_string_can_append < OutStringType ,Arg > ::value 4447&& detect_string_can_append_op < OutStringType ,Arg > ::value ,int > > 4448inline void concat_into (OutStringType & out ,Arg && arg ,Args && ...rest ) 4449{ 4450out += std::forward < Arg > (arg ); 4451concat_into (out , std::forward < Args > (rest )...); 4452} 4453 4454template < typename OutStringType ,typename Arg ,typename ...Args , 4455enable_if_t < !detect_string_can_append < OutStringType ,Arg > ::value 4456&& !detect_string_can_append_op < OutStringType ,Arg > ::value 4457&& detect_string_can_append_iter < OutStringType ,Arg > ::value ,int > > 4458inline void concat_into (OutStringType & out ,const Arg & arg ,Args && ...rest ) 4459{ 4460out .append (arg .begin (),arg .end ()); 4461concat_into (out , std::forward < Args > (rest )...); 4462} 4463 4464template < typename OutStringType ,typename Arg ,typename ...Args , 4465enable_if_t < !detect_string_can_append < OutStringType ,Arg > ::value 4466&& !detect_string_can_append_op < OutStringType ,Arg > ::value 4467&& !detect_string_can_append_iter < OutStringType ,Arg > ::value 4468&& detect_string_can_append_data < OutStringType ,Arg > ::value ,int > > 4469inline void concat_into (OutStringType & out ,const Arg & arg ,Args && ...rest ) 4470{ 4471out .append (arg .data (),arg .size ()); 4472concat_into (out , std::forward < Args > (rest )...); 4473} 4474 4475template < typename OutStringType = std::string ,typename ...Args > 4476inline OutStringType concat (Args && ...args ) 4477{ 4478OutStringType str ; 4479str .reserve (concat_length (args ...)); 4480concat_into (str , std::forward < Args > (args )...); 4481return str ; 4482} 4483 4484}// namespace detail 4485NLOHMANN_JSON_NAMESPACE_END 4486 4487 4488// With -Wweak-vtables, Clang will complain about the exception classes as they 4489// have no out-of-line virtual method definitions and their vtable will be 4490// emitted in every translation unit. This issue cannot be fixed with a 4491// header-only library as there is no implementation file to move these 4492// functions to. As a result, we suppress this warning here to avoid client 4493// code to stumble over this. See https://github.com/nlohmann/json/issues/4087 4494// for a discussion. 4495#if defined(__clang__ ) 4496#pragma clang diagnostic push 4497#pragma clang diagnostic ignored "-Wweak-vtables" 4498#endif 4499 4500NLOHMANN_JSON_NAMESPACE_BEGIN 4501namespace detail 4502{ 4503 4504//////////////// 4505// exceptions // 4506//////////////// 4507 4508/// @brief general exception of the @ref basic_json class 4509/// @sa https://json.nlohmann.me/api/basic_json/exception/ 4510class exception :public std::exception 4511{ 4512public : 4513/// returns the explanatory string 4514const char * what ()const noexcept override 4515 { 4516return m .what (); 4517 } 4518 4519/// the id of the exception 4520const int id ;// NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) 4521 4522protected : 4523JSON_HEDLEY_NON_NULL (3 ) 4524exception (int id_ ,const char * what_arg ) :id (id_ ),m (what_arg ) {}// NOLINT(bugprone-throw-keyword-missing) 4525 4526static std::string name (const std::string & ename ,int id_ ) 4527 { 4528return concat ("[json.exception." ,ename ,'.' , std::to_string (id_ ),"] " ); 4529 } 4530 4531static std::string diagnostics (std::nullptr_t /*leaf_element*/ ) 4532 { 4533return "" ; 4534 } 4535 4536template < typename BasicJsonType > 4537static std::string diagnostics (const BasicJsonType * leaf_element ) 4538 { 4539#if JSON_DIAGNOSTICS 4540 std::vector < std::string > tokens ; 4541for (const auto * current = leaf_element ;current != nullptr && current -> m_parent != nullptr ;current = current -> m_parent ) 4542 { 4543switch (current -> m_parent -> type ()) 4544 { 4545case value_t::array : 4546 { 4547for (std::size_t i = 0 ;i < current -> m_parent -> m_data .m_value .array -> size ();++ i ) 4548 { 4549if (& current -> m_parent -> m_data .m_value .array -> operator[](i )== current ) 4550 { 4551tokens .emplace_back (std::to_string (i )); 4552break ; 4553 } 4554 } 4555break ; 4556 } 4557 4558case value_t::object : 4559 { 4560for (const auto & element :* current -> m_parent -> m_data .m_value .object ) 4561 { 4562if (& element .second == current ) 4563 { 4564tokens .emplace_back (element .first .c_str ()); 4565break ; 4566 } 4567 } 4568break ; 4569 } 4570 4571case value_t::null :// LCOV_EXCL_LINE 4572case value_t::string :// LCOV_EXCL_LINE 4573case value_t::boolean :// LCOV_EXCL_LINE 4574case value_t::number_integer :// LCOV_EXCL_LINE 4575case value_t::number_unsigned :// LCOV_EXCL_LINE 4576case value_t::number_float :// LCOV_EXCL_LINE 4577case value_t::binary :// LCOV_EXCL_LINE 4578case value_t::discarded :// LCOV_EXCL_LINE 4579default :// LCOV_EXCL_LINE 4580break ;// LCOV_EXCL_LINE 4581 } 4582 } 4583 4584if (tokens .empty ()) 4585 { 4586return "" ; 4587 } 4588 4589auto str = std::accumulate (tokens .rbegin (),tokens .rend (), std::string {}, 4590 [](const std::string & a ,const std::string & b ) 4591 { 4592return concat (a ,'/' , detail::escape (b )); 4593 }); 4594 4595return concat ('(' ,str ,") " ,get_byte_positions (leaf_element )); 4596#else 4597return get_byte_positions (leaf_element ); 4598#endif 4599 } 4600 4601private : 4602/// an exception object as storage for error messages 4603 std::runtime_error m ; 4604#if JSON_DIAGNOSTIC_POSITIONS 4605template < typename BasicJsonType > 4606static std::string get_byte_positions (const BasicJsonType * leaf_element ) 4607 { 4608if ((leaf_element -> start_pos ()!= std::string::npos )&& (leaf_element -> end_pos ()!= std::string::npos )) 4609 { 4610return concat ("(bytes " , std::to_string (leaf_element -> start_pos ()),"-" , std::to_string (leaf_element -> end_pos ()),") " ); 4611 } 4612return "" ; 4613 } 4614#else 4615template < typename BasicJsonType > 4616static std::string get_byte_positions (const BasicJsonType * leaf_element ) 4617 { 4618static_cast < void > (leaf_element ); 4619return "" ; 4620 } 4621#endif 4622}; 4623 4624/// @brief exception indicating a parse error 4625/// @sa https://json.nlohmann.me/api/basic_json/parse_error/ 4626class parse_error :public exception 4627{ 4628public : 4629/*! 4630@brief create a parse error exception 4631@param[in] id_ the id of the exception 4632@param[in] pos the position where the error occurred (or with 4633chars_read_total=0 if the position cannot be 4634determined) 4635@param[in] what_arg the explanatory string 4636@return parse_error object 4637*/ 4638template < typename BasicJsonContext ,enable_if_t < is_basic_json_context < BasicJsonContext > ::value ,int > = 0 > 4639static parse_error create (int id_ ,const position_t & pos ,const std::string & what_arg ,BasicJsonContext context ) 4640 { 4641const std::string w = concat (exception::name ("parse_error" ,id_ ),"parse error" , 4642position_string (pos ),": " , exception::diagnostics (context ),what_arg ); 4643return {id_ ,pos .chars_read_total ,w .c_str ()}; 4644 } 4645 4646template < typename BasicJsonContext ,enable_if_t < is_basic_json_context < BasicJsonContext > ::value ,int > = 0 > 4647static parse_error create (int id_ , std::size_t byte_ ,const std::string & what_arg ,BasicJsonContext context ) 4648 { 4649const std::string w = concat (exception::name ("parse_error" ,id_ ),"parse error" , 4650 (byte_ != 0 ? (concat (" at byte " , std::to_string (byte_ ))) :"" ), 4651": " , exception::diagnostics (context ),what_arg ); 4652return {id_ ,byte_ ,w .c_str ()}; 4653 } 4654 4655/*! 4656@brief byte index of the parse error 4657 4658The byte index of the last read character in the input file. 4659 4660@note For an input with n bytes, 1 is the index of the first character and 4661n+1 is the index of the terminating null byte or the end of file. 4662This also holds true when reading a byte vector (CBOR or MessagePack). 4663*/ 4664const std::size_t byte ; 4665 4666private : 4667parse_error (int id_ , std::size_t byte_ ,const char * what_arg ) 4668 :exception (id_ ,what_arg ),byte (byte_ ) {} 4669 4670static std::string position_string (const position_t & pos ) 4671 { 4672return concat (" at line " , std::to_string (pos .lines_read + 1 ), 4673", column " , std::to_string (pos .chars_read_current_line )); 4674 } 4675}; 4676 4677/// @brief exception indicating errors with iterators 4678/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ 4679class invalid_iterator :public exception 4680{ 4681public : 4682template < typename BasicJsonContext ,enable_if_t < is_basic_json_context < BasicJsonContext > ::value ,int > = 0 > 4683static invalid_iterator create (int id_ ,const std::string & what_arg ,BasicJsonContext context ) 4684 { 4685const std::string w = concat (exception::name ("invalid_iterator" ,id_ ), exception::diagnostics (context ),what_arg ); 4686return {id_ ,w .c_str ()}; 4687 } 4688 4689private : 4690JSON_HEDLEY_NON_NULL (3 ) 4691invalid_iterator (int id_ ,const char * what_arg ) 4692 :exception (id_ ,what_arg ) {} 4693}; 4694 4695/// @brief exception indicating executing a member function with a wrong type 4696/// @sa https://json.nlohmann.me/api/basic_json/type_error/ 4697class type_error :public exception 4698{ 4699public : 4700template < typename BasicJsonContext ,enable_if_t < is_basic_json_context < BasicJsonContext > ::value ,int > = 0 > 4701static type_error create (int id_ ,const std::string & what_arg ,BasicJsonContext context ) 4702 { 4703const std::string w = concat (exception::name ("type_error" ,id_ ), exception::diagnostics (context ),what_arg ); 4704return {id_ ,w .c_str ()}; 4705 } 4706 4707private : 4708JSON_HEDLEY_NON_NULL (3 ) 4709type_error (int id_ ,const char * what_arg ) :exception (id_ ,what_arg ) {} 4710}; 4711 4712/// @brief exception indicating access out of the defined range 4713/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ 4714class out_of_range :public exception 4715{ 4716public : 4717template < typename BasicJsonContext ,enable_if_t < is_basic_json_context < BasicJsonContext > ::value ,int > = 0 > 4718static out_of_range create (int id_ ,const std::string & what_arg ,BasicJsonContext context ) 4719 { 4720const std::string w = concat (exception::name ("out_of_range" ,id_ ), exception::diagnostics (context ),what_arg ); 4721return {id_ ,w .c_str ()}; 4722 } 4723 4724private : 4725JSON_HEDLEY_NON_NULL (3 ) 4726out_of_range (int id_ ,const char * what_arg ) :exception (id_ ,what_arg ) {} 4727}; 4728 4729/// @brief exception indicating other library errors 4730/// @sa https://json.nlohmann.me/api/basic_json/other_error/ 4731class other_error :public exception 4732{ 4733public : 4734template < typename BasicJsonContext ,enable_if_t < is_basic_json_context < BasicJsonContext > ::value ,int > = 0 > 4735static other_error create (int id_ ,const std::string & what_arg ,BasicJsonContext context ) 4736 { 4737const std::string w = concat (exception::name ("other_error" ,id_ ), exception::diagnostics (context ),what_arg ); 4738return {id_ ,w .c_str ()}; 4739 } 4740 4741private : 4742JSON_HEDLEY_NON_NULL (3 ) 4743other_error (int id_ ,const char * what_arg ) :exception (id_ ,what_arg ) {} 4744}; 4745 4746}// namespace detail 4747NLOHMANN_JSON_NAMESPACE_END 4748 4749#if defined(__clang__ ) 4750#pragma clang diagnostic pop 4751#endif 4752 4753// #include <nlohmann/detail/macro_scope.hpp> 4754 4755// #include <nlohmann/detail/meta/cpp_future.hpp> 4756 4757// #include <nlohmann/detail/meta/identity_tag.hpp> 4758// __ _____ _____ _____ 4759// __| | __| | | | JSON for Modern C++ 4760// | | |__ | | | | | | version 3.12.0 4761// |_____|_____|_____|_|___| https://github.com/nlohmann/json 4762// 4763// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 4764// SPDX-License-Identifier: MIT 4765 4766 4767 4768// #include <nlohmann/detail/abi_macros.hpp> 4769 4770 4771NLOHMANN_JSON_NAMESPACE_BEGIN 4772namespace detail 4773{ 4774 4775// dispatching helper struct 4776template < class T > struct identity_tag {}; 4777 4778}// namespace detail 4779NLOHMANN_JSON_NAMESPACE_END 4780 4781// #include <nlohmann/detail/meta/std_fs.hpp> 4782// __ _____ _____ _____ 4783// __| | __| | | | JSON for Modern C++ 4784// | | |__ | | | | | | version 3.12.0 4785// |_____|_____|_____|_|___| https://github.com/nlohmann/json 4786// 4787// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 4788// SPDX-License-Identifier: MIT 4789 4790 4791 4792// #include <nlohmann/detail/macro_scope.hpp> 4793 4794 4795#if JSON_HAS_EXPERIMENTAL_FILESYSTEM 4796#include <experimental/filesystem> 4797NLOHMANN_JSON_NAMESPACE_BEGIN 4798namespace detail 4799{ 4800namespace std_fs= std::experimental::filesystem; 4801}// namespace detail 4802NLOHMANN_JSON_NAMESPACE_END 4803#elif JSON_HAS_FILESYSTEM 4804#include <filesystem> // NOLINT(build/c++17) 4805NLOHMANN_JSON_NAMESPACE_BEGIN 4806namespace detail 4807{ 4808namespace std_fs= std::filesystem; 4809}// namespace detail 4810NLOHMANN_JSON_NAMESPACE_END 4811#endif 4812 4813// #include <nlohmann/detail/meta/type_traits.hpp> 4814 4815// #include <nlohmann/detail/string_concat.hpp> 4816 4817// #include <nlohmann/detail/value_t.hpp> 4818 4819 4820NLOHMANN_JSON_NAMESPACE_BEGIN 4821namespace detail 4822{ 4823 4824template < typename BasicJsonType > 4825inline void from_json (const BasicJsonType & j ,typename std::nullptr_t & n ) 4826{ 4827if (JSON_HEDLEY_UNLIKELY (!j .is_null ())) 4828 { 4829JSON_THROW (type_error::create (302 ,concat ("type must be null, but is " ,j .type_name ()),& j )); 4830 } 4831n = nullptr ; 4832} 4833 4834#ifdef JSON_HAS_CPP_17 4835#ifndef JSON_USE_IMPLICIT_CONVERSIONS 4836template < typename BasicJsonType ,typename T > 4837void from_json (const BasicJsonType & j , std::optional < T >& opt ) 4838{ 4839if (j .is_null ()) 4840 { 4841opt = std::nullopt ; 4842 } 4843else 4844 { 4845opt .emplace (j .template get < T > ()); 4846 } 4847} 4848 4849#endif // JSON_USE_IMPLICIT_CONVERSIONS 4850#endif // JSON_HAS_CPP_17 4851 4852// overloads for basic_json template parameters 4853template < typename BasicJsonType ,typename ArithmeticType , 4854enable_if_t < std::is_arithmetic < ArithmeticType > ::value && 4855 !std::is_same < ArithmeticType ,typename BasicJsonType ::boolean_t > ::value , 4856int > = 0 > 4857void get_arithmetic_value (const BasicJsonType & j ,ArithmeticType & val ) 4858{ 4859switch (static_cast < value_t > (j )) 4860 { 4861case value_t::number_unsigned : 4862 { 4863val = static_cast < ArithmeticType > (* j .template get_ptr < const typename BasicJsonType ::number_unsigned_t *> ()); 4864break ; 4865 } 4866case value_t::number_integer : 4867 { 4868val = static_cast < ArithmeticType > (* j .template get_ptr < const typename BasicJsonType ::number_integer_t *> ()); 4869break ; 4870 } 4871case value_t::number_float : 4872 { 4873val = static_cast < ArithmeticType > (* j .template get_ptr < const typename BasicJsonType ::number_float_t *> ()); 4874break ; 4875 } 4876 4877case value_t::null : 4878case value_t::object : 4879case value_t::array : 4880case value_t::string : 4881case value_t::boolean : 4882case value_t::binary : 4883case value_t::discarded : 4884default : 4885JSON_THROW (type_error::create (302 ,concat ("type must be number, but is " ,j .type_name ()),& j )); 4886 } 4887} 4888 4889template < typename BasicJsonType > 4890inline void from_json (const BasicJsonType & j ,typename BasicJsonType ::boolean_t & b ) 4891{ 4892if (JSON_HEDLEY_UNLIKELY (!j .is_boolean ())) 4893 { 4894JSON_THROW (type_error::create (302 ,concat ("type must be boolean, but is " ,j .type_name ()),& j )); 4895 } 4896b = * j .template get_ptr < const typename BasicJsonType ::boolean_t *> (); 4897} 4898 4899template < typename BasicJsonType > 4900inline void from_json (const BasicJsonType & j ,typename BasicJsonType ::string_t & s ) 4901{ 4902if (JSON_HEDLEY_UNLIKELY (!j .is_string ())) 4903 { 4904JSON_THROW (type_error::create (302 ,concat ("type must be string, but is " ,j .type_name ()),& j )); 4905 } 4906s = * j .template get_ptr < const typename BasicJsonType ::string_t *> (); 4907} 4908 4909template < 4910typename BasicJsonType ,typename StringType , 4911enable_if_t < 4912 std::is_assignable < StringType & ,const typename BasicJsonType ::string_t > ::value 4913&& is_detected_exact < typename BasicJsonType ::string_t::value_type ,value_type_t ,StringType > ::value 4914&& !std::is_same < typename BasicJsonType ::string_t ,StringType > ::value 4915&& !is_json_ref < StringType > ::value ,int > = 0 > 4916inline void from_json (const BasicJsonType & j ,StringType & s ) 4917{ 4918if (JSON_HEDLEY_UNLIKELY (!j .is_string ())) 4919 { 4920JSON_THROW (type_error::create (302 ,concat ("type must be string, but is " ,j .type_name ()),& j )); 4921 } 4922 4923s = * j .template get_ptr < const typename BasicJsonType ::string_t *> (); 4924} 4925 4926template < typename BasicJsonType > 4927inline void from_json (const BasicJsonType & j ,typename BasicJsonType ::number_float_t & val ) 4928{ 4929get_arithmetic_value (j ,val ); 4930} 4931 4932template < typename BasicJsonType > 4933inline void from_json (const BasicJsonType & j ,typename BasicJsonType ::number_unsigned_t & val ) 4934{ 4935get_arithmetic_value (j ,val ); 4936} 4937 4938template < typename BasicJsonType > 4939inline void from_json (const BasicJsonType & j ,typename BasicJsonType ::number_integer_t & val ) 4940{ 4941get_arithmetic_value (j ,val ); 4942} 4943 4944#if !JSON_DISABLE_ENUM_SERIALIZATION 4945template < typename BasicJsonType ,typename EnumType , 4946enable_if_t < std::is_enum < EnumType > ::value ,int > = 0 > 4947inline void from_json (const BasicJsonType & j ,EnumType & e ) 4948{ 4949typename std::underlying_type < EnumType > ::type val ; 4950get_arithmetic_value (j ,val ); 4951e = static_cast < EnumType > (val ); 4952} 4953#endif // JSON_DISABLE_ENUM_SERIALIZATION 4954 4955// forward_list doesn't have an insert method 4956template < typename BasicJsonType ,typename T ,typename Allocator , 4957enable_if_t < is_getable < BasicJsonType ,T > ::value ,int > = 0 > 4958inline void from_json (const BasicJsonType & j , std::forward_list < T ,Allocator >& l ) 4959{ 4960if (JSON_HEDLEY_UNLIKELY (!j .is_array ())) 4961 { 4962JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,j .type_name ()),& j )); 4963 } 4964l .clear (); 4965 std::transform (j .rbegin (),j .rend (), 4966 std::front_inserter (l ), [](const BasicJsonType & i ) 4967 { 4968return i .template get < T > (); 4969 }); 4970} 4971 4972// valarray doesn't have an insert method 4973template < typename BasicJsonType ,typename T , 4974enable_if_t < is_getable < BasicJsonType ,T > ::value ,int > = 0 > 4975inline void from_json (const BasicJsonType & j , std::valarray < T >& l ) 4976{ 4977if (JSON_HEDLEY_UNLIKELY (!j .is_array ())) 4978 { 4979JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,j .type_name ()),& j )); 4980 } 4981l .resize (j .size ()); 4982 std::transform (j .begin (),j .end (), std::begin (l ), 4983 [](const BasicJsonType & elem ) 4984 { 4985return elem .template get < T > (); 4986 }); 4987} 4988 4989template < typename BasicJsonType ,typename T , std::size_t N > 4990auto from_json (const BasicJsonType & j ,T (& arr )[N ])// NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4991-> decltype(j .template get < T > (),void ()) 4992{ 4993for (std::size_t i = 0 ;i < N ;++ i ) 4994 { 4995arr [i ]= j .at (i ).template get < T > (); 4996 } 4997} 4998 4999template < typename BasicJsonType ,typename T , std::size_t N1 , std::size_t N2 > 5000auto from_json (const BasicJsonType & j ,T (& arr )[N1 ][N2 ])// NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5001-> decltype(j .template get < T > (),void ()) 5002{ 5003for (std::size_t i1 = 0 ;i1 < N1 ;++ i1 ) 5004 { 5005for (std::size_t i2 = 0 ;i2 < N2 ;++ i2 ) 5006 { 5007arr [i1 ][i2 ]= j .at (i1 ).at (i2 ).template get < T > (); 5008 } 5009 } 5010} 5011 5012template < typename BasicJsonType ,typename T , std::size_t N1 , std::size_t N2 , std::size_t N3 > 5013auto from_json (const BasicJsonType & j ,T (& arr )[N1 ][N2 ][N3 ])// NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5014-> decltype(j .template get < T > (),void ()) 5015{ 5016for (std::size_t i1 = 0 ;i1 < N1 ;++ i1 ) 5017 { 5018for (std::size_t i2 = 0 ;i2 < N2 ;++ i2 ) 5019 { 5020for (std::size_t i3 = 0 ;i3 < N3 ;++ i3 ) 5021 { 5022arr [i1 ][i2 ][i3 ]= j .at (i1 ).at (i2 ).at (i3 ).template get < T > (); 5023 } 5024 } 5025 } 5026} 5027 5028template < typename BasicJsonType ,typename T , std::size_t N1 , std::size_t N2 , std::size_t N3 , std::size_t N4 > 5029auto from_json (const BasicJsonType & j ,T (& arr )[N1 ][N2 ][N3 ][N4 ])// NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5030-> decltype(j .template get < T > (),void ()) 5031{ 5032for (std::size_t i1 = 0 ;i1 < N1 ;++ i1 ) 5033 { 5034for (std::size_t i2 = 0 ;i2 < N2 ;++ i2 ) 5035 { 5036for (std::size_t i3 = 0 ;i3 < N3 ;++ i3 ) 5037 { 5038for (std::size_t i4 = 0 ;i4 < N4 ;++ i4 ) 5039 { 5040arr [i1 ][i2 ][i3 ][i4 ]= j .at (i1 ).at (i2 ).at (i3 ).at (i4 ).template get < T > (); 5041 } 5042 } 5043 } 5044 } 5045} 5046 5047template < typename BasicJsonType > 5048inline void from_json_array_impl (const BasicJsonType & j ,typename BasicJsonType ::array_t & arr ,priority_tag < 3 > /*unused*/ ) 5049{ 5050arr = * j .template get_ptr < const typename BasicJsonType ::array_t *> (); 5051} 5052 5053template < typename BasicJsonType ,typename T , std::size_t N > 5054auto from_json_array_impl (const BasicJsonType & j , std::array < T ,N >& arr , 5055priority_tag < 2 > /*unused*/ ) 5056-> decltype(j .template get < T > (),void ()) 5057{ 5058for (std::size_t i = 0 ;i < N ;++ i ) 5059 { 5060arr [i ]= j .at (i ).template get < T > (); 5061 } 5062} 5063 5064template < typename BasicJsonType ,typename ConstructibleArrayType , 5065enable_if_t < 5066 std::is_assignable < ConstructibleArrayType & ,ConstructibleArrayType > ::value , 5067int > = 0 > 5068auto from_json_array_impl (const BasicJsonType & j ,ConstructibleArrayType & arr ,priority_tag < 1 > /*unused*/ ) 5069-> decltype( 5070arr .reserve (std::declval < typename ConstructibleArrayType ::size_type > ()), 5071j .template get < typename ConstructibleArrayType ::value_type > (), 5072void ()) 5073{ 5074using std::end ; 5075 5076ConstructibleArrayType ret ; 5077ret .reserve (j .size ()); 5078 std::transform (j .begin (),j .end (), 5079 std::inserter (ret ,end (ret )), [](const BasicJsonType & i ) 5080 { 5081// get<BasicJsonType>() returns *this, this won't call a from_json 5082// method when value_type is BasicJsonType 5083return i .template get < typename ConstructibleArrayType ::value_type > (); 5084 }); 5085arr = std::move (ret ); 5086} 5087 5088template < typename BasicJsonType ,typename ConstructibleArrayType , 5089enable_if_t < 5090 std::is_assignable < ConstructibleArrayType & ,ConstructibleArrayType > ::value , 5091int > = 0 > 5092inline void from_json_array_impl (const BasicJsonType & j ,ConstructibleArrayType & arr , 5093priority_tag < 0 > /*unused*/ ) 5094{ 5095using std::end ; 5096 5097ConstructibleArrayType ret ; 5098 std::transform ( 5099j .begin (),j .end (), std::inserter (ret ,end (ret )), 5100 [](const BasicJsonType & i ) 5101 { 5102// get<BasicJsonType>() returns *this, this won't call a from_json 5103// method when value_type is BasicJsonType 5104return i .template get < typename ConstructibleArrayType ::value_type > (); 5105 }); 5106arr = std::move (ret ); 5107} 5108 5109template < typename BasicJsonType ,typename ConstructibleArrayType , 5110enable_if_t < 5111is_constructible_array_type < BasicJsonType ,ConstructibleArrayType > ::value && 5112 !is_constructible_object_type < BasicJsonType ,ConstructibleArrayType > ::value && 5113 !is_constructible_string_type < BasicJsonType ,ConstructibleArrayType > ::value && 5114 !std::is_same < ConstructibleArrayType ,typename BasicJsonType ::binary_t > ::value && 5115 !is_basic_json < ConstructibleArrayType > ::value , 5116int > = 0 > 5117auto from_json (const BasicJsonType & j ,ConstructibleArrayType & arr ) 5118-> decltype(from_json_array_impl (j ,arr ,priority_tag < 3 > {}), 5119j .template get < typename ConstructibleArrayType ::value_type > (), 5120void ()) 5121{ 5122if (JSON_HEDLEY_UNLIKELY (!j .is_array ())) 5123 { 5124JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,j .type_name ()),& j )); 5125 } 5126 5127from_json_array_impl (j ,arr ,priority_tag < 3 > {}); 5128} 5129 5130template < typename BasicJsonType ,typename T , std::size_t ...Idx > 5131std::array < T ,sizeof ...(Idx )> from_json_inplace_array_impl (BasicJsonType && j , 5132identity_tag < std::array < T ,sizeof ...(Idx )>> /*unused*/ ,index_sequence < Idx ...> /*unused*/ ) 5133{ 5134return { { std::forward < BasicJsonType > (j ).at (Idx ).template get < T > ()... } }; 5135} 5136 5137template < typename BasicJsonType ,typename T , std::size_t N > 5138auto from_json (BasicJsonType && j ,identity_tag < std::array < T ,N >> tag ) 5139-> decltype(from_json_inplace_array_impl (std::forward < BasicJsonType > (j ),tag ,make_index_sequence < N > {})) 5140{ 5141if (JSON_HEDLEY_UNLIKELY (!j .is_array ())) 5142 { 5143JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,j .type_name ()),& j )); 5144 } 5145 5146return from_json_inplace_array_impl (std::forward < BasicJsonType > (j ),tag ,make_index_sequence < N > {}); 5147} 5148 5149template < typename BasicJsonType > 5150inline void from_json (const BasicJsonType & j ,typename BasicJsonType ::binary_t & bin ) 5151{ 5152if (JSON_HEDLEY_UNLIKELY (!j .is_binary ())) 5153 { 5154JSON_THROW (type_error::create (302 ,concat ("type must be binary, but is " ,j .type_name ()),& j )); 5155 } 5156 5157bin = * j .template get_ptr < const typename BasicJsonType ::binary_t *> (); 5158} 5159 5160template < typename BasicJsonType ,typename ConstructibleObjectType , 5161enable_if_t < is_constructible_object_type < BasicJsonType ,ConstructibleObjectType > ::value ,int > = 0 > 5162inline void from_json (const BasicJsonType & j ,ConstructibleObjectType & obj ) 5163{ 5164if (JSON_HEDLEY_UNLIKELY (!j .is_object ())) 5165 { 5166JSON_THROW (type_error::create (302 ,concat ("type must be object, but is " ,j .type_name ()),& j )); 5167 } 5168 5169ConstructibleObjectType ret ; 5170const auto * inner_object = j .template get_ptr < const typename BasicJsonType ::object_t *> (); 5171using value_type = typename ConstructibleObjectType ::value_type ; 5172 std::transform ( 5173inner_object -> begin (),inner_object -> end (), 5174 std::inserter (ret ,ret .begin ()), 5175 [](typename BasicJsonType ::object_t::value_type const & p ) 5176 { 5177return value_type (p .first ,p .second .template get < typename ConstructibleObjectType ::mapped_type > ()); 5178 }); 5179obj = std::move (ret ); 5180} 5181 5182// overload for arithmetic types, not chosen for basic_json template arguments 5183// (BooleanType, etc..); note: Is it really necessary to provide explicit 5184// overloads for boolean_t etc. in case of a custom BooleanType which is not 5185// an arithmetic type? 5186template < typename BasicJsonType ,typename ArithmeticType , 5187enable_if_t < 5188 std::is_arithmetic < ArithmeticType > ::value && 5189 !std::is_same < ArithmeticType ,typename BasicJsonType ::number_unsigned_t > ::value && 5190 !std::is_same < ArithmeticType ,typename BasicJsonType ::number_integer_t > ::value && 5191 !std::is_same < ArithmeticType ,typename BasicJsonType ::number_float_t > ::value && 5192 !std::is_same < ArithmeticType ,typename BasicJsonType ::boolean_t > ::value , 5193int > = 0 > 5194inline void from_json (const BasicJsonType & j ,ArithmeticType & val ) 5195{ 5196switch (static_cast < value_t > (j )) 5197 { 5198case value_t::number_unsigned : 5199 { 5200val = static_cast < ArithmeticType > (* j .template get_ptr < const typename BasicJsonType ::number_unsigned_t *> ()); 5201break ; 5202 } 5203case value_t::number_integer : 5204 { 5205val = static_cast < ArithmeticType > (* j .template get_ptr < const typename BasicJsonType ::number_integer_t *> ()); 5206break ; 5207 } 5208case value_t::number_float : 5209 { 5210val = static_cast < ArithmeticType > (* j .template get_ptr < const typename BasicJsonType ::number_float_t *> ()); 5211break ; 5212 } 5213case value_t::boolean : 5214 { 5215val = static_cast < ArithmeticType > (* j .template get_ptr < const typename BasicJsonType ::boolean_t *> ()); 5216break ; 5217 } 5218 5219case value_t::null : 5220case value_t::object : 5221case value_t::array : 5222case value_t::string : 5223case value_t::binary : 5224case value_t::discarded : 5225default : 5226JSON_THROW (type_error::create (302 ,concat ("type must be number, but is " ,j .type_name ()),& j )); 5227 } 5228} 5229 5230template < typename BasicJsonType ,typename ...Args , std::size_t ...Idx > 5231std::tuple < Args ...> from_json_tuple_impl_base (BasicJsonType && j ,index_sequence < Idx ...> /*unused*/ ) 5232{ 5233return std::make_tuple (std::forward < BasicJsonType > (j ).at (Idx ).template get < Args > ()...); 5234} 5235 5236template < typename BasicJsonType > 5237std::tuple <> from_json_tuple_impl_base (BasicJsonType & /*unused*/ ,index_sequence <> /*unused*/ ) 5238{ 5239return {}; 5240} 5241 5242template < typename BasicJsonType ,class A1 ,class A2 > 5243std::pair < A1 ,A2 > from_json_tuple_impl (BasicJsonType && j ,identity_tag < std::pair < A1 ,A2 >> /*unused*/ ,priority_tag < 0 > /*unused*/ ) 5244{ 5245return {std::forward < BasicJsonType > (j ).at (0 ).template get < A1 > (), 5246 std::forward < BasicJsonType > (j ).at (1 ).template get < A2 > ()}; 5247} 5248 5249template < typename BasicJsonType ,typename A1 ,typename A2 > 5250inline void from_json_tuple_impl (BasicJsonType && j , std::pair < A1 ,A2 >& p ,priority_tag < 1 > /*unused*/ ) 5251{ 5252p = from_json_tuple_impl (std::forward < BasicJsonType > (j ),identity_tag < std::pair < A1 ,A2 >> {},priority_tag < 0 > {}); 5253} 5254 5255template < typename BasicJsonType ,typename ...Args > 5256std::tuple < Args ...> from_json_tuple_impl (BasicJsonType && j ,identity_tag < std::tuple < Args ...>> /*unused*/ ,priority_tag < 2 > /*unused*/ ) 5257{ 5258return from_json_tuple_impl_base < BasicJsonType ,Args ...> (std::forward < BasicJsonType > (j ),index_sequence_for < Args ...> {}); 5259} 5260 5261template < typename BasicJsonType ,typename ...Args > 5262inline void from_json_tuple_impl (BasicJsonType && j , std::tuple < Args ...>& t ,priority_tag < 3 > /*unused*/ ) 5263{ 5264t = from_json_tuple_impl_base < BasicJsonType ,Args ...> (std::forward < BasicJsonType > (j ),index_sequence_for < Args ...> {}); 5265} 5266 5267template < typename BasicJsonType ,typename TupleRelated > 5268auto from_json (BasicJsonType && j ,TupleRelated && t ) 5269-> decltype(from_json_tuple_impl (std::forward < BasicJsonType > (j ), std::forward < TupleRelated > (t ),priority_tag < 3 > {})) 5270{ 5271if (JSON_HEDLEY_UNLIKELY (!j .is_array ())) 5272 { 5273JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,j .type_name ()),& j )); 5274 } 5275 5276return from_json_tuple_impl (std::forward < BasicJsonType > (j ), std::forward < TupleRelated > (t ),priority_tag < 3 > {}); 5277} 5278 5279template < typename BasicJsonType ,typename Key ,typename Value ,typename Compare ,typename Allocator , 5280typename = enable_if_t < !std::is_constructible < 5281typename BasicJsonType ::string_t ,Key > ::value >> 5282inline void from_json (const BasicJsonType & j , std::map < Key ,Value ,Compare ,Allocator >& m ) 5283{ 5284if (JSON_HEDLEY_UNLIKELY (!j .is_array ())) 5285 { 5286JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,j .type_name ()),& j )); 5287 } 5288m .clear (); 5289for (const auto & p :j ) 5290 { 5291if (JSON_HEDLEY_UNLIKELY (!p .is_array ())) 5292 { 5293JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,p .type_name ()),& j )); 5294 } 5295m .emplace (p .at (0 ).template get < Key > (),p .at (1 ).template get < Value > ()); 5296 } 5297} 5298 5299template < typename BasicJsonType ,typename Key ,typename Value ,typename Hash ,typename KeyEqual ,typename Allocator , 5300typename = enable_if_t < !std::is_constructible < 5301typename BasicJsonType ::string_t ,Key > ::value >> 5302inline void from_json (const BasicJsonType & j , std::unordered_map < Key ,Value ,Hash ,KeyEqual ,Allocator >& m ) 5303{ 5304if (JSON_HEDLEY_UNLIKELY (!j .is_array ())) 5305 { 5306JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,j .type_name ()),& j )); 5307 } 5308m .clear (); 5309for (const auto & p :j ) 5310 { 5311if (JSON_HEDLEY_UNLIKELY (!p .is_array ())) 5312 { 5313JSON_THROW (type_error::create (302 ,concat ("type must be array, but is " ,p .type_name ()),& j )); 5314 } 5315m .emplace (p .at (0 ).template get < Key > (),p .at (1 ).template get < Value > ()); 5316 } 5317} 5318 5319#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 5320template < typename BasicJsonType > 5321inline void from_json (const BasicJsonType & j , std_fs::path & p ) 5322{ 5323if (JSON_HEDLEY_UNLIKELY (!j .is_string ())) 5324 { 5325JSON_THROW (type_error::create (302 ,concat ("type must be string, but is " ,j .type_name ()),& j )); 5326 } 5327const auto & s = * j .template get_ptr < const typename BasicJsonType ::string_t *> (); 5328#ifdef JSON_HAS_CPP_20 5329p = std_fs::path (std::u8string_view (reinterpret_cast < const char8_t *> (s .data ()),s .size ())); 5330#else 5331p = std_fs::u8path (s );// accepts UTF-8 encoded std::string in C++17, deprecated in C++20 5332#endif 5333} 5334#endif 5335 5336struct from_json_fn 5337{ 5338template < typename BasicJsonType ,typename T > 5339auto operator()(const BasicJsonType & j ,T && val )const 5340noexcept (noexcept (from_json (j , std::forward < T > (val )))) 5341-> decltype(from_json (j , std::forward < T > (val ))) 5342 { 5343return from_json (j , std::forward < T > (val )); 5344 } 5345}; 5346 5347}// namespace detail 5348 5349#ifndef JSON_HAS_CPP_17 5350/// namespace to hold default `from_json` function 5351/// to see why this is required: 5352/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 5353namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 5354{ 5355#endif 5356JSON_INLINE_VARIABLE constexpr const auto & from_json = // NOLINT(misc-definitions-in-headers) 5357 detail::static_const < detail::from_json_fn > ::value ; 5358#ifndef JSON_HAS_CPP_17 5359}// namespace 5360#endif 5361 5362NLOHMANN_JSON_NAMESPACE_END 5363 5364// #include <nlohmann/detail/conversions/to_json.hpp> 5365// __ _____ _____ _____ 5366// __| | __| | | | JSON for Modern C++ 5367// | | |__ | | | | | | version 3.12.0 5368// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5369// 5370// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 5371// SPDX-License-Identifier: MIT 5372 5373 5374 5375// #include <nlohmann/detail/macro_scope.hpp> 5376// JSON_HAS_CPP_17 5377#ifdef JSON_HAS_CPP_17 5378#include <optional> // optional 5379#endif 5380 5381#include <algorithm> // copy 5382#include <iterator> // begin, end 5383#include <string> // string 5384#include <tuple> // tuple, get 5385#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type 5386#include <utility> // move, forward, declval, pair 5387#include <valarray> // valarray 5388#include <vector> // vector 5389 5390// #include <nlohmann/detail/iterators/iteration_proxy.hpp> 5391// __ _____ _____ _____ 5392// __| | __| | | | JSON for Modern C++ 5393// | | |__ | | | | | | version 3.12.0 5394// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5395// 5396// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 5397// SPDX-License-Identifier: MIT 5398 5399 5400 5401#include <cstddef> // size_t 5402#include <iterator> // forward_iterator_tag 5403#include <tuple> // tuple_size, get, tuple_element 5404#include <utility> // move 5405 5406#if JSON_HAS_RANGES 5407#include <ranges> // enable_borrowed_range 5408#endif 5409 5410// #include <nlohmann/detail/abi_macros.hpp> 5411 5412// #include <nlohmann/detail/meta/type_traits.hpp> 5413 5414// #include <nlohmann/detail/string_utils.hpp> 5415// __ _____ _____ _____ 5416// __| | __| | | | JSON for Modern C++ 5417// | | |__ | | | | | | version 3.12.0 5418// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5419// 5420// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 5421// SPDX-License-Identifier: MIT 5422 5423 5424 5425#include <cstddef> // size_t 5426#include <string> // string, to_string 5427 5428// #include <nlohmann/detail/abi_macros.hpp> 5429 5430 5431NLOHMANN_JSON_NAMESPACE_BEGIN 5432namespace detail 5433{ 5434 5435template < typename StringType > 5436void int_to_string (StringType & target , std::size_t value ) 5437{ 5438// For ADL 5439using std::to_string ; 5440target = to_string (value ); 5441} 5442 5443template < typename StringType > 5444StringType to_string (std::size_t value ) 5445{ 5446StringType result ; 5447int_to_string (result ,value ); 5448return result ; 5449} 5450 5451}// namespace detail 5452NLOHMANN_JSON_NAMESPACE_END 5453 5454// #include <nlohmann/detail/value_t.hpp> 5455 5456 5457NLOHMANN_JSON_NAMESPACE_BEGIN 5458namespace detail 5459{ 5460 5461template < typename IteratorType > class iteration_proxy_value 5462{ 5463public : 5464using difference_type = std::ptrdiff_t ; 5465using value_type = iteration_proxy_value ; 5466using pointer = value_type * ; 5467using reference = value_type & ; 5468using iterator_category = std::forward_iterator_tag ; 5469using string_type = typename std::remove_cv < typename std::remove_reference < decltype( std::declval < IteratorType > ().key () )> ::type > ::type ; 5470 5471private : 5472/// the iterator 5473IteratorType anchor {}; 5474/// an index for arrays (used to create key names) 5475 std::size_t array_index = 0 ; 5476/// last stringified array index 5477mutable std::size_t array_index_last = 0 ; 5478/// a string representation of the array index 5479mutable string_type array_index_str = "0" ; 5480/// an empty string (to return a reference for primitive values) 5481string_type empty_str {}; 5482 5483public : 5484explicit iteration_proxy_value ()= default ; 5485explicit iteration_proxy_value (IteratorType it , std::size_t array_index_ = 0 ) 5486noexcept (std::is_nothrow_move_constructible < IteratorType > ::value 5487&& std::is_nothrow_default_constructible < string_type > ::value ) 5488 :anchor (std::move (it )) 5489 ,array_index (array_index_ ) 5490 {} 5491 5492iteration_proxy_value (iteration_proxy_value const & )= default ; 5493iteration_proxy_value & operator= (iteration_proxy_value const & )= default ; 5494// older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions 5495iteration_proxy_value (iteration_proxy_value && ) 5496noexcept (std::is_nothrow_move_constructible < IteratorType > ::value 5497&& std::is_nothrow_move_constructible < string_type > ::value )= default ;// NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) 5498iteration_proxy_value & operator= (iteration_proxy_value && ) 5499noexcept (std::is_nothrow_move_assignable < IteratorType > ::value 5500&& std::is_nothrow_move_assignable < string_type > ::value )= default ;// NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) 5501 ~iteration_proxy_value ()= default ; 5502 5503/// dereference operator (needed for range-based for) 5504const iteration_proxy_value & operator* ()const 5505 { 5506return * this ; 5507 } 5508 5509/// increment operator (needed for range-based for) 5510iteration_proxy_value & operator++ () 5511 { 5512++ anchor ; 5513++ array_index ; 5514 5515return * this ; 5516 } 5517 5518iteration_proxy_value operator++ (int )& // NOLINT(cert-dcl21-cpp) 5519 { 5520auto tmp = iteration_proxy_value (anchor ,array_index ); 5521++ anchor ; 5522++ array_index ; 5523return tmp ; 5524 } 5525 5526/// equality operator (needed for InputIterator) 5527bool operator== (const iteration_proxy_value & o )const 5528 { 5529return anchor == o .anchor ; 5530 } 5531 5532/// inequality operator (needed for range-based for) 5533bool operator!= (const iteration_proxy_value & o )const 5534 { 5535return anchor != o .anchor ; 5536 } 5537 5538/// return key of the iterator 5539const string_type & key ()const 5540 { 5541JSON_ASSERT (anchor .m_object != nullptr ); 5542 5543switch (anchor .m_object -> type ()) 5544 { 5545// use integer array index as key 5546case value_t::array : 5547 { 5548if (array_index != array_index_last ) 5549 { 5550int_to_string (array_index_str ,array_index ); 5551array_index_last = array_index ; 5552 } 5553return array_index_str ; 5554 } 5555 5556// use key from the object 5557case value_t::object : 5558return anchor .key (); 5559 5560// use an empty key for all primitive types 5561case value_t::null : 5562case value_t::string : 5563case value_t::boolean : 5564case value_t::number_integer : 5565case value_t::number_unsigned : 5566case value_t::number_float : 5567case value_t::binary : 5568case value_t::discarded : 5569default : 5570return empty_str ; 5571 } 5572 } 5573 5574/// return value of the iterator 5575typename IteratorType ::reference value ()const 5576 { 5577return anchor .value (); 5578 } 5579}; 5580 5581/// proxy class for the items() function 5582template < typename IteratorType > class iteration_proxy 5583{ 5584private : 5585/// the container to iterate 5586typename IteratorType ::pointer container = nullptr ; 5587 5588public : 5589explicit iteration_proxy ()= default ; 5590 5591/// construct iteration proxy from a container 5592explicit iteration_proxy (typename IteratorType ::reference cont )noexcept 5593 :container (& cont ) {} 5594 5595iteration_proxy (iteration_proxy const & )= default ; 5596iteration_proxy & operator= (iteration_proxy const & )= default ; 5597iteration_proxy (iteration_proxy && )noexcept = default ; 5598iteration_proxy & operator= (iteration_proxy && )noexcept = default ; 5599 ~iteration_proxy ()= default ; 5600 5601/// return iterator begin (needed for range-based for) 5602iteration_proxy_value < IteratorType > begin ()const noexcept 5603 { 5604return iteration_proxy_value < IteratorType > (container -> begin ()); 5605 } 5606 5607/// return iterator end (needed for range-based for) 5608iteration_proxy_value < IteratorType > end ()const noexcept 5609 { 5610return iteration_proxy_value < IteratorType > (container -> end ()); 5611 } 5612}; 5613 5614// Structured Bindings Support 5615// For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5616// And see https://github.com/nlohmann/json/pull/1391 5617template < std::size_t N ,typename IteratorType ,enable_if_t < N == 0 ,int > = 0 > 5618auto get (const nlohmann::detail::iteration_proxy_value < IteratorType >& i )-> decltype(i .key ()) 5619{ 5620return i .key (); 5621} 5622// Structured Bindings Support 5623// For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5624// And see https://github.com/nlohmann/json/pull/1391 5625template < std::size_t N ,typename IteratorType ,enable_if_t < N == 1 ,int > = 0 > 5626auto get (const nlohmann::detail::iteration_proxy_value < IteratorType >& i )-> decltype(i .value ()) 5627{ 5628return i .value (); 5629} 5630 5631}// namespace detail 5632NLOHMANN_JSON_NAMESPACE_END 5633 5634// The Addition to the STD Namespace is required to add 5635// Structured Bindings Support to the iteration_proxy_value class 5636// For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5637// And see https://github.com/nlohmann/json/pull/1391 5638namespace std 5639{ 5640 5641#if defined(__clang__ ) 5642// Fix: https://github.com/nlohmann/json/issues/1401 5643#pragma clang diagnostic push 5644#pragma clang diagnostic ignored "-Wmismatched-tags" 5645#endif 5646template < typename IteratorType > 5647class tuple_size < ::nlohmann::detail::iteration_proxy_value < IteratorType >> // NOLINT(cert-dcl58-cpp) 5648 :public std::integral_constant < std::size_t ,2 > {}; 5649 5650template < std::size_t N ,typename IteratorType > 5651class tuple_element < N , ::nlohmann::detail::iteration_proxy_value < IteratorType >> // NOLINT(cert-dcl58-cpp) 5652{ 5653public : 5654using type = decltype( 5655get < N > (std::declval < 5656 ::nlohmann::detail::iteration_proxy_value < IteratorType >> ())); 5657}; 5658#if defined(__clang__ ) 5659#pragma clang diagnostic pop 5660#endif 5661 5662}// namespace std 5663 5664#if JSON_HAS_RANGES 5665template < typename IteratorType > 5666inline constexpr bool ::std::ranges::enable_borrowed_range < ::nlohmann::detail::iteration_proxy < IteratorType >> = true; 5667#endif 5668 5669// #include <nlohmann/detail/meta/cpp_future.hpp> 5670 5671// #include <nlohmann/detail/meta/std_fs.hpp> 5672 5673// #include <nlohmann/detail/meta/type_traits.hpp> 5674 5675// #include <nlohmann/detail/value_t.hpp> 5676 5677 5678NLOHMANN_JSON_NAMESPACE_BEGIN 5679namespace detail 5680{ 5681 5682////////////////// 5683// constructors // 5684////////////////// 5685 5686/* 5687* Note all external_constructor<>::construct functions need to call 5688* j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an 5689* allocated value (e.g., a string). See bug issue 5690* https://github.com/nlohmann/json/issues/2865 for more information. 5691*/ 5692 5693template < value_t > struct external_constructor ; 5694 5695template <> 5696struct external_constructor < value_t::boolean > 5697{ 5698template < typename BasicJsonType > 5699static void construct (BasicJsonType & j ,typename BasicJsonType ::boolean_t b )noexcept 5700 { 5701j .m_data .m_value .destroy (j .m_data .m_type ); 5702j .m_data .m_type = value_t::boolean ; 5703j .m_data .m_value = b ; 5704j .assert_invariant (); 5705 } 5706}; 5707 5708template <> 5709struct external_constructor < value_t::string > 5710{ 5711template < typename BasicJsonType > 5712static void construct (BasicJsonType & j ,const typename BasicJsonType ::string_t & s ) 5713 { 5714j .m_data .m_value .destroy (j .m_data .m_type ); 5715j .m_data .m_type = value_t::string ; 5716j .m_data .m_value = s ; 5717j .assert_invariant (); 5718 } 5719 5720template < typename BasicJsonType > 5721static void construct (BasicJsonType & j ,typename BasicJsonType ::string_t && s ) 5722 { 5723j .m_data .m_value .destroy (j .m_data .m_type ); 5724j .m_data .m_type = value_t::string ; 5725j .m_data .m_value = std::move (s ); 5726j .assert_invariant (); 5727 } 5728 5729template < typename BasicJsonType ,typename CompatibleStringType , 5730enable_if_t < !std::is_same < CompatibleStringType ,typename BasicJsonType ::string_t > ::value , 5731int > = 0 > 5732static void construct (BasicJsonType & j ,const CompatibleStringType & str ) 5733 { 5734j .m_data .m_value .destroy (j .m_data .m_type ); 5735j .m_data .m_type = value_t::string ; 5736j .m_data .m_value .string = j .template create < typename BasicJsonType ::string_t > (str ); 5737j .assert_invariant (); 5738 } 5739}; 5740 5741template <> 5742struct external_constructor < value_t::binary > 5743{ 5744template < typename BasicJsonType > 5745static void construct (BasicJsonType & j ,const typename BasicJsonType ::binary_t & b ) 5746 { 5747j .m_data .m_value .destroy (j .m_data .m_type ); 5748j .m_data .m_type = value_t::binary ; 5749j .m_data .m_value = typename BasicJsonType ::binary_t (b ); 5750j .assert_invariant (); 5751 } 5752 5753template < typename BasicJsonType > 5754static void construct (BasicJsonType & j ,typename BasicJsonType ::binary_t && b ) 5755 { 5756j .m_data .m_value .destroy (j .m_data .m_type ); 5757j .m_data .m_type = value_t::binary ; 5758j .m_data .m_value = typename BasicJsonType ::binary_t (std::move (b )); 5759j .assert_invariant (); 5760 } 5761}; 5762 5763template <> 5764struct external_constructor < value_t::number_float > 5765{ 5766template < typename BasicJsonType > 5767static void construct (BasicJsonType & j ,typename BasicJsonType ::number_float_t val )noexcept 5768 { 5769j .m_data .m_value .destroy (j .m_data .m_type ); 5770j .m_data .m_type = value_t::number_float ; 5771j .m_data .m_value = val ; 5772j .assert_invariant (); 5773 } 5774}; 5775 5776template <> 5777struct external_constructor < value_t::number_unsigned > 5778{ 5779template < typename BasicJsonType > 5780static void construct (BasicJsonType & j ,typename BasicJsonType ::number_unsigned_t val )noexcept 5781 { 5782j .m_data .m_value .destroy (j .m_data .m_type ); 5783j .m_data .m_type = value_t::number_unsigned ; 5784j .m_data .m_value = val ; 5785j .assert_invariant (); 5786 } 5787}; 5788 5789template <> 5790struct external_constructor < value_t::number_integer > 5791{ 5792template < typename BasicJsonType > 5793static void construct (BasicJsonType & j ,typename BasicJsonType ::number_integer_t val )noexcept 5794 { 5795j .m_data .m_value .destroy (j .m_data .m_type ); 5796j .m_data .m_type = value_t::number_integer ; 5797j .m_data .m_value = val ; 5798j .assert_invariant (); 5799 } 5800}; 5801 5802template <> 5803struct external_constructor < value_t::array > 5804{ 5805template < typename BasicJsonType > 5806static void construct (BasicJsonType & j ,const typename BasicJsonType ::array_t & arr ) 5807 { 5808j .m_data .m_value .destroy (j .m_data .m_type ); 5809j .m_data .m_type = value_t::array ; 5810j .m_data .m_value = arr ; 5811j .set_parents (); 5812j .assert_invariant (); 5813 } 5814 5815template < typename BasicJsonType > 5816static void construct (BasicJsonType & j ,typename BasicJsonType ::array_t && arr ) 5817 { 5818j .m_data .m_value .destroy (j .m_data .m_type ); 5819j .m_data .m_type = value_t::array ; 5820j .m_data .m_value = std::move (arr ); 5821j .set_parents (); 5822j .assert_invariant (); 5823 } 5824 5825template < typename BasicJsonType ,typename CompatibleArrayType , 5826enable_if_t < !std::is_same < CompatibleArrayType ,typename BasicJsonType ::array_t > ::value , 5827int > = 0 > 5828static void construct (BasicJsonType & j ,const CompatibleArrayType & arr ) 5829 { 5830using std::begin ; 5831using std::end ; 5832 5833j .m_data .m_value .destroy (j .m_data .m_type ); 5834j .m_data .m_type = value_t::array ; 5835j .m_data .m_value .array = j .template create < typename BasicJsonType ::array_t > (begin (arr ),end (arr )); 5836j .set_parents (); 5837j .assert_invariant (); 5838 } 5839 5840template < typename BasicJsonType > 5841static void construct (BasicJsonType & j ,const std::vector < bool >& arr ) 5842 { 5843j .m_data .m_value .destroy (j .m_data .m_type ); 5844j .m_data .m_type = value_t::array ; 5845j .m_data .m_value = value_t::array ; 5846j .m_data .m_value .array -> reserve (arr .size ()); 5847for (const bool x :arr ) 5848 { 5849j .m_data .m_value .array -> push_back (x ); 5850j .set_parent (j .m_data .m_value .array -> back ()); 5851 } 5852j .assert_invariant (); 5853 } 5854 5855template < typename BasicJsonType ,typename T , 5856enable_if_t < std::is_convertible < T ,BasicJsonType > ::value ,int > = 0 > 5857static void construct (BasicJsonType & j ,const std::valarray < T >& arr ) 5858 { 5859j .m_data .m_value .destroy (j .m_data .m_type ); 5860j .m_data .m_type = value_t::array ; 5861j .m_data .m_value = value_t::array ; 5862j .m_data .m_value .array -> resize (arr .size ()); 5863if (arr .size ()> 0 ) 5864 { 5865 std::copy (std::begin (arr ), std::end (arr ),j .m_data .m_value .array -> begin ()); 5866 } 5867j .set_parents (); 5868j .assert_invariant (); 5869 } 5870}; 5871 5872template <> 5873struct external_constructor < value_t::object > 5874{ 5875template < typename BasicJsonType > 5876static void construct (BasicJsonType & j ,const typename BasicJsonType ::object_t & obj ) 5877 { 5878j .m_data .m_value .destroy (j .m_data .m_type ); 5879j .m_data .m_type = value_t::object ; 5880j .m_data .m_value = obj ; 5881j .set_parents (); 5882j .assert_invariant (); 5883 } 5884 5885template < typename BasicJsonType > 5886static void construct (BasicJsonType & j ,typename BasicJsonType ::object_t && obj ) 5887 { 5888j .m_data .m_value .destroy (j .m_data .m_type ); 5889j .m_data .m_type = value_t::object ; 5890j .m_data .m_value = std::move (obj ); 5891j .set_parents (); 5892j .assert_invariant (); 5893 } 5894 5895template < typename BasicJsonType ,typename CompatibleObjectType , 5896enable_if_t < !std::is_same < CompatibleObjectType ,typename BasicJsonType ::object_t > ::value ,int > = 0 > 5897static void construct (BasicJsonType & j ,const CompatibleObjectType & obj ) 5898 { 5899using std::begin ; 5900using std::end ; 5901 5902j .m_data .m_value .destroy (j .m_data .m_type ); 5903j .m_data .m_type = value_t::object ; 5904j .m_data .m_value .object = j .template create < typename BasicJsonType ::object_t > (begin (obj ),end (obj )); 5905j .set_parents (); 5906j .assert_invariant (); 5907 } 5908}; 5909 5910///////////// 5911// to_json // 5912///////////// 5913 5914#ifdef JSON_HAS_CPP_17 5915template < typename BasicJsonType ,typename T , 5916enable_if_t < std::is_constructible < BasicJsonType ,T > ::value ,int > = 0 > 5917void to_json (BasicJsonType & j ,const std::optional < T >& opt ) 5918{ 5919if (opt .has_value ()) 5920 { 5921j = * opt ; 5922 } 5923else 5924 { 5925j = nullptr ; 5926 } 5927} 5928#endif 5929 5930template < typename BasicJsonType ,typename T , 5931enable_if_t < std::is_same < T ,typename BasicJsonType ::boolean_t > ::value ,int > = 0 > 5932inline void to_json (BasicJsonType & j ,T b )noexcept 5933{ 5934external_constructor < value_t::boolean > ::construct (j ,b ); 5935} 5936 5937template < typename BasicJsonType ,typename BoolRef , 5938enable_if_t < 5939 ((std::is_same < std::vector < bool > ::reference ,BoolRef > ::value 5940&& !std::is_same < std::vector < bool > ::reference ,typename BasicJsonType ::boolean_t &> ::value ) 5941|| (std::is_same < std::vector < bool > ::const_reference ,BoolRef > ::value 5942&& !std::is_same < detail::uncvref_t < std::vector < bool > ::const_reference > , 5943typename BasicJsonType ::boolean_t > ::value )) 5944&& std::is_convertible < const BoolRef & ,typename BasicJsonType ::boolean_t > ::value ,int > = 0 > 5945inline void to_json (BasicJsonType & j ,const BoolRef & b )noexcept 5946{ 5947external_constructor < value_t::boolean > ::construct (j ,static_cast < typename BasicJsonType ::boolean_t > (b )); 5948} 5949 5950template < typename BasicJsonType ,typename CompatibleString , 5951enable_if_t < std::is_constructible < typename BasicJsonType ::string_t ,CompatibleString > ::value ,int > = 0 > 5952inline void to_json (BasicJsonType & j ,const CompatibleString & s ) 5953{ 5954external_constructor < value_t::string > ::construct (j ,s ); 5955} 5956 5957template < typename BasicJsonType > 5958inline void to_json (BasicJsonType & j ,typename BasicJsonType ::string_t && s ) 5959{ 5960external_constructor < value_t::string > ::construct (j , std::move (s )); 5961} 5962 5963template < typename BasicJsonType ,typename FloatType , 5964enable_if_t < std::is_floating_point < FloatType > ::value ,int > = 0 > 5965inline void to_json (BasicJsonType & j ,FloatType val )noexcept 5966{ 5967external_constructor < value_t::number_float > ::construct (j ,static_cast < typename BasicJsonType ::number_float_t > (val )); 5968} 5969 5970template < typename BasicJsonType ,typename CompatibleNumberUnsignedType , 5971enable_if_t < is_compatible_integer_type < typename BasicJsonType ::number_unsigned_t ,CompatibleNumberUnsignedType > ::value ,int > = 0 > 5972inline void to_json (BasicJsonType & j ,CompatibleNumberUnsignedType val )noexcept 5973{ 5974external_constructor < value_t::number_unsigned > ::construct (j ,static_cast < typename BasicJsonType ::number_unsigned_t > (val )); 5975} 5976 5977template < typename BasicJsonType ,typename CompatibleNumberIntegerType , 5978enable_if_t < is_compatible_integer_type < typename BasicJsonType ::number_integer_t ,CompatibleNumberIntegerType > ::value ,int > = 0 > 5979inline void to_json (BasicJsonType & j ,CompatibleNumberIntegerType val )noexcept 5980{ 5981external_constructor < value_t::number_integer > ::construct (j ,static_cast < typename BasicJsonType ::number_integer_t > (val )); 5982} 5983 5984#if !JSON_DISABLE_ENUM_SERIALIZATION 5985template < typename BasicJsonType ,typename EnumType , 5986enable_if_t < std::is_enum < EnumType > ::value ,int > = 0 > 5987inline void to_json (BasicJsonType & j ,EnumType e )noexcept 5988{ 5989using underlying_type = typename std::underlying_type < EnumType > ::type ; 5990static constexpr value_t integral_value_t = std::is_unsigned < underlying_type > ::value ? value_t::number_unsigned : value_t::number_integer ; 5991external_constructor < integral_value_t > ::construct (j ,static_cast < underlying_type > (e )); 5992} 5993#endif // JSON_DISABLE_ENUM_SERIALIZATION 5994 5995template < typename BasicJsonType > 5996inline void to_json (BasicJsonType & j ,const std::vector < bool >& e ) 5997{ 5998external_constructor < value_t::array > ::construct (j ,e ); 5999} 6000 6001template < typename BasicJsonType ,typename CompatibleArrayType , 6002enable_if_t < is_compatible_array_type < BasicJsonType , 6003CompatibleArrayType > ::value && 6004 !is_compatible_object_type < BasicJsonType ,CompatibleArrayType > ::value && 6005 !is_compatible_string_type < BasicJsonType ,CompatibleArrayType > ::value && 6006 !std::is_same < typename BasicJsonType ::binary_t ,CompatibleArrayType > ::value && 6007 !is_basic_json < CompatibleArrayType > ::value , 6008int > = 0 > 6009inline void to_json (BasicJsonType & j ,const CompatibleArrayType & arr ) 6010{ 6011external_constructor < value_t::array > ::construct (j ,arr ); 6012} 6013 6014template < typename BasicJsonType > 6015inline void to_json (BasicJsonType & j ,const typename BasicJsonType ::binary_t & bin ) 6016{ 6017external_constructor < value_t::binary > ::construct (j ,bin ); 6018} 6019 6020template < typename BasicJsonType ,typename T , 6021enable_if_t < std::is_convertible < T ,BasicJsonType > ::value ,int > = 0 > 6022inline void to_json (BasicJsonType & j ,const std::valarray < T >& arr ) 6023{ 6024external_constructor < value_t::array > ::construct (j , std::move (arr )); 6025} 6026 6027template < typename BasicJsonType > 6028inline void to_json (BasicJsonType & j ,typename BasicJsonType ::array_t && arr ) 6029{ 6030external_constructor < value_t::array > ::construct (j , std::move (arr )); 6031} 6032 6033template < typename BasicJsonType ,typename CompatibleObjectType , 6034enable_if_t < is_compatible_object_type < BasicJsonType ,CompatibleObjectType > ::value && !is_basic_json < CompatibleObjectType > ::value ,int > = 0 > 6035inline void to_json (BasicJsonType & j ,const CompatibleObjectType & obj ) 6036{ 6037external_constructor < value_t::object > ::construct (j ,obj ); 6038} 6039 6040template < typename BasicJsonType > 6041inline void to_json (BasicJsonType & j ,typename BasicJsonType ::object_t && obj ) 6042{ 6043external_constructor < value_t::object > ::construct (j , std::move (obj )); 6044} 6045 6046template < 6047typename BasicJsonType ,typename T , std::size_t N , 6048enable_if_t < !std::is_constructible < typename BasicJsonType ::string_t , 6049const T (& )[N ]> ::value ,// NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 6050int > = 0 > 6051inline void to_json (BasicJsonType & j ,const T (& arr )[N ])// NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 6052{ 6053external_constructor < value_t::array > ::construct (j ,arr ); 6054} 6055 6056template < typename BasicJsonType ,typename T1 ,typename T2 ,enable_if_t < std::is_constructible < BasicJsonType ,T1 > ::value && std::is_constructible < BasicJsonType ,T2 > ::value ,int > = 0 > 6057inline void to_json (BasicJsonType & j ,const std::pair < T1 ,T2 >& p ) 6058{ 6059j = {p .first ,p .second }; 6060} 6061 6062// for https://github.com/nlohmann/json/pull/1134 6063template < typename BasicJsonType ,typename T , 6064enable_if_t < std::is_same < T ,iteration_proxy_value < typename BasicJsonType ::iterator >> ::value ,int > = 0 > 6065inline void to_json (BasicJsonType & j ,const T & b ) 6066{ 6067j = { {b .key (),b .value ()} }; 6068} 6069 6070template < typename BasicJsonType ,typename Tuple , std::size_t ...Idx > 6071inline void to_json_tuple_impl (BasicJsonType & j ,const Tuple & t ,index_sequence < Idx ...> /*unused*/ ) 6072{ 6073j = { std::get < Idx > (t )... }; 6074} 6075 6076template < typename BasicJsonType ,typename Tuple > 6077inline void to_json_tuple_impl (BasicJsonType & j ,const Tuple & /*unused*/ ,index_sequence <> /*unused*/ ) 6078{ 6079using array_t = typename BasicJsonType ::array_t ; 6080j = array_t (); 6081} 6082 6083template < typename BasicJsonType ,typename T ,enable_if_t < is_constructible_tuple < BasicJsonType ,T > ::value ,int > = 0 > 6084inline void to_json (BasicJsonType & j ,const T & t ) 6085{ 6086to_json_tuple_impl (j ,t ,make_index_sequence < std::tuple_size < T > ::value > {}); 6087} 6088 6089#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 6090template < typename BasicJsonType > 6091inline void to_json (BasicJsonType & j ,const std_fs::path & p ) 6092{ 6093#ifdef JSON_HAS_CPP_20 6094const std::u8string s = p .u8string (); 6095j = std::string (s .begin (),s .end ()); 6096#else 6097j = p .u8string ();// returns std::string in C++17 6098#endif 6099} 6100#endif 6101 6102struct to_json_fn 6103{ 6104template < typename BasicJsonType ,typename T > 6105auto operator()(BasicJsonType & j ,T && val )const noexcept (noexcept (to_json (j , std::forward < T > (val )))) 6106-> decltype(to_json (j , std::forward < T > (val )),void ()) 6107 { 6108return to_json (j , std::forward < T > (val )); 6109 } 6110}; 6111}// namespace detail 6112 6113#ifndef JSON_HAS_CPP_17 6114/// namespace to hold default `to_json` function 6115/// to see why this is required: 6116/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 6117namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 6118{ 6119#endif 6120JSON_INLINE_VARIABLE constexpr const auto & to_json = // NOLINT(misc-definitions-in-headers) 6121 detail::static_const < detail::to_json_fn > ::value ; 6122#ifndef JSON_HAS_CPP_17 6123}// namespace 6124#endif 6125 6126NLOHMANN_JSON_NAMESPACE_END 6127 6128// #include <nlohmann/detail/meta/identity_tag.hpp> 6129 6130 6131NLOHMANN_JSON_NAMESPACE_BEGIN 6132 6133/// @sa https://json.nlohmann.me/api/adl_serializer/ 6134template < typename ValueType ,typename > 6135struct adl_serializer 6136{ 6137/// @brief convert a JSON value to any value type 6138/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 6139template < typename BasicJsonType ,typename TargetType = ValueType > 6140static auto from_json (BasicJsonType && j ,TargetType & val )noexcept ( 6141noexcept (::nlohmann::from_json (std::forward < BasicJsonType > (j ),val ))) 6142-> decltype(::nlohmann::from_json (std::forward < BasicJsonType > (j ),val ),void ()) 6143 { 6144 ::nlohmann::from_json (std::forward < BasicJsonType > (j ),val ); 6145 } 6146 6147/// @brief convert a JSON value to any value type 6148/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 6149template < typename BasicJsonType ,typename TargetType = ValueType > 6150static auto from_json (BasicJsonType && j )noexcept ( 6151noexcept (::nlohmann::from_json (std::forward < BasicJsonType > (j ), detail::identity_tag < TargetType > {}))) 6152-> decltype(::nlohmann::from_json (std::forward < BasicJsonType > (j ), detail::identity_tag < TargetType > {})) 6153 { 6154return ::nlohmann::from_json (std::forward < BasicJsonType > (j ), detail::identity_tag < TargetType > {}); 6155 } 6156 6157/// @brief convert any value type to a JSON value 6158/// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ 6159template < typename BasicJsonType ,typename TargetType = ValueType > 6160static auto to_json (BasicJsonType & j ,TargetType && val )noexcept ( 6161noexcept (::nlohmann::to_json (j , std::forward < TargetType > (val )))) 6162-> decltype(::nlohmann::to_json (j , std::forward < TargetType > (val )),void ()) 6163 { 6164 ::nlohmann::to_json (j , std::forward < TargetType > (val )); 6165 } 6166}; 6167 6168NLOHMANN_JSON_NAMESPACE_END 6169 6170// #include <nlohmann/byte_container_with_subtype.hpp> 6171// __ _____ _____ _____ 6172// __| | __| | | | JSON for Modern C++ 6173// | | |__ | | | | | | version 3.12.0 6174// |_____|_____|_____|_|___| https://github.com/nlohmann/json 6175// 6176// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 6177// SPDX-License-Identifier: MIT 6178 6179 6180 6181#include <cstdint> // uint8_t, uint64_t 6182#include <tuple> // tie 6183#include <utility> // move 6184 6185// #include <nlohmann/detail/abi_macros.hpp> 6186 6187 6188NLOHMANN_JSON_NAMESPACE_BEGIN 6189 6190/// @brief an internal type for a backed binary type 6191/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ 6192template < typename BinaryType > 6193class byte_container_with_subtype : public BinaryType 6194{ 6195public : 6196using container_type = BinaryType ; 6197using subtype_type = std :: uint64_t ; 6198 6199/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 6200byte_container_with_subtype () noexcept ( noexcept ( container_type ())) 6201: container_type () 6202{} 6203 6204/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 6205byte_container_with_subtype ( const container_type & b ) noexcept ( noexcept ( container_type ( b ))) 6206: container_type ( b ) 6207{} 6208 6209/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 6210byte_container_with_subtype ( container_type && b ) noexcept ( noexcept ( container_type ( std :: move ( b )))) 6211: container_type ( std :: move ( b )) 6212{} 6213 6214/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 6215byte_container_with_subtype ( const container_type & b , subtype_type subtype_ ) noexcept ( noexcept ( container_type ( b ))) 6216: container_type ( b ) 6217, m_subtype ( subtype_ ) 6218, m_has_subtype (true) 6219{} 6220 6221/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 6222byte_container_with_subtype ( container_type && b , subtype_type subtype_ ) noexcept ( noexcept ( container_type ( std :: move ( b )))) 6223: container_type ( std :: move ( b )) 6224, m_subtype ( subtype_ ) 6225, m_has_subtype (true) 6226{} 6227 6228bool operator==( const byte_container_with_subtype & rhs ) const 6229{ 6230return std :: tie ( static_cast < const BinaryType &>(* this ), m_subtype , m_has_subtype ) == 6231std :: tie ( static_cast < const BinaryType &>( rhs ), rhs . m_subtype , rhs . m_has_subtype ); 6232} 6233 6234bool operator!=( const byte_container_with_subtype & rhs ) const 6235{ 6236return !( rhs == * this ); 6237} 6238 6239/// @brief sets the binary subtype 6240/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ 6241void set_subtype ( subtype_type subtype_ ) noexcept 6242{ 6243m_subtype = subtype_ ; 6244m_has_subtype = true; 6245} 6246 6247/// @brief return the binary subtype 6248/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ 6249constexpr subtype_type subtype () const noexcept 6250{ 6251return m_has_subtype ? m_subtype : static_cast < subtype_type >( -1 ); 6252} 6253 6254/// @brief return whether the value has a subtype 6255/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ 6256constexpr bool has_subtype () const noexcept 6257{ 6258return m_has_subtype ; 6259} 6260 6261/// @brief clears the binary subtype 6262/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ 6263void clear_subtype () noexcept 6264{ 6265m_subtype = 0 ; 6266m_has_subtype = false; 6267} 6268 6269private : 6270subtype_type m_subtype = 0 ; 6271bool m_has_subtype = false; 6272}; 6273 6274NLOHMANN_JSON_NAMESPACE_END 6275 6276// #include <nlohmann/detail/conversions/from_json.hpp> 6277 6278// #include <nlohmann/detail/conversions/to_json.hpp> 6279 6280// #include <nlohmann/detail/exceptions.hpp> 6281 6282// #include <nlohmann/detail/hash.hpp> 6283// __ _____ _____ _____ 6284// __| | __| | | | JSON for Modern C++ 6285// | | |__ | | | | | | version 3.12.0 6286// |_____|_____|_____|_|___| https://github.com/nlohmann/json 6287// 6288// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 6289// SPDX-License-Identifier: MIT 6290 6291 6292 6293#include <cstdint> // uint8_t 6294#include <cstddef> // size_t 6295#include <functional> // hash 6296 6297// #include <nlohmann/detail/abi_macros.hpp> 6298 6299// #include <nlohmann/detail/value_t.hpp> 6300 6301 6302NLOHMANN_JSON_NAMESPACE_BEGIN 6303namespace detail 6304{ 6305 6306// boost::hash_combine 6307inline std:: size_t combine (std:: size_t seed , std:: size_t h ) noexcept 6308{ 6309seed ^= h + 0x9e3779b9 + ( seed << 6U ) + ( seed >> 2U ); 6310return seed ; 6311} 6312 6313/*! 6314@brief hash a JSON value 6315 6316The hash function tries to rely on std::hash where possible. Furthermore, the 6317type of the JSON value is taken into account to have different hash values for 6318null, 0, 0U, and false, etc. 6319 6320@tparam BasicJsonType basic_json specialization 6321@param j JSON value to hash 6322@return hash value of j 6323*/ 6324template < typename BasicJsonType > 6325std:: size_t hash ( const BasicJsonType & j ) 6326{ 6327using string_t = typename BasicJsonType :: string_t ; 6328using number_integer_t = typename BasicJsonType :: number_integer_t ; 6329using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 6330using number_float_t = typename BasicJsonType :: number_float_t ; 6331 6332const auto type = static_cast <std:: size_t >( j . type ()); 6333switch ( j . type ()) 6334{ 6335case BasicJsonType ::value_t:: null : 6336case BasicJsonType ::value_t:: discarded : 6337{ 6338return combine ( type , 0 ); 6339} 6340 6341case BasicJsonType ::value_t:: object : 6342{ 6343auto seed = combine ( type , j . size ()); 6344for ( const auto & element : j . items ()) 6345{ 6346const auto h = std:: hash < string_t > {}( element . key ()); 6347seed = combine ( seed , h ); 6348seed = combine ( seed , hash ( element . value ())); 6349} 6350return seed ; 6351} 6352 6353case BasicJsonType ::value_t:: array : 6354{ 6355auto seed = combine ( type , j . size ()); 6356for ( const auto & element : j ) 6357{ 6358seed = combine ( seed , hash ( element )); 6359} 6360return seed ; 6361} 6362 6363case BasicJsonType ::value_t:: string : 6364{ 6365const auto h = std:: hash < string_t > {}( j . template get_ref < const string_t &>()); 6366return combine ( type , h ); 6367} 6368 6369case BasicJsonType ::value_t:: boolean : 6370{ 6371const auto h = std:: hash < bool > {}( j . template get < bool >()); 6372return combine ( type , h ); 6373} 6374 6375case BasicJsonType ::value_t:: number_integer : 6376{ 6377const auto h = std:: hash < number_integer_t > {}( j . template get < number_integer_t >()); 6378return combine ( type , h ); 6379} 6380 6381case BasicJsonType ::value_t:: number_unsigned : 6382{ 6383const auto h = std:: hash < number_unsigned_t > {}( j . template get < number_unsigned_t >()); 6384return combine ( type , h ); 6385} 6386 6387case BasicJsonType ::value_t:: number_float : 6388{ 6389const auto h = std:: hash < number_float_t > {}( j . template get < number_float_t >()); 6390return combine ( type , h ); 6391} 6392 6393case BasicJsonType ::value_t:: binary : 6394{ 6395auto seed = combine ( type , j . get_binary (). size ()); 6396const auto h = std:: hash < bool > {}( j . get_binary (). has_subtype ()); 6397seed = combine ( seed , h ); 6398seed = combine ( seed , static_cast <std:: size_t >( j . get_binary (). subtype ())); 6399for ( const auto byte : j . get_binary ()) 6400{ 6401seed = combine ( seed , std:: hash <std:: uint8_t > {}( byte )); 6402} 6403return seed ; 6404} 6405 6406default : // LCOV_EXCL_LINE 6407JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 6408return 0 ; // LCOV_EXCL_LINE 6409} 6410} 6411 6412} // namespace detail 6413NLOHMANN_JSON_NAMESPACE_END 6414 6415// #include <nlohmann/detail/input/binary_reader.hpp> 6416// __ _____ _____ _____ 6417// __| | __| | | | JSON for Modern C++ 6418// | | |__ | | | | | | version 3.12.0 6419// |_____|_____|_____|_|___| https://github.com/nlohmann/json 6420// 6421// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 6422// SPDX-License-Identifier: MIT 6423 6424 6425 6426#include <algorithm> // generate_n 6427#include <array> // array 6428#include <cmath> // ldexp 6429#include <cstddef> // size_t 6430#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 6431#include <cstdio> // snprintf 6432#include <cstring> // memcpy 6433#include <iterator> // back_inserter 6434#include <limits> // numeric_limits 6435#include <string> // char_traits, string 6436#include <utility> // make_pair, move 6437#include <vector> // vector 6438#ifdef __cpp_lib_byteswap 6439#include <bit> //byteswap 6440#endif 6441 6442// #include <nlohmann/detail/exceptions.hpp> 6443 6444// #include <nlohmann/detail/input/input_adapters.hpp> 6445// __ _____ _____ _____ 6446// __| | __| | | | JSON for Modern C++ 6447// | | |__ | | | | | | version 3.12.0 6448// |_____|_____|_____|_|___| https://github.com/nlohmann/json 6449// 6450// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 6451// SPDX-License-Identifier: MIT 6452 6453 6454 6455#include <array> // array 6456#include <cstddef> // size_t 6457#include <cstring> // strlen 6458#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next 6459#include <memory> // shared_ptr, make_shared, addressof 6460#include <numeric> // accumulate 6461#include <string> // string, char_traits 6462#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer 6463#include <utility> // pair, declval 6464 6465#ifndef JSON_NO_IO 6466#include <cstdio> // FILE * 6467#include <istream> // istream 6468#endif // JSON_NO_IO 6469 6470// #include <nlohmann/detail/exceptions.hpp> 6471 6472// #include <nlohmann/detail/iterators/iterator_traits.hpp> 6473 6474// #include <nlohmann/detail/macro_scope.hpp> 6475 6476// #include <nlohmann/detail/meta/type_traits.hpp> 6477 6478 6479NLOHMANN_JSON_NAMESPACE_BEGIN 6480namespace detail 6481{ 6482 6483/// the supported input formats 6484enum class input_format_t { json , cbor , msgpack , ubjson , bson , bjdata }; 6485 6486//////////////////// 6487// input adapters // 6488//////////////////// 6489 6490#ifndef JSON_NO_IO 6491/*! 6492Input adapter for stdio file access. This adapter read only 1 byte and do not use any 6493buffer. This adapter is a very low level adapter. 6494*/ 6495class file_input_adapter 6496{ 6497public : 6498using char_type = char ; 6499 6500JSON_HEDLEY_NON_NULL ( 2 ) 6501explicit file_input_adapter (std:: FILE * f ) noexcept 6502: m_file ( f ) 6503{ 6504JSON_ASSERT ( m_file != nullptr ); 6505} 6506 6507// make class move-only 6508file_input_adapter ( const file_input_adapter &) = delete ; 6509file_input_adapter ( file_input_adapter &&) noexcept = default ; 6510file_input_adapter & operator=( const file_input_adapter &) = delete ; 6511file_input_adapter & operator = ( file_input_adapter && ) = delete ; 6512~ file_input_adapter () = default; 6513 6514std:: char_traits < char > :: int_type get_character () noexcept 6515{ 6516return std:: fgetc (m_file); 6517} 6518 6519// returns the number of characters successfully read 6520template < class T > 6521std:: size_t get_elements ( T * dest, std:: size_t count = 1 ) 6522{ 6523return fread (dest, 1 , sizeof ( T ) * count, m_file); 6524} 6525 6526private : 6527/// the file pointer to read from 6528std:: FILE * m_file; 6529}; 6530 6531/*! 6532Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at 6533beginning of input. Does not support changing the underlying std::streambuf 6534in mid-input. Maintains underlying std::istream and std::streambuf to support 6535subsequent use of standard std::istream operations to process any input 6536characters following those used in parsing the JSON input. Clears the 6537std::istream flags; any input errors (e.g., EOF) will be detected by the first 6538subsequent call for input from the std::istream. 6539*/ 6540class input_stream_adapter 6541{ 6542public : 6543using char_type = char ; 6544 6545~input_stream_adapter() 6546{ 6547// clear stream flags; we use underlying streambuf I/O, do not 6548// maintain ifstream flags, except eof 6549if (is != nullptr ) 6550{ 6551is -> clear (is -> rdstate () & std::ios::eofbit); 6552} 6553} 6554 6555explicit input_stream_adapter (std:: istream & i) 6556: is ( & i), sb (i. rdbuf ()) 6557{} 6558 6559// delete because of pointer members 6560input_stream_adapter ( const input_stream_adapter & ) = delete ; 6561input_stream_adapter & operator = ( input_stream_adapter & ) = delete ; 6562input_stream_adapter & operator = ( input_stream_adapter && ) = delete ; 6563 6564input_stream_adapter ( input_stream_adapter && rhs) noexcept 6565: is (rhs. is ), sb (rhs. sb ) 6566{ 6567rhs. is = nullptr ; 6568rhs. sb = nullptr ; 6569} 6570 6571// std::istream/std::streambuf use std::char_traits<char>::to_int_type, to 6572// ensure that std::char_traits<char>::eof() and the character 0xFF do not 6573// end up as the same value, e.g. 0xFFFFFFFF. 6574std:: char_traits < char > :: int_type get_character () 6575{ 6576auto res = sb -> sbumpc (); 6577// set eof manually, as we don't use the istream interface. 6578if ( JSON_HEDLEY_UNLIKELY (res == std:: char_traits < char > ::eof())) 6579{ 6580is -> clear (is -> rdstate () | std::ios::eofbit); 6581} 6582return res; 6583} 6584 6585template < class T > 6586std:: size_t get_elements ( T * dest, std:: size_t count = 1 ) 6587{ 6588auto res = static_cast < std:: size_t > (sb -> sgetn ( reinterpret_cast < char *> (dest), static_cast < std:: streamsize > (count * sizeof ( T )))); 6589if ( JSON_HEDLEY_UNLIKELY (res < count * sizeof ( T ))) 6590{ 6591is -> clear (is -> rdstate () | std::ios::eofbit); 6592} 6593return res; 6594} 6595 6596private : 6597/// the associated input stream 6598std:: istream * is = nullptr ; 6599std:: streambuf * sb = nullptr ; 6600}; 6601#endif // JSON_NO_IO 6602 6603// General-purpose iterator-based adapter. It might not be as fast as 6604// theoretically possible for some containers, but it is extremely versatile. 6605template < typename IteratorType > 6606class iterator_input_adapter 6607{ 6608public : 6609using char_type = typename std:: iterator_traits < IteratorType > :: value_type ; 6610 6611iterator_input_adapter ( IteratorType first, IteratorType last) 6612: current (std:: move (first)), end (std:: move (last)) 6613{} 6614 6615typename char_traits < char_type > :: int_type get_character () 6616{ 6617if ( JSON_HEDLEY_LIKELY (current != end)) 6618{ 6619auto result = char_traits < char_type > :: to_int_type ( * current); 6620std:: advance (current, 1 ); 6621return result; 6622} 6623 6624return char_traits < char_type > :: eof (); 6625} 6626 6627// for general iterators, we cannot really do something better than falling back to processing the range one-by-one 6628template < class T > 6629std:: size_t get_elements ( T * dest, std:: size_t count = 1 ) 6630{ 6631auto * ptr = reinterpret_cast < char *> (dest); 6632for (std:: size_t read_index = 0 ; read_index < count * sizeof ( T ); ++ read_index) 6633{ 6634if ( JSON_HEDLEY_LIKELY (current != end)) 6635{ 6636ptr[read_index] = static_cast < char > ( * current); 6637std:: advance (current, 1 ); 6638} 6639else 6640{ 6641return read_index; 6642} 6643} 6644return count * sizeof ( T ); 6645} 6646 6647private : 6648IteratorType current ; 6649IteratorType end ; 6650 6651template < typename BaseInputAdapter , size_t T > 6652friend struct wide_string_input_helper ; 6653 6654bool empty () const 6655{ 6656return current == end; 6657} 6658}; 6659 6660template < typename BaseInputAdapter , size_t T > 6661struct wide_string_input_helper ; 6662 6663template < typename BaseInputAdapter > 6664struct wide_string_input_helper < BaseInputAdapter , 4 > 6665{ 6666// UTF-32 6667static void fill_buffer ( BaseInputAdapter & input, 6668std:: array < std:: char_traits < char > :: int_type , 4 >& utf8_bytes, 6669size_t & utf8_bytes_index, 6670size_t & utf8_bytes_filled) 6671{ 6672utf8_bytes_index = 0 ; 6673 6674if ( JSON_HEDLEY_UNLIKELY (input. empty ())) 6675{ 6676utf8_bytes[ 0 ] = std:: char_traits < char > ::eof(); 6677utf8_bytes_filled = 1 ; 6678} 6679else 6680{ 6681// get the current character 6682const auto wc = input. get_character (); 6683 6684// UTF-32 to UTF-8 encoding 6685if (wc < 0x80 ) 6686{ 6687utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > (wc); 6688utf8_bytes_filled = 1 ; 6689} 6690else if (wc <= 0x7FF ) 6691{ 6692utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > ( 0xC0u | (( static_cast < unsigned int > (wc) >> 6u ) & 0x1Fu )); 6693utf8_bytes[ 1 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | ( static_cast < unsigned int > (wc) & 0x3Fu )); 6694utf8_bytes_filled = 2 ; 6695} 6696else if (wc <= 0xFFFF ) 6697{ 6698utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > ( 0xE0u | (( static_cast < unsigned int > (wc) >> 12u ) & 0x0Fu )); 6699utf8_bytes[ 1 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | (( static_cast < unsigned int > (wc) >> 6u ) & 0x3Fu )); 6700utf8_bytes[ 2 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | ( static_cast < unsigned int > (wc) & 0x3Fu )); 6701utf8_bytes_filled = 3 ; 6702} 6703else if (wc <= 0x10FFFF ) 6704{ 6705utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > ( 0xF0u | (( static_cast < unsigned int > (wc) >> 18u ) & 0x07u )); 6706utf8_bytes[ 1 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | (( static_cast < unsigned int > (wc) >> 12u ) & 0x3Fu )); 6707utf8_bytes[ 2 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | (( static_cast < unsigned int > (wc) >> 6u ) & 0x3Fu )); 6708utf8_bytes[ 3 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | ( static_cast < unsigned int > (wc) & 0x3Fu )); 6709utf8_bytes_filled = 4 ; 6710} 6711else 6712{ 6713// unknown character 6714utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > (wc); 6715utf8_bytes_filled = 1 ; 6716} 6717} 6718} 6719}; 6720 6721template < typename BaseInputAdapter > 6722struct wide_string_input_helper < BaseInputAdapter , 2 > 6723{ 6724// UTF-16 6725static void fill_buffer ( BaseInputAdapter & input, 6726std:: array < std:: char_traits < char > :: int_type , 4 >& utf8_bytes, 6727size_t & utf8_bytes_index, 6728size_t & utf8_bytes_filled) 6729{ 6730utf8_bytes_index = 0 ; 6731 6732if ( JSON_HEDLEY_UNLIKELY (input. empty ())) 6733{ 6734utf8_bytes[ 0 ] = std:: char_traits < char > ::eof(); 6735utf8_bytes_filled = 1 ; 6736} 6737else 6738{ 6739// get the current character 6740const auto wc = input. get_character (); 6741 6742// UTF-16 to UTF-8 encoding 6743if (wc < 0x80 ) 6744{ 6745utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > (wc); 6746utf8_bytes_filled = 1 ; 6747} 6748else if (wc <= 0x7FF ) 6749{ 6750utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > ( 0xC0u | (( static_cast < unsigned int > (wc) >> 6u ))); 6751utf8_bytes[ 1 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | ( static_cast < unsigned int > (wc) & 0x3Fu )); 6752utf8_bytes_filled = 2 ; 6753} 6754else if ( 0xD800 > wc || wc >= 0xE000 ) 6755{ 6756utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > ( 0xE0u | (( static_cast < unsigned int > (wc) >> 12u ))); 6757utf8_bytes[ 1 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | (( static_cast < unsigned int > (wc) >> 6u ) & 0x3Fu )); 6758utf8_bytes[ 2 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | ( static_cast < unsigned int > (wc) & 0x3Fu )); 6759utf8_bytes_filled = 3 ; 6760} 6761else 6762{ 6763if ( JSON_HEDLEY_UNLIKELY (!input. empty ())) 6764{ 6765const auto wc2 = static_cast < unsigned int > (input. get_character ()); 6766const auto charcode = 0x10000u + ((( static_cast < unsigned int > (wc) & 0x3FFu ) << 10u ) | (wc2 & 0x3FFu )); 6767utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > ( 0xF0u | (charcode >> 18u )); 6768utf8_bytes[ 1 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | ((charcode >> 12u ) & 0x3Fu )); 6769utf8_bytes[ 2 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | ((charcode >> 6u ) & 0x3Fu )); 6770utf8_bytes[ 3 ] = static_cast < std:: char_traits < char > :: int_type > ( 0x80u | (charcode & 0x3Fu )); 6771utf8_bytes_filled = 4 ; 6772} 6773else 6774{ 6775utf8_bytes[ 0 ] = static_cast < std:: char_traits < char > :: int_type > (wc); 6776utf8_bytes_filled = 1 ; 6777} 6778} 6779} 6780} 6781}; 6782 6783// Wraps another input adapter to convert wide character types into individual bytes. 6784template < typename BaseInputAdapter , typename WideCharType > 6785class wide_string_input_adapter 6786{ 6787public : 6788using char_type = char ; 6789 6790wide_string_input_adapter ( BaseInputAdapter base) 6791: base_adapter (base) {} 6792 6793typename std:: char_traits < char > :: int_type get_character () noexcept 6794{ 6795// check if buffer needs to be filled 6796if (utf8_bytes_index == utf8_bytes_filled) 6797{ 6798fill_buffer < sizeof (WideCharType) > (); 6799 6800JSON_ASSERT (utf8_bytes_filled > 0 ); 6801JSON_ASSERT (utf8_bytes_index == 0 ); 6802} 6803 6804// use buffer 6805JSON_ASSERT (utf8_bytes_filled > 0 ); 6806JSON_ASSERT (utf8_bytes_index < utf8_bytes_filled); 6807return utf8_bytes[utf8_bytes_index ++ ]; 6808} 6809 6810// parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here 6811template < class T > 6812std:: size_t get_elements ( T * /*dest*/ , std:: size_t /*count*/ = 1 ) 6813{ 6814JSON_THROW (parse_error:: create ( 112 , 1 , "wide string type cannot be interpreted as binary data" , nullptr )); 6815} 6816 6817private : 6818BaseInputAdapter base_adapter ; 6819 6820template < size_t T > 6821void fill_buffer () 6822{ 6823wide_string_input_helper < BaseInputAdapter , T > :: fill_buffer (base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); 6824} 6825 6826/// a buffer for UTF-8 bytes 6827std:: array < std:: char_traits < char > :: int_type , 4 > utf8_bytes = {{ 0 , 0 , 0 , 0 }}; 6828 6829/// index to the utf8_codes array for the next valid byte 6830std:: size_t utf8_bytes_index = 0 ; 6831/// number of valid bytes in the utf8_codes array 6832std:: size_t utf8_bytes_filled = 0 ; 6833}; 6834 6835template < typename IteratorType , typename Enable = void > 6836struct iterator_input_adapter_factory 6837{ 6838using iterator_type = IteratorType ; 6839using char_type = typename std:: iterator_traits < iterator_type > :: value_type ; 6840using adapter_type = iterator_input_adapter < iterator_type > ; 6841 6842static adapter_type create ( IteratorType first, IteratorType last) 6843{ 6844return adapter_type (std:: move (first), std:: move (last)); 6845} 6846}; 6847 6848template < typename T > 6849struct is_iterator_of_multibyte 6850{ 6851using value_type = typename std:: iterator_traits < T > :: value_type ; 6852enum 6853{ 6854value = sizeof (value_type) > 1 6855}; 6856}; 6857 6858template < typename IteratorType > 6859struct iterator_input_adapter_factory < IteratorType , enable_if_t < is_iterator_of_multibyte < IteratorType > :: value >> 6860{ 6861using iterator_type = IteratorType ; 6862using char_type = typename std:: iterator_traits < iterator_type > :: value_type ; 6863using base_adapter_type = iterator_input_adapter < iterator_type > ; 6864using adapter_type = wide_string_input_adapter < base_adapter_type , char_type > ; 6865 6866static adapter_type create ( IteratorType first, IteratorType last) 6867{ 6868return adapter_type ( base_adapter_type (std:: move (first), std:: move (last))); 6869} 6870}; 6871 6872// General purpose iterator-based input 6873template < typename IteratorType > 6874typename iterator_input_adapter_factory < IteratorType > :: adapter_type input_adapter ( IteratorType first, IteratorType last) 6875{ 6876using factory_type = iterator_input_adapter_factory < IteratorType > ; 6877return factory_type:: create (first, last); 6878} 6879 6880// Convenience shorthand from container to iterator 6881// Enables ADL on begin(container) and end(container) 6882// Encloses the using declarations in namespace for not to leak them to outside scope 6883 6884namespace container_input_adapter_factory_impl 6885{ 6886 6887using std::begin; 6888using std::end; 6889 6890template < typename ContainerType , typename Enable = void > 6891struct container_input_adapter_factory {}; 6892 6893template < typename ContainerType > 6894struct container_input_adapter_factory < ContainerType , 6895void_t < decltype( begin (std:: declval < ContainerType > ()), end (std:: declval < ContainerType > ())) >> 6896{ 6897using adapter_type = decltype( input_adapter ( begin (std:: declval < ContainerType > ()), end (std:: declval < ContainerType > ()))); 6898 6899static adapter_type create ( const ContainerType & container) 6900{ 6901return input_adapter ( begin (container), end (container)); 6902} 6903}; 6904 6905} // namespace container_input_adapter_factory_impl 6906 6907template < typename ContainerType > 6908typename container_input_adapter_factory_impl:: container_input_adapter_factory < ContainerType > :: adapter_type input_adapter ( const ContainerType & container) 6909{ 6910return container_input_adapter_factory_impl:: container_input_adapter_factory < ContainerType > ::create(container); 6911} 6912 6913// specialization for std::string 6914using string_input_adapter_type = decltype( input_adapter (std:: declval < std:: string > ())); 6915 6916#ifndef JSON_NO_IO 6917// Special cases with fast paths 6918inline file_input_adapter input_adapter (std:: FILE * file) 6919{ 6920if (file == nullptr ) 6921{ 6922JSON_THROW (parse_error:: create ( 101 , 0 , "attempting to parse an empty input; check that your input string or stream contains the expected JSON" , nullptr )); 6923} 6924return file_input_adapter (file); 6925} 6926 6927inline input_stream_adapter input_adapter (std:: istream & stream) 6928{ 6929return input_stream_adapter (stream); 6930} 6931 6932inline input_stream_adapter input_adapter (std:: istream && stream) 6933{ 6934return input_stream_adapter (stream); 6935} 6936#endif // JSON_NO_IO 6937 6938using contiguous_bytes_input_adapter = decltype( input_adapter (std:: declval < const char *> (), std:: declval < const char *> ())); 6939 6940// Null-delimited strings, and the like. 6941template < typename CharT , 6942typename std:: enable_if < 6943std:: is_pointer < CharT > ::value && 6944!std:: is_array < CharT > ::value && 6945std:: is_integral < typename std:: remove_pointer < CharT > :: type > ::value && 6946sizeof ( typename std:: remove_pointer < CharT > :: type ) == 1 , 6947int > :: type = 0 > 6948contiguous_bytes_input_adapter input_adapter ( CharT b) 6949{ 6950if (b == nullptr ) 6951{ 6952JSON_THROW (parse_error:: create ( 101 , 0 , "attempting to parse an empty input; check that your input string or stream contains the expected JSON" , nullptr )); 6953} 6954auto length = std:: strlen ( reinterpret_cast < const char *> (b)); 6955const auto * ptr = reinterpret_cast < const char *> (b); 6956return input_adapter (ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck] 6957} 6958 6959template < typename T , std:: size_t N > 6960auto input_adapter ( T ( & array)[ N ]) -> decltype( input_adapter (array, array + N )) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 6961{ 6962return input_adapter (array, array + N ); 6963} 6964 6965// This class only handles inputs of input_buffer_adapter type. 6966// It's required so that expressions like {ptr, len} can be implicitly cast 6967// to the correct adapter. 6968class span_input_adapter 6969{ 6970public : 6971template < typename CharT , 6972typename std:: enable_if < 6973std:: is_pointer < CharT > ::value && 6974std:: is_integral < typename std:: remove_pointer < CharT > :: type > ::value && 6975sizeof ( typename std:: remove_pointer < CharT > :: type ) == 1 , 6976int > :: type = 0 > 6977span_input_adapter ( CharT b, std:: size_t l) 6978: ia ( reinterpret_cast < const char *> (b), reinterpret_cast < const char *> (b) + l) {} 6979 6980template < class IteratorType , 6981typename std:: enable_if < 6982std:: is_same < typename iterator_traits < IteratorType > :: iterator_category , std:: random_access_iterator_tag > :: value , 6983int > :: type = 0 > 6984span_input_adapter ( IteratorType first, IteratorType last) 6985: ia ( input_adapter (first, last)) {} 6986 6987contiguous_bytes_input_adapter && get () 6988{ 6989return std:: move (ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) 6990} 6991 6992private : 6993contiguous_bytes_input_adapter ia ; 6994}; 6995 6996} // namespace detail 6997NLOHMANN_JSON_NAMESPACE_END 6998 6999// #include <nlohmann/detail/input/json_sax.hpp> 7000// __ _____ _____ _____ 7001// __| | __| | | | JSON for Modern C++ 7002// | | |__ | | | | | | version 3.12.0 7003// |_____|_____|_____|_|___| https://github.com/nlohmann/json 7004// 7005// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 7006// SPDX-License-Identifier: MIT 7007 7008 7009 7010#include <cstddef> 7011#include <string> // string 7012#include <type_traits> // enable_if_t 7013#include <utility> // move 7014#include <vector> // vector 7015 7016// #include <nlohmann/detail/exceptions.hpp> 7017 7018// #include <nlohmann/detail/input/lexer.hpp> 7019// __ _____ _____ _____ 7020// __| | __| | | | JSON for Modern C++ 7021// | | |__ | | | | | | version 3.12.0 7022// |_____|_____|_____|_|___| https://github.com/nlohmann/json 7023// 7024// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 7025// SPDX-License-Identifier: MIT 7026 7027 7028 7029#include <array> // array 7030#include <clocale> // localeconv 7031#include <cstddef> // size_t 7032#include <cstdio> // snprintf 7033#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull 7034#include <initializer_list> // initializer_list 7035#include <string> // char_traits, string 7036#include <utility> // move 7037#include <vector> // vector 7038 7039// #include <nlohmann/detail/input/input_adapters.hpp> 7040 7041// #include <nlohmann/detail/input/position_t.hpp> 7042 7043// #include <nlohmann/detail/macro_scope.hpp> 7044 7045// #include <nlohmann/detail/meta/type_traits.hpp> 7046 7047 7048NLOHMANN_JSON_NAMESPACE_BEGIN 7049namespace detail 7050{ 7051 7052/////////// 7053// lexer // 7054/////////// 7055 7056template < typename BasicJsonType > 7057class lexer_base 7058{ 7059public : 7060/// token types for the parser 7061enum class token_type 7062{ 7063uninitialized, ///< indicating the scanner is uninitialized 7064literal_true, ///< the `true` literal 7065literal_false, ///< the `false` literal 7066literal_null, ///< the `null` literal 7067value_string, ///< a string -- use get_string() for actual value 7068value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value 7069value_integer, ///< a signed integer -- use get_number_integer() for actual value 7070value_float, ///< an floating point number -- use get_number_float() for actual value 7071begin_array, ///< the character for array begin `[` 7072begin_object, ///< the character for object begin `{` 7073end_array, ///< the character for array end `]` 7074end_object, ///< the character for object end `}` 7075name_separator, ///< the name separator `:` 7076value_separator, ///< the value separator `,` 7077parse_error, ///< indicating a parse error 7078end_of_input, ///< indicating the end of the input buffer 7079literal_or_value ///< a literal or the begin of a value (only for diagnostics) 7080}; 7081 7082/// return name of values of type token_type (only used for errors) 7083JSON_HEDLEY_RETURNS_NON_NULL 7084JSON_HEDLEY_CONST 7085static const char * token_type_name ( const token_type t) noexcept 7086{ 7087switch (t) 7088{ 7089case token_type::uninitialized: 7090return "<uninitialized>" ; 7091case token_type::literal_true: 7092return "true literal" ; 7093case token_type::literal_false: 7094return "false literal" ; 7095case token_type::literal_null: 7096return "null literal" ; 7097case token_type::value_string: 7098return "string literal" ; 7099case token_type::value_unsigned: 7100case token_type::value_integer: 7101case token_type::value_float: 7102return "number literal" ; 7103case token_type::begin_array: 7104return "'['" ; 7105case token_type::begin_object: 7106return "'{'" ; 7107case token_type::end_array: 7108return "']'" ; 7109case token_type::end_object: 7110return "'}'" ; 7111case token_type::name_separator: 7112return "':'" ; 7113case token_type::value_separator: 7114return "','" ; 7115case token_type::parse_error: 7116return "<parse error>" ; 7117case token_type::end_of_input: 7118return "end of input" ; 7119case token_type::literal_or_value: 7120return "'[', '{', or a literal" ; 7121// LCOV_EXCL_START 7122default : // catch non-enum values 7123return "unknown token" ; 7124// LCOV_EXCL_STOP 7125} 7126} 7127}; 7128/*! 7129@brief lexical analysis 7130 7131This class organizes the lexical analysis during JSON deserialization. 7132*/ 7133template < typename BasicJsonType , typename InputAdapterType > 7134class lexer : public lexer_base < BasicJsonType > 7135{ 7136using number_integer_t = typename BasicJsonType :: number_integer_t ; 7137using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 7138using number_float_t = typename BasicJsonType :: number_float_t ; 7139using string_t = typename BasicJsonType :: string_t ; 7140using char_type = typename InputAdapterType :: char_type ; 7141using char_int_type = typename char_traits < char_type > :: int_type ; 7142 7143public : 7144using token_type = typename lexer_base < BasicJsonType > :: token_type ; 7145 7146explicit lexer ( InputAdapterType && adapter, bool ignore_comments_ = false) noexcept 7147: ia (std:: move (adapter)) 7148, ignore_comments (ignore_comments_) 7149, decimal_point_char ( static_cast < char_int_type > ( get_decimal_point ())) 7150{} 7151 7152// delete because of pointer members 7153lexer ( const lexer & ) = delete ; 7154lexer ( lexer && ) = default ; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7155lexer & operator = ( lexer & ) = delete ; 7156lexer & operator = ( lexer && ) = default ; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7157~lexer() = default ; 7158 7159private : 7160///////////////////// 7161// locales 7162///////////////////// 7163 7164/// return the locale-dependent decimal point 7165JSON_HEDLEY_PURE 7166static char get_decimal_point () noexcept 7167{ 7168const auto * loc = localeconv (); 7169JSON_ASSERT (loc != nullptr ); 7170return (loc -> decimal_point == nullptr ) ? '.' : * (loc -> decimal_point ); 7171} 7172 7173///////////////////// 7174// scan functions 7175///////////////////// 7176 7177/*! 7178@brief get codepoint from 4 hex characters following `\u` 7179 7180For input "\u c1 c2 c3 c4" the codepoint is: 7181(c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 7182= (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) 7183 7184Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' 7185must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The 7186conversion is done by subtracting the offset (0x30, 0x37, and 0x57) 7187between the ASCII value of the character and the desired integer value. 7188 7189@return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or 7190non-hex character) 7191*/ 7192int get_codepoint () 7193{ 7194// this function only makes sense after reading `\u` 7195JSON_ASSERT (current == 'u' ); 7196int codepoint = 0 ; 7197 7198const auto factors = { 12u , 8u , 4u , 0u }; 7199for ( const auto factor : factors) 7200{ 7201get (); 7202 7203if (current >= '0' && current <= '9' ) 7204{ 7205codepoint += static_cast < int > (( static_cast < unsigned int > (current) - 0x30u ) << factor); 7206} 7207else if (current >= 'A' && current <= 'F' ) 7208{ 7209codepoint += static_cast < int > (( static_cast < unsigned int > (current) - 0x37u ) << factor); 7210} 7211else if (current >= 'a' && current <= 'f' ) 7212{ 7213codepoint += static_cast < int > (( static_cast < unsigned int > (current) - 0x57u ) << factor); 7214} 7215else 7216{ 7217return -1 ; 7218} 7219} 7220 7221JSON_ASSERT ( 0x0000 <= codepoint && codepoint <= 0xFFFF ); 7222return codepoint; 7223} 7224 7225/*! 7226@brief check if the next byte(s) are inside a given range 7227 7228Adds the current byte and, for each passed range, reads a new byte and 7229checks if it is inside the range. If a violation was detected, set up an 7230error message and return false. Otherwise, return true. 7231 7232@param[in] ranges list of integers; interpreted as list of pairs of 7233inclusive lower and upper bound, respectively 7234 7235@pre The passed list @a ranges must have 2, 4, or 6 elements; that is, 72361, 2, or 3 pairs. This precondition is enforced by an assertion. 7237 7238@return true if and only if no range violation was detected 7239*/ 7240bool next_byte_in_range (std:: initializer_list < char_int_type > ranges) 7241{ 7242JSON_ASSERT (ranges. size () == 2 || ranges. size () == 4 || ranges. size () == 6 ); 7243add (current); 7244 7245for ( auto range = ranges. begin (); range != ranges. end (); ++ range) 7246{ 7247get (); 7248if ( JSON_HEDLEY_LIKELY ( * range <= current && current <= * ( ++ range))) // NOLINT(bugprone-inc-dec-in-conditions) 7249{ 7250add (current); 7251} 7252else 7253{ 7254error_message = "invalid string: ill-formed UTF-8 byte" ; 7255return false; 7256} 7257} 7258 7259return true; 7260} 7261 7262/*! 7263@brief scan a string literal 7264 7265This function scans a string according to Sect. 7 of RFC 8259. While 7266scanning, bytes are escaped and copied into buffer token_buffer. Then the 7267function returns successfully, token_buffer is *not* null-terminated (as it 7268may contain \0 bytes), and token_buffer.size() is the number of bytes in the 7269string. 7270 7271@return token_type::value_string if string could be successfully scanned, 7272token_type::parse_error otherwise 7273 7274@note In case of errors, variable error_message contains a textual 7275description. 7276*/ 7277token_type scan_string () 7278{ 7279// reset token_buffer (ignore opening quote) 7280reset (); 7281 7282// we entered the function by reading an open quote 7283JSON_ASSERT (current == '\"' ); 7284 7285while (true) 7286{ 7287// get next character 7288switch ( get ()) 7289{ 7290// end of file while parsing string 7291case char_traits < char_type > :: eof (): 7292{ 7293error_message = "invalid string: missing closing quote" ; 7294return token_type::parse_error; 7295} 7296 7297// closing quote 7298case '\"' : 7299{ 7300return token_type::value_string; 7301} 7302 7303// escapes 7304case '\\' : 7305{ 7306switch ( get ()) 7307{ 7308// quotation mark 7309case '\"' : 7310add ( '\"' ); 7311break ; 7312// reverse solidus 7313case '\\' : 7314add ( '\\' ); 7315break ; 7316// solidus 7317case '/' : 7318add ( '/' ); 7319break ; 7320// backspace 7321case 'b' : 7322add ( '\b' ); 7323break ; 7324// form feed 7325case 'f' : 7326add ( '\f' ); 7327break ; 7328// line feed 7329case 'n' : 7330add ( '\n' ); 7331break ; 7332// carriage return 7333case 'r' : 7334add ( '\r' ); 7335break ; 7336// tab 7337case 't' : 7338add ( '\t' ); 7339break ; 7340 7341// unicode escapes 7342case 'u' : 7343{ 7344const int codepoint1 = get_codepoint (); 7345int codepoint = codepoint1; // start with codepoint1 7346 7347if ( JSON_HEDLEY_UNLIKELY (codepoint1 == -1 )) 7348{ 7349error_message = "invalid string: '\\u' must be followed by 4 hex digits" ; 7350return token_type::parse_error; 7351} 7352 7353// check if code point is a high surrogate 7354if ( 0xD800 <= codepoint1 && codepoint1 <= 0xDBFF ) 7355{ 7356// expect next \uxxxx entry 7357if ( JSON_HEDLEY_LIKELY ( get () == '\\' && get () == 'u' )) 7358{ 7359const int codepoint2 = get_codepoint (); 7360 7361if ( JSON_HEDLEY_UNLIKELY (codepoint2 == -1 )) 7362{ 7363error_message = "invalid string: '\\u' must be followed by 4 hex digits" ; 7364return token_type::parse_error; 7365} 7366 7367// check if codepoint2 is a low surrogate 7368if ( JSON_HEDLEY_LIKELY ( 0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF )) 7369{ 7370// overwrite codepoint 7371codepoint = static_cast < int > ( 7372// high surrogate occupies the most significant 22 bits 7373( static_cast < unsigned int > (codepoint1) << 10u ) 7374// low surrogate occupies the least significant 15 bits 7375+ static_cast < unsigned int > (codepoint2) 7376// there is still the 0xD800, 0xDC00 and 0x10000 noise 7377// in the result, so we have to subtract with: 7378// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 7379- 0x35FDC00u ); 7380} 7381else 7382{ 7383error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF" ; 7384return token_type::parse_error; 7385} 7386} 7387else 7388{ 7389error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF" ; 7390return token_type::parse_error; 7391} 7392} 7393else 7394{ 7395if ( JSON_HEDLEY_UNLIKELY ( 0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF )) 7396{ 7397error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF" ; 7398return token_type::parse_error; 7399} 7400} 7401 7402// result of the above calculation yields a proper codepoint 7403JSON_ASSERT ( 0x00 <= codepoint && codepoint <= 0x10FFFF ); 7404 7405// translate codepoint into bytes 7406if (codepoint < 0x80 ) 7407{ 7408// 1-byte characters: 0xxxxxxx (ASCII) 7409add ( static_cast < char_int_type > (codepoint)); 7410} 7411else if (codepoint <= 0x7FF ) 7412{ 7413// 2-byte characters: 110xxxxx 10xxxxxx 7414add ( static_cast < char_int_type > ( 0xC0u | ( static_cast < unsigned int > (codepoint) >> 6u ))); 7415add ( static_cast < char_int_type > ( 0x80u | ( static_cast < unsigned int > (codepoint) & 0x3Fu ))); 7416} 7417else if (codepoint <= 0xFFFF ) 7418{ 7419// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx 7420add ( static_cast < char_int_type > ( 0xE0u | ( static_cast < unsigned int > (codepoint) >> 12u ))); 7421add ( static_cast < char_int_type > ( 0x80u | (( static_cast < unsigned int > (codepoint) >> 6u ) & 0x3Fu ))); 7422add ( static_cast < char_int_type > ( 0x80u | ( static_cast < unsigned int > (codepoint) & 0x3Fu ))); 7423} 7424else 7425{ 7426// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 7427add ( static_cast < char_int_type > ( 0xF0u | ( static_cast < unsigned int > (codepoint) >> 18u ))); 7428add ( static_cast < char_int_type > ( 0x80u | (( static_cast < unsigned int > (codepoint) >> 12u ) & 0x3Fu ))); 7429add ( static_cast < char_int_type > ( 0x80u | (( static_cast < unsigned int > (codepoint) >> 6u ) & 0x3Fu ))); 7430add ( static_cast < char_int_type > ( 0x80u | ( static_cast < unsigned int > (codepoint) & 0x3Fu ))); 7431} 7432 7433break ; 7434} 7435 7436// other characters after escape 7437default : 7438error_message = "invalid string: forbidden character after backslash" ; 7439return token_type::parse_error; 7440} 7441 7442break ; 7443} 7444 7445// invalid control characters 7446case 0x00 : 7447{ 7448error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000" ; 7449return token_type::parse_error; 7450} 7451 7452case 0x01 : 7453{ 7454error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001" ; 7455return token_type::parse_error; 7456} 7457 7458case 0x02 : 7459{ 7460error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002" ; 7461return token_type::parse_error; 7462} 7463 7464case 0x03 : 7465{ 7466error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003" ; 7467return token_type::parse_error; 7468} 7469 7470case 0x04 : 7471{ 7472error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004" ; 7473return token_type::parse_error; 7474} 7475 7476case 0x05 : 7477{ 7478error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005" ; 7479return token_type::parse_error; 7480} 7481 7482case 0x06 : 7483{ 7484error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006" ; 7485return token_type::parse_error; 7486} 7487 7488case 0x07 : 7489{ 7490error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007" ; 7491return token_type::parse_error; 7492} 7493 7494case 0x08 : 7495{ 7496error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b" ; 7497return token_type::parse_error; 7498} 7499 7500case 0x09 : 7501{ 7502error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t" ; 7503return token_type::parse_error; 7504} 7505 7506case 0x0A : 7507{ 7508error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n" ; 7509return token_type::parse_error; 7510} 7511 7512case 0x0B : 7513{ 7514error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B" ; 7515return token_type::parse_error; 7516} 7517 7518case 0x0C : 7519{ 7520error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f" ; 7521return token_type::parse_error; 7522} 7523 7524case 0x0D : 7525{ 7526error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r" ; 7527return token_type::parse_error; 7528} 7529 7530case 0x0E : 7531{ 7532error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E" ; 7533return token_type::parse_error; 7534} 7535 7536case 0x0F : 7537{ 7538error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F" ; 7539return token_type::parse_error; 7540} 7541 7542case 0x10 : 7543{ 7544error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010" ; 7545return token_type::parse_error; 7546} 7547 7548case 0x11 : 7549{ 7550error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011" ; 7551return token_type::parse_error; 7552} 7553 7554case 0x12 : 7555{ 7556error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012" ; 7557return token_type::parse_error; 7558} 7559 7560case 0x13 : 7561{ 7562error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013" ; 7563return token_type::parse_error; 7564} 7565 7566case 0x14 : 7567{ 7568error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014" ; 7569return token_type::parse_error; 7570} 7571 7572case 0x15 : 7573{ 7574error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015" ; 7575return token_type::parse_error; 7576} 7577 7578case 0x16 : 7579{ 7580error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016" ; 7581return token_type::parse_error; 7582} 7583 7584case 0x17 : 7585{ 7586error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017" ; 7587return token_type::parse_error; 7588} 7589 7590case 0x18 : 7591{ 7592error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018" ; 7593return token_type::parse_error; 7594} 7595 7596case 0x19 : 7597{ 7598error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019" ; 7599return token_type::parse_error; 7600} 7601 7602case 0x1A : 7603{ 7604error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A" ; 7605return token_type::parse_error; 7606} 7607 7608case 0x1B : 7609{ 7610error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B" ; 7611return token_type::parse_error; 7612} 7613 7614case 0x1C : 7615{ 7616error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C" ; 7617return token_type::parse_error; 7618} 7619 7620case 0x1D : 7621{ 7622error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D" ; 7623return token_type::parse_error; 7624} 7625 7626case 0x1E : 7627{ 7628error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E" ; 7629return token_type::parse_error; 7630} 7631 7632case 0x1F : 7633{ 7634error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F" ; 7635return token_type::parse_error; 7636} 7637 7638// U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) 7639case 0x20 : 7640case 0x21 : 7641case 0x23 : 7642case 0x24 : 7643case 0x25 : 7644case 0x26 : 7645case 0x27 : 7646case 0x28 : 7647case 0x29 : 7648case 0x2A : 7649case 0x2B : 7650case 0x2C : 7651case 0x2D : 7652case 0x2E : 7653case 0x2F : 7654case 0x30 : 7655case 0x31 : 7656case 0x32 : 7657case 0x33 : 7658case 0x34 : 7659case 0x35 : 7660case 0x36 : 7661case 0x37 : 7662case 0x38 : 7663case 0x39 : 7664case 0x3A : 7665case 0x3B : 7666case 0x3C : 7667case 0x3D : 7668case 0x3E : 7669case 0x3F : 7670case 0x40 : 7671case 0x41 : 7672case 0x42 : 7673case 0x43 : 7674case 0x44 : 7675case 0x45 : 7676case 0x46 : 7677case 0x47 : 7678case 0x48 : 7679case 0x49 : 7680case 0x4A : 7681case 0x4B : 7682case 0x4C : 7683case 0x4D : 7684case 0x4E : 7685case 0x4F : 7686case 0x50 : 7687case 0x51 : 7688case 0x52 : 7689case 0x53 : 7690case 0x54 : 7691case 0x55 : 7692case 0x56 : 7693case 0x57 : 7694case 0x58 : 7695case 0x59 : 7696case 0x5A : 7697case 0x5B : 7698case 0x5D : 7699case 0x5E : 7700case 0x5F : 7701case 0x60 : 7702case 0x61 : 7703case 0x62 : 7704case 0x63 : 7705case 0x64 : 7706case 0x65 : 7707case 0x66 : 7708case 0x67 : 7709case 0x68 : 7710case 0x69 : 7711case 0x6A : 7712case 0x6B : 7713case 0x6C : 7714case 0x6D : 7715case 0x6E : 7716case 0x6F : 7717case 0x70 : 7718case 0x71 : 7719case 0x72 : 7720case 0x73 : 7721case 0x74 : 7722case 0x75 : 7723case 0x76 : 7724case 0x77 : 7725case 0x78 : 7726case 0x79 : 7727case 0x7A : 7728case 0x7B : 7729case 0x7C : 7730case 0x7D : 7731case 0x7E : 7732case 0x7F : 7733{ 7734add (current); 7735break ; 7736} 7737 7738// U+0080..U+07FF: bytes C2..DF 80..BF 7739case 0xC2 : 7740case 0xC3 : 7741case 0xC4 : 7742case 0xC5 : 7743case 0xC6 : 7744case 0xC7 : 7745case 0xC8 : 7746case 0xC9 : 7747case 0xCA : 7748case 0xCB : 7749case 0xCC : 7750case 0xCD : 7751case 0xCE : 7752case 0xCF : 7753case 0xD0 : 7754case 0xD1 : 7755case 0xD2 : 7756case 0xD3 : 7757case 0xD4 : 7758case 0xD5 : 7759case 0xD6 : 7760case 0xD7 : 7761case 0xD8 : 7762case 0xD9 : 7763case 0xDA : 7764case 0xDB : 7765case 0xDC : 7766case 0xDD : 7767case 0xDE : 7768case 0xDF : 7769{ 7770if ( JSON_HEDLEY_UNLIKELY (! next_byte_in_range ({ 0x80 , 0xBF }))) 7771{ 7772return token_type::parse_error; 7773} 7774break ; 7775} 7776 7777// U+0800..U+0FFF: bytes E0 A0..BF 80..BF 7778case 0xE0 : 7779{ 7780if ( JSON_HEDLEY_UNLIKELY (!( next_byte_in_range ({ 0xA0 , 0xBF , 0x80 , 0xBF })))) 7781{ 7782return token_type::parse_error; 7783} 7784break ; 7785} 7786 7787// U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF 7788// U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF 7789case 0xE1 : 7790case 0xE2 : 7791case 0xE3 : 7792case 0xE4 : 7793case 0xE5 : 7794case 0xE6 : 7795case 0xE7 : 7796case 0xE8 : 7797case 0xE9 : 7798case 0xEA : 7799case 0xEB : 7800case 0xEC : 7801case 0xEE : 7802case 0xEF : 7803{ 7804if ( JSON_HEDLEY_UNLIKELY (!( next_byte_in_range ({ 0x80 , 0xBF , 0x80 , 0xBF })))) 7805{ 7806return token_type::parse_error; 7807} 7808break ; 7809} 7810 7811// U+D000..U+D7FF: bytes ED 80..9F 80..BF 7812case 0xED : 7813{ 7814if ( JSON_HEDLEY_UNLIKELY (!( next_byte_in_range ({ 0x80 , 0x9F , 0x80 , 0xBF })))) 7815{ 7816return token_type::parse_error; 7817} 7818break ; 7819} 7820 7821// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF 7822case 0xF0 : 7823{ 7824if ( JSON_HEDLEY_UNLIKELY (!( next_byte_in_range ({ 0x90 , 0xBF , 0x80 , 0xBF , 0x80 , 0xBF })))) 7825{ 7826return token_type::parse_error; 7827} 7828break ; 7829} 7830 7831// U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF 7832case 0xF1 : 7833case 0xF2 : 7834case 0xF3 : 7835{ 7836if ( JSON_HEDLEY_UNLIKELY (!( next_byte_in_range ({ 0x80 , 0xBF , 0x80 , 0xBF , 0x80 , 0xBF })))) 7837{ 7838return token_type::parse_error; 7839} 7840break ; 7841} 7842 7843// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 7844case 0xF4 : 7845{ 7846if ( JSON_HEDLEY_UNLIKELY (!( next_byte_in_range ({ 0x80 , 0x8F , 0x80 , 0xBF , 0x80 , 0xBF })))) 7847{ 7848return token_type::parse_error; 7849} 7850break ; 7851} 7852 7853// remaining bytes (80..C1 and F5..FF) are ill-formed 7854default : 7855{ 7856error_message = "invalid string: ill-formed UTF-8 byte" ; 7857return token_type::parse_error; 7858} 7859} 7860} 7861} 7862 7863/*! 7864* @brief scan a comment 7865* @return whether comment could be scanned successfully 7866*/ 7867bool scan_comment () 7868{ 7869switch ( get ()) 7870{ 7871// single-line comments skip input until a newline or EOF is read 7872case '/' : 7873{ 7874while (true) 7875{ 7876switch ( get ()) 7877{ 7878case '\n' : 7879case '\r' : 7880case char_traits < char_type > :: eof (): 7881case '\0' : 7882return true; 7883 7884default : 7885break ; 7886} 7887} 7888} 7889 7890// multi-line comments skip input until */ is read 7891case '*' : 7892{ 7893while (true) 7894{ 7895switch ( get ()) 7896{ 7897case char_traits < char_type > :: eof (): 7898case '\0' : 7899{ 7900error_message = "invalid comment; missing closing '*/'" ; 7901return false; 7902} 7903 7904case '*' : 7905{ 7906switch ( get ()) 7907{ 7908case '/' : 7909return true; 7910 7911default : 7912{ 7913unget (); 7914continue ; 7915} 7916} 7917} 7918 7919default : 7920continue ; 7921} 7922} 7923} 7924 7925// unexpected character after reading '/' 7926default : 7927{ 7928error_message = "invalid comment; expecting '/' or '*' after '/'" ; 7929return false; 7930} 7931} 7932} 7933 7934JSON_HEDLEY_NON_NULL ( 2 ) 7935static void strtof ( float & f, const char * str, char ** endptr) noexcept 7936{ 7937f = std:: strtof (str, endptr); 7938} 7939 7940JSON_HEDLEY_NON_NULL ( 2 ) 7941static void strtof ( double & f, const char * str, char ** endptr) noexcept 7942{ 7943f = std:: strtod (str, endptr); 7944} 7945 7946JSON_HEDLEY_NON_NULL ( 2 ) 7947static void strtof ( long double & f, const char * str, char ** endptr) noexcept 7948{ 7949f = std:: strtold (str, endptr); 7950} 7951 7952/*! 7953@brief scan a number literal 7954 7955This function scans a string according to Sect. 6 of RFC 8259. 7956 7957The function is realized with a deterministic finite state machine derived 7958from the grammar described in RFC 8259. Starting in state "init", the 7959input is read and used to determined the next state. Only state "done" 7960accepts the number. State "error" is a trap state to model errors. In the 7961table below, "anything" means any character but the ones listed before. 7962 7963state | 0 | 1-9 | e E | + | - | . | anything 7964---------|----------|----------|----------|---------|---------|----------|----------- 7965init | zero | any1 | [error] | [error] | minus | [error] | [error] 7966minus | zero | any1 | [error] | [error] | [error] | [error] | [error] 7967zero | done | done | exponent | done | done | decimal1 | done 7968any1 | any1 | any1 | exponent | done | done | decimal1 | done 7969decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] 7970decimal2 | decimal2 | decimal2 | exponent | done | done | done | done 7971exponent | any2 | any2 | [error] | sign | sign | [error] | [error] 7972sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] 7973any2 | any2 | any2 | done | done | done | done | done 7974 7975The state machine is realized with one label per state (prefixed with 7976"scan_number_") and `goto` statements between them. The state machine 7977contains cycles, but any cycle can be left when EOF is read. Therefore, 7978the function is guaranteed to terminate. 7979 7980During scanning, the read bytes are stored in token_buffer. This string is 7981then converted to a signed integer, an unsigned integer, or a 7982floating-point number. 7983 7984@return token_type::value_unsigned, token_type::value_integer, or 7985token_type::value_float if number could be successfully scanned, 7986token_type::parse_error otherwise 7987 7988@note The scanner is independent of the current locale. Internally, the 7989locale's decimal point is used instead of `.` to work with the 7990locale-dependent converters. 7991*/ 7992token_type scan_number () // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated. 7993{ 7994// reset token_buffer to store the number's bytes 7995reset (); 7996 7997// the type of the parsed number; initially set to unsigned; will be 7998// changed if minus sign, decimal point or exponent is read 7999token_type number_type = token_type::value_unsigned; 8000 8001// state (init): we just found out we need to scan a number 8002switch (current) 8003{ 8004case '-' : 8005{ 8006add (current); 8007goto scan_number_minus ; 8008} 8009 8010case '0' : 8011{ 8012add (current); 8013goto scan_number_zero ; 8014} 8015 8016case '1' : 8017case '2' : 8018case '3' : 8019case '4' : 8020case '5' : 8021case '6' : 8022case '7' : 8023case '8' : 8024case '9' : 8025{ 8026add (current); 8027goto scan_number_any1 ; 8028} 8029 8030// all other characters are rejected outside scan_number() 8031default : // LCOV_EXCL_LINE 8032JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 8033} 8034 8035scan_number_minus : 8036// state: we just parsed a leading minus sign 8037number_type = token_type::value_integer; 8038switch ( get ()) 8039{ 8040case '0' : 8041{ 8042add (current); 8043goto scan_number_zero ; 8044} 8045 8046case '1' : 8047case '2' : 8048case '3' : 8049case '4' : 8050case '5' : 8051case '6' : 8052case '7' : 8053case '8' : 8054case '9' : 8055{ 8056add (current); 8057goto scan_number_any1 ; 8058} 8059 8060default : 8061{ 8062error_message = "invalid number; expected digit after '-'" ; 8063return token_type::parse_error; 8064} 8065} 8066 8067scan_number_zero : 8068// state: we just parse a zero (maybe with a leading minus sign) 8069switch ( get ()) 8070{ 8071case '.' : 8072{ 8073add (decimal_point_char); 8074decimal_point_position = token_buffer. size () - 1 ; 8075goto scan_number_decimal1 ; 8076} 8077 8078case 'e' : 8079case 'E' : 8080{ 8081add (current); 8082goto scan_number_exponent ; 8083} 8084 8085default : 8086goto scan_number_done ; 8087} 8088 8089scan_number_any1 : 8090// state: we just parsed a number 0-9 (maybe with a leading minus sign) 8091switch ( get ()) 8092{ 8093case '0' : 8094case '1' : 8095case '2' : 8096case '3' : 8097case '4' : 8098case '5' : 8099case '6' : 8100case '7' : 8101case '8' : 8102case '9' : 8103{ 8104add (current); 8105goto scan_number_any1 ; 8106} 8107 8108case '.' : 8109{ 8110add (decimal_point_char); 8111decimal_point_position = token_buffer. size () - 1 ; 8112goto scan_number_decimal1 ; 8113} 8114 8115case 'e' : 8116case 'E' : 8117{ 8118add (current); 8119goto scan_number_exponent ; 8120} 8121 8122default : 8123goto scan_number_done ; 8124} 8125 8126scan_number_decimal1 : 8127// state: we just parsed a decimal point 8128number_type = token_type::value_float; 8129switch ( get ()) 8130{ 8131case '0' : 8132case '1' : 8133case '2' : 8134case '3' : 8135case '4' : 8136case '5' : 8137case '6' : 8138case '7' : 8139case '8' : 8140case '9' : 8141{ 8142add (current); 8143goto scan_number_decimal2 ; 8144} 8145 8146default : 8147{ 8148error_message = "invalid number; expected digit after '.'" ; 8149return token_type::parse_error; 8150} 8151} 8152 8153scan_number_decimal2 : 8154// we just parsed at least one number after a decimal point 8155switch ( get ()) 8156{ 8157case '0' : 8158case '1' : 8159case '2' : 8160case '3' : 8161case '4' : 8162case '5' : 8163case '6' : 8164case '7' : 8165case '8' : 8166case '9' : 8167{ 8168add (current); 8169goto scan_number_decimal2 ; 8170} 8171 8172case 'e' : 8173case 'E' : 8174{ 8175add (current); 8176goto scan_number_exponent ; 8177} 8178 8179default : 8180goto scan_number_done ; 8181} 8182 8183scan_number_exponent : 8184// we just parsed an exponent 8185number_type = token_type::value_float; 8186switch ( get ()) 8187{ 8188case '+' : 8189case '-' : 8190{ 8191add (current); 8192goto scan_number_sign ; 8193} 8194 8195case '0' : 8196case '1' : 8197case '2' : 8198case '3' : 8199case '4' : 8200case '5' : 8201case '6' : 8202case '7' : 8203case '8' : 8204case '9' : 8205{ 8206add (current); 8207goto scan_number_any2 ; 8208} 8209 8210default : 8211{ 8212error_message = 8213"invalid number; expected '+', '-', or digit after exponent" ; 8214return token_type::parse_error; 8215} 8216} 8217 8218scan_number_sign : 8219// we just parsed an exponent sign 8220switch ( get ()) 8221{ 8222case '0' : 8223case '1' : 8224case '2' : 8225case '3' : 8226case '4' : 8227case '5' : 8228case '6' : 8229case '7' : 8230case '8' : 8231case '9' : 8232{ 8233add (current); 8234goto scan_number_any2 ; 8235} 8236 8237default : 8238{ 8239error_message = "invalid number; expected digit after exponent sign" ; 8240return token_type::parse_error; 8241} 8242} 8243 8244scan_number_any2 : 8245// we just parsed a number after the exponent or exponent sign 8246switch ( get ()) 8247{ 8248case '0' : 8249case '1' : 8250case '2' : 8251case '3' : 8252case '4' : 8253case '5' : 8254case '6' : 8255case '7' : 8256case '8' : 8257case '9' : 8258{ 8259add (current); 8260goto scan_number_any2 ; 8261} 8262 8263default : 8264goto scan_number_done ; 8265} 8266 8267scan_number_done : 8268// unget the character after the number (we only read it to know that 8269// we are done scanning a number) 8270unget (); 8271 8272char * endptr = nullptr ; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8273errno = 0 ; 8274 8275// try to parse integers first and fall back to floats 8276if (number_type == token_type::value_unsigned) 8277{ 8278const auto x = std:: strtoull (token_buffer. data (), & endptr, 10 ); 8279 8280// we checked the number format before 8281JSON_ASSERT (endptr == token_buffer. data () + token_buffer. size ()); 8282 8283if (errno != ERANGE ) 8284{ 8285value_unsigned = static_cast < number_unsigned_t > (x); 8286if (value_unsigned == x) 8287{ 8288return token_type::value_unsigned; 8289} 8290} 8291} 8292else if (number_type == token_type::value_integer) 8293{ 8294const auto x = std:: strtoll (token_buffer. data (), & endptr, 10 ); 8295 8296// we checked the number format before 8297JSON_ASSERT (endptr == token_buffer. data () + token_buffer. size ()); 8298 8299if (errno != ERANGE ) 8300{ 8301value_integer = static_cast < number_integer_t > (x); 8302if (value_integer == x) 8303{ 8304return token_type::value_integer; 8305} 8306} 8307} 8308 8309// this code is reached if we parse a floating-point number or if an 8310// integer conversion above failed 8311strtof (value_float, token_buffer. data (), & endptr); 8312 8313// we checked the number format before 8314JSON_ASSERT (endptr == token_buffer. data () + token_buffer. size ()); 8315 8316return token_type::value_float; 8317} 8318 8319/*! 8320@param[in] literal_text the literal text to expect 8321@param[in] length the length of the passed literal text 8322@param[in] return_type the token type to return on success 8323*/ 8324JSON_HEDLEY_NON_NULL ( 2 ) 8325token_type scan_literal ( const char_type * literal_text, const std:: size_t length, 8326token_type return_type) 8327{ 8328JSON_ASSERT ( char_traits < char_type > :: to_char_type (current) == literal_text[ 0 ]); 8329for (std:: size_t i = 1 ; i < length; ++ i) 8330{ 8331if ( JSON_HEDLEY_UNLIKELY ( char_traits < char_type > :: to_char_type ( get ()) != literal_text[i])) 8332{ 8333error_message = "invalid literal" ; 8334return token_type :: parse_error ; 8335} 8336} 8337return return_type ; 8338} 8339 8340///////////////////// 8341// input management 8342///////////////////// 8343 8344/// reset token_buffer; current character is beginning of token 8345void reset () noexcept 8346{ 8347token_buffer . clear (); 8348token_string . clear (); 8349decimal_point_position = std::string:: npos ; 8350token_string . push_back ( char_traits < char_type > :: to_char_type ( current )); 8351} 8352 8353/* 8354@brief get next character from the input 8355 8356This function provides the interface to the used input adapter. It does 8357not throw in case the input reached EOF, but returns a 8358`char_traits<char>::eof()` in that case. Stores the scanned characters 8359for use in error messages. 8360 8361@return character read from the input 8362*/ 8363char_int_type get () 8364{ 8365++ position . chars_read_total ; 8366++ position . chars_read_current_line ; 8367 8368if ( next_unget ) 8369{ 8370// just reset the next_unget variable and work with current 8371next_unget = false; 8372} 8373else 8374{ 8375current = ia . get_character (); 8376} 8377 8378if ( JSON_HEDLEY_LIKELY ( current != char_traits < char_type > :: eof ())) 8379{ 8380token_string . push_back ( char_traits < char_type > :: to_char_type ( current )); 8381} 8382 8383if ( current == '\n' ) 8384{ 8385++ position . lines_read ; 8386position . chars_read_current_line = 0 ; 8387} 8388 8389return current ; 8390} 8391 8392/*! 8393@brief unget current character (read it again on next get) 8394 8395We implement unget by setting variable next_unget to true. The input is not 8396changed - we just simulate ungetting by modifying chars_read_total, 8397chars_read_current_line, and token_string. The next call to get() will 8398behave as if the unget character is read again. 8399*/ 8400void unget () 8401{ 8402next_unget = true; 8403 8404-- position . chars_read_total ; 8405 8406// in case we "unget" a newline, we have to also decrement the lines_read 8407if ( position . chars_read_current_line == 0 ) 8408{ 8409if ( position . lines_read > 0 ) 8410{ 8411-- position . lines_read ; 8412} 8413} 8414else 8415{ 8416-- position . chars_read_current_line ; 8417} 8418 8419if ( JSON_HEDLEY_LIKELY ( current != char_traits < char_type > :: eof ())) 8420{ 8421JSON_ASSERT (! token_string . empty ()); 8422token_string . pop_back (); 8423} 8424} 8425 8426/// add a character to token_buffer 8427void add ( char_int_type c ) 8428{ 8429token_buffer . push_back ( static_cast < typename string_t:: value_type > ( c )); 8430} 8431 8432public : 8433///////////////////// 8434// value getters 8435///////////////////// 8436 8437/// return integer value 8438constexpr number_integer_t get_number_integer () const noexcept 8439{ 8440return value_integer ; 8441} 8442 8443/// return unsigned integer value 8444constexpr number_unsigned_t get_number_unsigned () const noexcept 8445{ 8446return value_unsigned ; 8447} 8448 8449/// return floating-point value 8450constexpr number_float_t get_number_float () const noexcept 8451{ 8452return value_float ; 8453} 8454 8455/// return current string value (implicitly resets the token; useful only once) 8456string_t & get_string () 8457{ 8458// translate decimal points from locale back to '.' (#4084) 8459if ( decimal_point_char != '.' && decimal_point_position != std::string:: npos ) 8460{ 8461token_buffer [ decimal_point_position ] = '.' ; 8462} 8463return token_buffer ; 8464} 8465 8466///////////////////// 8467// diagnostics 8468///////////////////// 8469 8470/// return position of last read token 8471constexpr position_t get_position () const noexcept 8472{ 8473return position ; 8474} 8475 8476/// return the last read token (for errors only). Will never contain EOF 8477/// (an arbitrary value that is not a valid char value, often -1), because 8478/// 255 may legitimately occur. May contain NUL, which should be escaped. 8479std:: string get_token_string () const 8480{ 8481// escape control characters 8482std:: string result ; 8483for (const auto c : token_string ) 8484{ 8485if ( static_cast < unsigned char > ( c ) <= '\x1F' ) 8486{ 8487// escape control characters 8488std:: array < char , 9 > cs {{}}; 8489static_cast < void > ((std:: snprintf )( cs . data (), cs . size (), "<U+%.4X>" , static_cast < unsigned char > ( c ))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8490result += cs . data (); 8491} 8492else 8493{ 8494// add character as is 8495result . push_back ( static_cast < std::string:: value_type > ( c )); 8496} 8497} 8498 8499return result ; 8500} 8501 8502/// return syntax error message 8503JSON_HEDLEY_RETURNS_NON_NULL 8504constexpr const char * get_error_message () const noexcept 8505{ 8506return error_message ; 8507} 8508 8509///////////////////// 8510// actual scanner 8511///////////////////// 8512 8513/*! 8514@brief skip the UTF-8 byte order mark 8515@return true iff there is no BOM or the correct BOM has been skipped 8516*/ 8517bool skip_bom () 8518{ 8519if ( get () == 0xEF ) 8520{ 8521// check if we completely parse the BOM 8522return get () == 0xBB && get () == 0xBF ; 8523} 8524 8525// the first character is not the beginning of the BOM; unget it to 8526// process is later 8527unget (); 8528return true; 8529} 8530 8531void skip_whitespace () 8532{ 8533do 8534{ 8535get (); 8536} 8537while ( current == ' ' || current == '\t' || current == '\n' || current == '\r' ); 8538} 8539 8540token_type scan () 8541{ 8542// initially, skip the BOM 8543if ( position . chars_read_total == 0 && ! skip_bom ()) 8544{ 8545error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given" ; 8546return token_type:: parse_error ; 8547} 8548 8549// read next character and ignore whitespace 8550skip_whitespace (); 8551 8552// ignore comments 8553while ( ignore_comments && current == '/' ) 8554{ 8555if (! scan_comment ()) 8556{ 8557return token_type:: parse_error ; 8558} 8559 8560// skip following whitespace 8561skip_whitespace (); 8562} 8563 8564switch ( current ) 8565{ 8566// structural characters 8567case '[' : 8568return token_type:: begin_array ; 8569case ']' : 8570return token_type:: end_array ; 8571case '{' : 8572return token_type:: begin_object ; 8573case '}' : 8574return token_type:: end_object ; 8575case ':' : 8576return token_type:: name_separator ; 8577case ',' : 8578return token_type:: value_separator ; 8579 8580// literals 8581case 't' : 8582{ 8583std:: array < char_type , 4 > true_literal = {{ static_cast < char_type > ( 't' ), static_cast < char_type > ( 'r' ), static_cast < char_type > ( 'u' ), static_cast < char_type > ( 'e' )}}; 8584return scan_literal ( true_literal . data (), true_literal . size (), token_type:: literal_true ); 8585} 8586case 'f' : 8587{ 8588std:: array < char_type , 5 > false_literal = {{ static_cast < char_type > ( 'f' ), static_cast < char_type > ( 'a' ), static_cast < char_type > ( 'l' ), static_cast < char_type > ( 's' ), static_cast < char_type > ( 'e' )}}; 8589return scan_literal ( false_literal . data (), false_literal . size (), token_type:: literal_false ); 8590} 8591case 'n' : 8592{ 8593std:: array < char_type , 4 > null_literal = {{ static_cast < char_type > ( 'n' ), static_cast < char_type > ( 'u' ), static_cast < char_type > ( 'l' ), static_cast < char_type > ( 'l' )}}; 8594return scan_literal ( null_literal . data (), null_literal . size (), token_type:: literal_null ); 8595} 8596 8597// string 8598case '\"' : 8599return scan_string (); 8600 8601// number 8602case '-' : 8603case '0' : 8604case '1' : 8605case '2' : 8606case '3' : 8607case '4' : 8608case '5' : 8609case '6' : 8610case '7' : 8611case '8' : 8612case '9' : 8613return scan_number (); 8614 8615// end of input (the null byte is needed when parsing from 8616// string literals) 8617case '\0' : 8618case char_traits < char_type > :: eof (): 8619return token_type:: end_of_input ; 8620 8621// error 8622default: 8623error_message = "invalid literal" ; 8624return token_type:: parse_error ; 8625} 8626} 8627 8628private : 8629/// input adapter 8630InputAdapterType ia ; 8631 8632/// whether comments should be ignored (true) or signaled as errors (false) 8633const bool ignore_comments = false; 8634 8635/// the current character 8636char_int_type current = char_traits < char_type > :: eof (); 8637 8638/// whether the next get() call should just return current 8639bool next_unget = false; 8640 8641/// the start position of the current token 8642position_t position {}; 8643 8644/// raw input token string (for error messages) 8645std:: vector < char_type > token_string {}; 8646 8647/// buffer for variable-length tokens (numbers, strings) 8648string_t token_buffer {}; 8649 8650/// a description of occurred lexer errors 8651const char * error_message = "" ; 8652 8653// number values 8654number_integer_t value_integer = 0 ; 8655number_unsigned_t value_unsigned = 0 ; 8656number_float_t value_float = 0 ; 8657 8658/// the decimal point 8659const char_int_type decimal_point_char = '.' ; 8660/// the position of the decimal point in the input 8661std:: size_t decimal_point_position = std::string:: npos ; 8662}; 8663 8664} // namespace detail 8665NLOHMANN_JSON_NAMESPACE_END 8666 8667// #include <nlohmann/detail/macro_scope.hpp> 8668 8669// #include <nlohmann/detail/string_concat.hpp> 8670 8671NLOHMANN_JSON_NAMESPACE_BEGIN 8672 8673/*! 8674@brief SAX interface 8675 8676This class describes the SAX interface used by @ref nlohmann::json::sax_parse. 8677Each function is called in different situations while the input is parsed. The 8678boolean return value informs the parser whether to continue processing the 8679input. 8680*/ 8681template < typename BasicJsonType > 8682struct json_sax 8683{ 8684using number_integer_t = typename BasicJsonType :: number_integer_t ; 8685using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 8686using number_float_t = typename BasicJsonType :: number_float_t ; 8687using string_t = typename BasicJsonType :: string_t ; 8688using binary_t = typename BasicJsonType :: binary_t ; 8689 8690/*! 8691@brief a null value was read 8692@return whether parsing should proceed 8693*/ 8694virtual bool null () = 0 ; 8695 8696/*! 8697@brief a boolean value was read 8698@param[in] val boolean value 8699@return whether parsing should proceed 8700*/ 8701virtual bool boolean ( bool val ) = 0 ; 8702 8703/*! 8704@brief an integer number was read 8705@param[in] val integer value 8706@return whether parsing should proceed 8707*/ 8708virtual bool number_integer ( number_integer_t val ) = 0 ; 8709 8710/*! 8711@brief an unsigned integer number was read 8712@param[in] val unsigned integer value 8713@return whether parsing should proceed 8714*/ 8715virtual bool number_unsigned ( number_unsigned_t val ) = 0 ; 8716 8717/*! 8718@brief a floating-point number was read 8719@param[in] val floating-point value 8720@param[in] s raw token value 8721@return whether parsing should proceed 8722*/ 8723virtual bool number_float ( number_float_t val , const string_t & s ) = 0 ; 8724 8725/*! 8726@brief a string value was read 8727@param[in] val string value 8728@return whether parsing should proceed 8729@note It is safe to move the passed string value. 8730*/ 8731virtual bool string ( string_t & val ) = 0 ; 8732 8733/*! 8734@brief a binary value was read 8735@param[in] val binary value 8736@return whether parsing should proceed 8737@note It is safe to move the passed binary value. 8738*/ 8739virtual bool binary ( binary_t & val ) = 0 ; 8740 8741/*! 8742@brief the beginning of an object was read 8743@param[in] elements number of object elements or -1 if unknown 8744@return whether parsing should proceed 8745@note binary formats may report the number of elements 8746*/ 8747virtual bool start_object (std:: size_t elements ) = 0 ; 8748 8749/*! 8750@brief an object key was read 8751@param[in] val object key 8752@return whether parsing should proceed 8753@note It is safe to move the passed string. 8754*/ 8755virtual bool key ( string_t & val ) = 0 ; 8756 8757/*! 8758@brief the end of an object was read 8759@return whether parsing should proceed 8760*/ 8761virtual bool end_object () = 0 ; 8762 8763/*! 8764@brief the beginning of an array was read 8765@param[in] elements number of array elements or -1 if unknown 8766@return whether parsing should proceed 8767@note binary formats may report the number of elements 8768*/ 8769virtual bool start_array (std:: size_t elements ) = 0 ; 8770 8771/*! 8772@brief the end of an array was read 8773@return whether parsing should proceed 8774*/ 8775virtual bool end_array () = 0 ; 8776 8777/*! 8778@brief a parse error occurred 8779@param[in] position the position in the input where the error occurs 8780@param[in] last_token the last read token 8781@param[in] ex an exception object describing the error 8782@return whether parsing should proceed (must return false) 8783*/ 8784virtual bool parse_error (std:: size_t position , 8785const std:: string & last_token , 8786const detail:: exception & ex ) = 0 ; 8787 8788json_sax () = default ; 8789json_sax (const json_sax & ) = default; 8790json_sax ( json_sax && ) noexcept = default; 8791json_sax & operator = (const json_sax & ) = default ; 8792json_sax & operator = ( json_sax && ) noexcept = default ; 8793virtual ~ json_sax () = default; 8794}; 8795 8796namespace detail 8797{ 8798constexpr std:: size_t unknown_size () 8799{ 8800return (std:: numeric_limits < std:: size_t > :: max )(); 8801} 8802 8803/*! 8804@brief SAX implementation to create a JSON value from SAX events 8805 8806This class implements the @ref json_sax interface and processes the SAX events 8807to create a JSON value which makes it basically a DOM parser. The structure or 8808hierarchy of the JSON value is managed by the stack `ref_stack` which contains 8809a pointer to the respective array or object for each recursion depth. 8810 8811After successful parsing, the value that is passed by reference to the 8812constructor contains the parsed value. 8813 8814@tparam BasicJsonType the JSON type 8815*/ 8816template < typename BasicJsonType , typename InputAdapterType > 8817class json_sax_dom_parser 8818{ 8819public: 8820using number_integer_t = typename BasicJsonType :: number_integer_t ; 8821using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 8822using number_float_t = typename BasicJsonType :: number_float_t ; 8823using string_t = typename BasicJsonType :: string_t ; 8824using binary_t = typename BasicJsonType :: binary_t ; 8825using lexer_t = lexer < BasicJsonType , InputAdapterType > ; 8826 8827/*! 8828@param[in,out] r reference to a JSON value that is manipulated while 8829parsing 8830@param[in] allow_exceptions_ whether parse errors yield exceptions 8831*/ 8832explicit json_sax_dom_parser ( BasicJsonType & r , const bool allow_exceptions_ = true, lexer_t * lexer_ = nullptr ) 8833: root ( r ), allow_exceptions ( allow_exceptions_ ), m_lexer_ref ( lexer_ ) 8834{} 8835 8836// make class move-only 8837json_sax_dom_parser (const json_sax_dom_parser & ) = delete; 8838json_sax_dom_parser ( json_sax_dom_parser && ) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 8839json_sax_dom_parser & operator = (const json_sax_dom_parser & ) = delete; 8840json_sax_dom_parser & operator = ( json_sax_dom_parser && ) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 8841~ json_sax_dom_parser () = default; 8842 8843bool null () 8844{ 8845handle_value ( nullptr ); 8846return true; 8847} 8848 8849bool boolean ( bool val ) 8850{ 8851handle_value ( val ); 8852return true; 8853} 8854 8855bool number_integer ( number_integer_t val ) 8856{ 8857handle_value ( val ); 8858return true; 8859} 8860 8861bool number_unsigned ( number_unsigned_t val ) 8862{ 8863handle_value ( val ); 8864return true; 8865} 8866 8867bool number_float ( number_float_t val , const string_t & /*unused*/ ) 8868{ 8869handle_value ( val ); 8870return true; 8871} 8872 8873bool string ( string_t & val ) 8874{ 8875handle_value ( val ); 8876return true; 8877} 8878 8879bool binary ( binary_t & val ) 8880{ 8881handle_value (std:: move ( val )); 8882return true; 8883} 8884 8885bool start_object (std:: size_t len ) 8886{ 8887ref_stack . push_back ( handle_value ( BasicJsonType ::value_t:: object )); 8888 8889#if JSON_DIAGNOSTIC_POSITIONS 8890// Manually set the start position of the object here. 8891// Ensure this is after the call to handle_value to ensure correct start position. 8892if ( m_lexer_ref ) 8893{ 8894// Lexer has read the first character of the object, so 8895// subtract 1 from the position to get the correct start position. 8896ref_stack . back () -> start_position = m_lexer_ref -> get_position () - 1 ; 8897} 8898#endif 8899 8900if ( JSON_HEDLEY_UNLIKELY ( len != detail:: unknown_size () && len > ref_stack . back () -> max_size ())) 8901{ 8902JSON_THROW (out_of_range:: create ( 408 , concat ( "excessive object size: " , std:: to_string ( len )), ref_stack . back ())); 8903} 8904 8905return true; 8906} 8907 8908bool key ( string_t & val ) 8909{ 8910JSON_ASSERT (! ref_stack . empty ()); 8911JSON_ASSERT ( ref_stack . back () -> is_object ()); 8912 8913// add null at given key and store the reference for later 8914object_element = & ( ref_stack . back () -> m_data . m_value . object -> operator[]( val )); 8915return true; 8916} 8917 8918bool end_object () 8919{ 8920JSON_ASSERT (! ref_stack . empty ()); 8921JSON_ASSERT ( ref_stack . back () -> is_object ()); 8922 8923#if JSON_DIAGNOSTIC_POSITIONS 8924if ( m_lexer_ref ) 8925{ 8926// Lexer's position is past the closing brace, so set that as the end position. 8927ref_stack . back () -> end_position = m_lexer_ref -> get_position (); 8928} 8929#endif 8930 8931ref_stack . back () -> set_parents (); 8932ref_stack . pop_back (); 8933return true; 8934} 8935 8936bool start_array (std:: size_t len ) 8937{ 8938ref_stack . push_back ( handle_value ( BasicJsonType ::value_t:: array )); 8939 8940#if JSON_DIAGNOSTIC_POSITIONS 8941// Manually set the start position of the array here. 8942// Ensure this is after the call to handle_value to ensure correct start position. 8943if ( m_lexer_ref ) 8944{ 8945ref_stack . back () -> start_position = m_lexer_ref -> get_position () - 1 ; 8946} 8947#endif 8948 8949if ( JSON_HEDLEY_UNLIKELY ( len != detail:: unknown_size () && len > ref_stack . back () -> max_size ())) 8950{ 8951JSON_THROW (out_of_range:: create ( 408 , concat ( "excessive array size: " , std:: to_string ( len )), ref_stack . back ())); 8952} 8953 8954return true; 8955} 8956 8957bool end_array () 8958{ 8959JSON_ASSERT (! ref_stack . empty ()); 8960JSON_ASSERT ( ref_stack . back () -> is_array ()); 8961 8962#if JSON_DIAGNOSTIC_POSITIONS 8963if ( m_lexer_ref ) 8964{ 8965// Lexer's position is past the closing bracket, so set that as the end position. 8966ref_stack . back () -> end_position = m_lexer_ref -> get_position (); 8967} 8968#endif 8969 8970ref_stack . back () -> set_parents (); 8971ref_stack . pop_back (); 8972return true; 8973} 8974 8975template < class Exception > 8976bool parse_error (std:: size_t /*unused*/ , const std:: string & /*unused*/ , 8977const Exception & ex ) 8978{ 8979errored = true; 8980static_cast < void > ( ex ); 8981if ( allow_exceptions ) 8982{ 8983JSON_THROW ( ex ); 8984} 8985return false; 8986} 8987 8988constexpr bool is_errored () const 8989{ 8990return errored ; 8991} 8992 8993private: 8994 8995#if JSON_DIAGNOSTIC_POSITIONS 8996void handle_diagnostic_positions_for_json_value ( BasicJsonType & v ) 8997{ 8998if ( m_lexer_ref ) 8999{ 9000// Lexer has read past the current field value, so set the end position to the current position. 9001// The start position will be set below based on the length of the string representation 9002// of the value. 9003v . end_position = m_lexer_ref -> get_position (); 9004 9005switch ( v . type ()) 9006{ 9007case value_t:: boolean : 9008{ 9009// 4 and 5 are the string length of "true" and "false" 9010v . start_position = v . end_position - ( v . m_data . m_value . boolean ? 4 : 5 ); 9011break; 9012} 9013 9014case value_t:: null : 9015{ 9016// 4 is the string length of "null" 9017v . start_position = v . end_position - 4 ; 9018break; 9019} 9020 9021case value_t:: string : 9022{ 9023// include the length of the quotes, which is 2 9024v . start_position = v . end_position - v . m_data . m_value . string -> size () - 2 ; 9025break; 9026} 9027 9028// As we handle the start and end positions for values created during parsing, 9029// we do not expect the following value type to be called. Regardless, set the positions 9030// in case this is created manually or through a different constructor. Exclude from lcov 9031// since the exact condition of this switch is esoteric. 9032// LCOV_EXCL_START 9033case value_t:: discarded : 9034{ 9035v . end_position = std::string:: npos ; 9036v . start_position = v . end_position ; 9037break; 9038} 9039// LCOV_EXCL_STOP 9040case value_t:: binary : 9041case value_t:: number_integer : 9042case value_t:: number_unsigned : 9043case value_t:: number_float : 9044{ 9045v . start_position = v . end_position - m_lexer_ref -> get_string (). size (); 9046break; 9047} 9048case value_t:: object : 9049case value_t:: array : 9050{ 9051// object and array are handled in start_object() and start_array() handlers 9052// skip setting the values here. 9053break; 9054} 9055default: // LCOV_EXCL_LINE 9056// Handle all possible types discretely, default handler should never be reached. 9057JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE 9058} 9059} 9060} 9061#endif 9062 9063/*! 9064@invariant If the ref stack is empty, then the passed value will be the new 9065root. 9066@invariant If the ref stack contains a value, then it is an array or an 9067object to which we can add elements 9068*/ 9069template < typename Value > 9070JSON_HEDLEY_RETURNS_NON_NULL 9071BasicJsonType * handle_value ( Value && v ) 9072{ 9073if ( ref_stack . empty ()) 9074{ 9075root = BasicJsonType (std:: forward < Value > ( v )); 9076 9077#if JSON_DIAGNOSTIC_POSITIONS 9078handle_diagnostic_positions_for_json_value ( root ); 9079#endif 9080 9081return & root ; 9082} 9083 9084JSON_ASSERT ( ref_stack . back () -> is_array () || ref_stack . back () -> is_object ()); 9085 9086if ( ref_stack . back () -> is_array ()) 9087{ 9088ref_stack . back () -> m_data . m_value . array -> emplace_back (std:: forward < Value > ( v )); 9089 9090#if JSON_DIAGNOSTIC_POSITIONS 9091handle_diagnostic_positions_for_json_value ( ref_stack . back () -> m_data . m_value . array -> back ()); 9092#endif 9093 9094return & ( ref_stack . back () -> m_data . m_value . array -> back ()); 9095} 9096 9097JSON_ASSERT ( ref_stack . back () -> is_object ()); 9098JSON_ASSERT ( object_element ); 9099* object_element = BasicJsonType (std:: forward < Value > ( v )); 9100 9101#if JSON_DIAGNOSTIC_POSITIONS 9102handle_diagnostic_positions_for_json_value ( * object_element ); 9103#endif 9104 9105return object_element ; 9106} 9107 9108/// the parsed JSON value 9109BasicJsonType & root ; 9110/// stack to model hierarchy of values 9111std:: vector < BasicJsonType *> ref_stack {}; 9112/// helper to hold the reference for the next object element 9113BasicJsonType * object_element = nullptr ; 9114/// whether a syntax error occurred 9115bool errored = false; 9116/// whether to throw exceptions in case of errors 9117const bool allow_exceptions = true; 9118/// the lexer reference to obtain the current position 9119lexer_t * m_lexer_ref = nullptr ; 9120}; 9121 9122template < typename BasicJsonType , typename InputAdapterType > 9123class json_sax_dom_callback_parser 9124{ 9125public: 9126using number_integer_t = typename BasicJsonType :: number_integer_t ; 9127using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 9128using number_float_t = typename BasicJsonType :: number_float_t ; 9129using string_t = typename BasicJsonType :: string_t ; 9130using binary_t = typename BasicJsonType :: binary_t ; 9131using parser_callback_t = typename BasicJsonType :: parser_callback_t ; 9132using parse_event_t = typename BasicJsonType :: parse_event_t ; 9133using lexer_t = lexer < BasicJsonType , InputAdapterType > ; 9134 9135json_sax_dom_callback_parser ( BasicJsonType & r , 9136parser_callback_t cb , 9137const bool allow_exceptions_ = true, 9138lexer_t * lexer_ = nullptr ) 9139: root ( r ), callback (std:: move ( cb )), allow_exceptions ( allow_exceptions_ ), m_lexer_ref ( lexer_ ) 9140{ 9141keep_stack . push_back (true); 9142} 9143 9144// make class move-only 9145json_sax_dom_callback_parser (const json_sax_dom_callback_parser & ) = delete; 9146json_sax_dom_callback_parser ( json_sax_dom_callback_parser && ) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9147json_sax_dom_callback_parser & operator = (const json_sax_dom_callback_parser & ) = delete; 9148json_sax_dom_callback_parser & operator = ( json_sax_dom_callback_parser && ) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9149~ json_sax_dom_callback_parser () = default; 9150 9151bool null () 9152{ 9153handle_value ( nullptr ); 9154return true; 9155} 9156 9157bool boolean ( bool val ) 9158{ 9159handle_value ( val ); 9160return true; 9161} 9162 9163bool number_integer ( number_integer_t val ) 9164{ 9165handle_value ( val ); 9166return true; 9167} 9168 9169bool number_unsigned ( number_unsigned_t val ) 9170{ 9171handle_value ( val ); 9172return true; 9173} 9174 9175bool number_float ( number_float_t val , const string_t & /*unused*/ ) 9176{ 9177handle_value ( val ); 9178return true; 9179} 9180 9181bool string ( string_t & val ) 9182{ 9183handle_value ( val ); 9184return true; 9185} 9186 9187bool binary ( binary_t & val ) 9188{ 9189handle_value (std:: move ( val )); 9190return true; 9191} 9192 9193bool start_object (std:: size_t len ) 9194{ 9195// check callback for object start 9196const bool keep = callback ( static_cast < int > ( ref_stack . size ()), parse_event_t:: object_start , discarded ); 9197keep_stack . push_back ( keep ); 9198 9199auto val = handle_value ( BasicJsonType ::value_t:: object , true); 9200ref_stack . push_back ( val . second ); 9201 9202if ( ref_stack . back ()) 9203{ 9204 9205#if JSON_DIAGNOSTIC_POSITIONS 9206// Manually set the start position of the object here. 9207// Ensure this is after the call to handle_value to ensure correct start position. 9208if ( m_lexer_ref ) 9209{ 9210// Lexer has read the first character of the object, so 9211// subtract 1 from the position to get the correct start position. 9212ref_stack . back () -> start_position = m_lexer_ref -> get_position () - 1 ; 9213} 9214#endif 9215 9216// check object limit 9217if ( JSON_HEDLEY_UNLIKELY ( len != detail:: unknown_size () && len > ref_stack . back () -> max_size ())) 9218{ 9219JSON_THROW (out_of_range:: create ( 408 , concat ( "excessive object size: " , std:: to_string ( len )), ref_stack . back ())); 9220} 9221} 9222return true; 9223} 9224 9225bool key ( string_t & val ) 9226{ 9227BasicJsonType k = BasicJsonType ( val ); 9228 9229// check callback for key 9230const bool keep = callback ( static_cast < int > ( ref_stack . size ()), parse_event_t:: key , k ); 9231key_keep_stack . push_back ( keep ); 9232 9233// add discarded value at given key and store the reference for later 9234if ( keep && ref_stack . back ()) 9235{ 9236object_element = & ( ref_stack . back () -> m_data . m_value . object -> operator[]( val ) = discarded ); 9237} 9238 9239return true; 9240} 9241 9242bool end_object () 9243{ 9244if ( ref_stack . back ()) 9245{ 9246if (! callback ( static_cast < int > ( ref_stack . size ()) - 1 , parse_event_t:: object_end , * ref_stack . back ())) 9247{ 9248// discard object 9249* ref_stack . back () = discarded ; 9250 9251#if JSON_DIAGNOSTIC_POSITIONS 9252// Set start/end positions for discarded object. 9253handle_diagnostic_positions_for_json_value ( * ref_stack . back ()); 9254#endif 9255} 9256else 9257{ 9258 9259#if JSON_DIAGNOSTIC_POSITIONS 9260if ( m_lexer_ref ) 9261{ 9262// Lexer's position is past the closing brace, so set that as the end position. 9263ref_stack . back () -> end_position = m_lexer_ref -> get_position (); 9264} 9265#endif 9266 9267ref_stack . back () -> set_parents (); 9268} 9269} 9270 9271JSON_ASSERT (! ref_stack . empty ()); 9272JSON_ASSERT (! keep_stack . empty ()); 9273ref_stack . pop_back (); 9274keep_stack . pop_back (); 9275 9276if (! ref_stack . empty () && ref_stack . back () && ref_stack . back () -> is_structured ()) 9277{ 9278// remove discarded value 9279for ( auto it = ref_stack . back () -> begin (); it != ref_stack . back () -> end (); ++ it ) 9280{ 9281if ( it -> is_discarded ()) 9282{ 9283ref_stack . back () -> erase ( it ); 9284break; 9285} 9286} 9287} 9288 9289return true; 9290} 9291 9292bool start_array (std:: size_t len ) 9293{ 9294const bool keep = callback ( static_cast < int > ( ref_stack . size ()), parse_event_t:: array_start , discarded ); 9295keep_stack . push_back ( keep ); 9296 9297auto val = handle_value ( BasicJsonType ::value_t:: array , true); 9298ref_stack . push_back ( val . second ); 9299 9300if ( ref_stack . back ()) 9301{ 9302 9303#if JSON_DIAGNOSTIC_POSITIONS 9304// Manually set the start position of the array here. 9305// Ensure this is after the call to handle_value to ensure correct start position. 9306if ( m_lexer_ref ) 9307{ 9308// Lexer has read the first character of the array, so 9309// subtract 1 from the position to get the correct start position. 9310ref_stack . back () -> start_position = m_lexer_ref -> get_position () - 1 ; 9311} 9312#endif 9313 9314// check array limit 9315if ( JSON_HEDLEY_UNLIKELY ( len != detail:: unknown_size () && len > ref_stack . back () -> max_size ())) 9316{ 9317JSON_THROW (out_of_range:: create ( 408 , concat ( "excessive array size: " , std:: to_string ( len )), ref_stack . back ())); 9318} 9319} 9320 9321return true; 9322} 9323 9324bool end_array () 9325{ 9326bool keep = true; 9327 9328if ( ref_stack . back ()) 9329{ 9330keep = callback ( static_cast < int > ( ref_stack . size ()) - 1 , parse_event_t:: array_end , * ref_stack . back ()); 9331if ( keep ) 9332{ 9333 9334#if JSON_DIAGNOSTIC_POSITIONS 9335if ( m_lexer_ref ) 9336{ 9337// Lexer's position is past the closing bracket, so set that as the end position. 9338ref_stack . back () -> end_position = m_lexer_ref -> get_position (); 9339} 9340#endif 9341 9342ref_stack . back () -> set_parents (); 9343} 9344else 9345{ 9346// discard array 9347* ref_stack . back () = discarded ; 9348 9349#if JSON_DIAGNOSTIC_POSITIONS 9350// Set start/end positions for discarded array. 9351handle_diagnostic_positions_for_json_value ( * ref_stack . back ()); 9352#endif 9353} 9354} 9355 9356JSON_ASSERT (! ref_stack . empty ()); 9357JSON_ASSERT (! keep_stack . empty ()); 9358ref_stack . pop_back (); 9359keep_stack . pop_back (); 9360 9361// remove discarded value 9362if (! keep && ! ref_stack . empty () && ref_stack . back () -> is_array ()) 9363{ 9364ref_stack . back () -> m_data . m_value . array -> pop_back (); 9365} 9366 9367return true; 9368} 9369 9370template < class Exception > 9371bool parse_error (std:: size_t /*unused*/ , const std:: string & /*unused*/ , 9372const Exception & ex ) 9373{ 9374errored = true; 9375static_cast < void > ( ex ); 9376if ( allow_exceptions ) 9377{ 9378JSON_THROW ( ex ); 9379} 9380return false; 9381} 9382 9383constexpr bool is_errored () const 9384{ 9385return errored ; 9386} 9387 9388private: 9389 9390#if JSON_DIAGNOSTIC_POSITIONS 9391void handle_diagnostic_positions_for_json_value ( BasicJsonType & v ) 9392{ 9393if ( m_lexer_ref ) 9394{ 9395// Lexer has read past the current field value, so set the end position to the current position. 9396// The start position will be set below based on the length of the string representation 9397// of the value. 9398v . end_position = m_lexer_ref -> get_position (); 9399 9400switch ( v . type ()) 9401{ 9402case value_t:: boolean : 9403{ 9404// 4 and 5 are the string length of "true" and "false" 9405v . start_position = v . end_position - ( v . m_data . m_value . boolean ? 4 : 5 ); 9406break; 9407} 9408 9409case value_t:: null : 9410{ 9411// 4 is the string length of "null" 9412v . start_position = v . end_position - 4 ; 9413break; 9414} 9415 9416case value_t:: string : 9417{ 9418// include the length of the quotes, which is 2 9419v . start_position = v . end_position - v . m_data . m_value . string -> size () - 2 ; 9420break; 9421} 9422 9423case value_t:: discarded : 9424{ 9425v . end_position = std::string:: npos ; 9426v . start_position = v . end_position ; 9427break; 9428} 9429 9430case value_t:: binary : 9431case value_t:: number_integer : 9432case value_t:: number_unsigned : 9433case value_t:: number_float : 9434{ 9435v . start_position = v . end_position - m_lexer_ref -> get_string (). size (); 9436break; 9437} 9438 9439case value_t:: object : 9440case value_t:: array : 9441{ 9442// object and array are handled in start_object() and start_array() handlers 9443// skip setting the values here. 9444break; 9445} 9446default: // LCOV_EXCL_LINE 9447// Handle all possible types discretely, default handler should never be reached. 9448JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE 9449} 9450} 9451} 9452#endif 9453 9454/*! 9455@param[in] v value to add to the JSON value we build during parsing 9456@param[in] skip_callback whether we should skip calling the callback 9457function; this is required after start_array() and 9458start_object() SAX events, because otherwise we would call the 9459callback function with an empty array or object, respectively. 9460 9461@invariant If the ref stack is empty, then the passed value will be the new 9462root. 9463@invariant If the ref stack contains a value, then it is an array or an 9464object to which we can add elements 9465 9466@return pair of boolean (whether value should be kept) and pointer (to the 9467passed value in the ref_stack hierarchy; nullptr if not kept) 9468*/ 9469template < typename Value > 9470std:: pair < bool , BasicJsonType *> handle_value ( Value && v , const bool skip_callback = false) 9471{ 9472JSON_ASSERT (! keep_stack . empty ()); 9473 9474// do not handle this value if we know it would be added to a discarded 9475// container 9476if (! keep_stack . back ()) 9477{ 9478return {false, nullptr }; 9479} 9480 9481// create value 9482auto value = BasicJsonType (std:: forward < Value > ( v )); 9483 9484#if JSON_DIAGNOSTIC_POSITIONS 9485handle_diagnostic_positions_for_json_value ( value ); 9486#endif 9487 9488// check callback 9489const bool keep = skip_callback || callback ( static_cast < int > ( ref_stack . size ()), parse_event_t:: value , value ); 9490 9491// do not handle this value if we just learnt it shall be discarded 9492if (! keep ) 9493{ 9494return {false, nullptr }; 9495} 9496 9497if ( ref_stack . empty ()) 9498{ 9499root = std:: move ( value ); 9500return {true, & root }; 9501} 9502 9503// skip this value if we already decided to skip the parent 9504// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) 9505if (! ref_stack . back ()) 9506{ 9507return {false, nullptr }; 9508} 9509 9510// we now only expect arrays and objects 9511JSON_ASSERT ( ref_stack . back () -> is_array () || ref_stack . back () -> is_object ()); 9512 9513// array 9514if ( ref_stack . back () -> is_array ()) 9515{ 9516ref_stack . back () -> m_data . m_value . array -> emplace_back (std:: move ( value )); 9517return {true, & ( ref_stack . back () -> m_data . m_value . array -> back ())}; 9518} 9519 9520// object 9521JSON_ASSERT ( ref_stack . back () -> is_object ()); 9522// check if we should store an element for the current key 9523JSON_ASSERT (! key_keep_stack . empty ()); 9524const bool store_element = key_keep_stack . back (); 9525key_keep_stack . pop_back (); 9526 9527if (! store_element ) 9528{ 9529return {false, nullptr }; 9530} 9531 9532JSON_ASSERT ( object_element ); 9533* object_element = std:: move ( value ); 9534return {true, object_element }; 9535} 9536 9537/// the parsed JSON value 9538BasicJsonType & root ; 9539/// stack to model hierarchy of values 9540std:: vector < BasicJsonType *> ref_stack {}; 9541/// stack to manage which values to keep 9542std:: vector < bool > keep_stack {}; // NOLINT(readability-redundant-member-init) 9543/// stack to manage which object keys to keep 9544std:: vector < bool > key_keep_stack {}; // NOLINT(readability-redundant-member-init) 9545/// helper to hold the reference for the next object element 9546BasicJsonType * object_element = nullptr ; 9547/// whether a syntax error occurred 9548bool errored = false; 9549/// callback function 9550const parser_callback_t callback = nullptr ; 9551/// whether to throw exceptions in case of errors 9552const bool allow_exceptions = true; 9553/// a discarded value for the callback 9554BasicJsonType discarded = BasicJsonType ::value_t:: discarded ; 9555/// the lexer reference to obtain the current position 9556lexer_t * m_lexer_ref = nullptr ; 9557}; 9558 9559template < typename BasicJsonType > 9560class json_sax_acceptor 9561{ 9562public: 9563using number_integer_t = typename BasicJsonType :: number_integer_t ; 9564using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 9565using number_float_t = typename BasicJsonType :: number_float_t ; 9566using string_t = typename BasicJsonType :: string_t ; 9567using binary_t = typename BasicJsonType :: binary_t ; 9568 9569bool null () 9570{ 9571return true; 9572} 9573 9574bool boolean ( bool /*unused*/ ) 9575{ 9576return true; 9577} 9578 9579bool number_integer ( number_integer_t /*unused*/ ) 9580{ 9581return true; 9582} 9583 9584bool number_unsigned ( number_unsigned_t /*unused*/ ) 9585{ 9586return true; 9587} 9588 9589bool number_float ( number_float_t /*unused*/ , const string_t & /*unused*/ ) 9590{ 9591return true; 9592} 9593 9594bool string ( string_t & /*unused*/ ) 9595{ 9596return true; 9597} 9598 9599bool binary ( binary_t & /*unused*/ ) 9600{ 9601return true; 9602} 9603 9604bool start_object (std:: size_t /*unused*/ = detail:: unknown_size ()) 9605{ 9606return true; 9607} 9608 9609bool key ( string_t & /*unused*/ ) 9610{ 9611return true; 9612} 9613 9614bool end_object () 9615{ 9616return true; 9617} 9618 9619bool start_array (std:: size_t /*unused*/ = detail:: unknown_size ()) 9620{ 9621return true; 9622} 9623 9624bool end_array () 9625{ 9626return true; 9627} 9628 9629bool parse_error (std:: size_t /*unused*/ , const std:: string & /*unused*/ , const detail:: exception & /*unused*/ ) 9630{ 9631return false; 9632} 9633}; 9634 9635} // namespace detail 9636NLOHMANN_JSON_NAMESPACE_END 9637 9638// #include <nlohmann/detail/input/lexer.hpp> 9639 9640// #include <nlohmann/detail/macro_scope.hpp> 9641 9642// #include <nlohmann/detail/meta/is_sax.hpp> 9643// __ _____ _____ _____ 9644// __| | __| | | | JSON for Modern C++ 9645// | | |__ | | | | | | version 3.12.0 9646// |_____|_____|_____|_|___| https://github.com/nlohmann/json 9647// 9648// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 9649// SPDX-License-Identifier: MIT 9650 9651 9652 9653#include <cstdint> // size_t 9654#include <utility> // declval 9655#include <string> // string 9656 9657// #include <nlohmann/detail/abi_macros.hpp> 9658 9659// #include <nlohmann/detail/meta/detected.hpp> 9660 9661// #include <nlohmann/detail/meta/type_traits.hpp> 9662 9663 9664NLOHMANN_JSON_NAMESPACE_BEGIN 9665namespace detail 9666{ 9667 9668template < typename T > 9669using null_function_t = decltype(std:: declval < T &> (). null ()); 9670 9671template < typename T > 9672using boolean_function_t = 9673decltype(std:: declval < T &> (). boolean (std:: declval < bool > ())); 9674 9675template < typename T , typename Integer > 9676using number_integer_function_t = 9677decltype(std:: declval < T &> (). number_integer (std:: declval < Integer > ())); 9678 9679template < typename T , typename Unsigned > 9680using number_unsigned_function_t = 9681decltype(std:: declval < T &> (). number_unsigned (std:: declval < Unsigned > ())); 9682 9683template < typename T , typename Float , typename String > 9684using number_float_function_t = decltype(std:: declval < T &> (). number_float ( 9685std:: declval < Float > (), std:: declval < const String &> ())); 9686 9687template < typename T , typename String > 9688using string_function_t = 9689decltype(std:: declval < T &> (). string (std:: declval < String &> ())); 9690 9691template < typename T , typename Binary > 9692using binary_function_t = 9693decltype(std:: declval < T &> (). binary (std:: declval < Binary &> ())); 9694 9695template < typename T > 9696using start_object_function_t = 9697decltype(std:: declval < T &> (). start_object (std:: declval < std:: size_t > ())); 9698 9699template < typename T , typename String > 9700using key_function_t = 9701decltype(std:: declval < T &> (). key (std:: declval < String &> ())); 9702 9703template < typename T > 9704using end_object_function_t = decltype(std:: declval < T &> (). end_object ()); 9705 9706template < typename T > 9707using start_array_function_t = 9708decltype(std:: declval < T &> (). start_array (std:: declval < std:: size_t > ())); 9709 9710template < typename T > 9711using end_array_function_t = decltype(std:: declval < T &> (). end_array ()); 9712 9713template < typename T , typename Exception > 9714using parse_error_function_t = decltype(std:: declval < T &> (). parse_error ( 9715std:: declval < std:: size_t > (), std:: declval < const std:: string &> (), 9716std:: declval < const Exception &> ())); 9717 9718template < typename SAX , typename BasicJsonType > 9719struct is_sax 9720{ 9721private: 9722static_assert( is_basic_json < BasicJsonType > :: value , 9723"BasicJsonType must be of type basic_json<...>" ); 9724 9725using number_integer_t = typename BasicJsonType :: number_integer_t ; 9726using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 9727using number_float_t = typename BasicJsonType :: number_float_t ; 9728using string_t = typename BasicJsonType :: string_t ; 9729using binary_t = typename BasicJsonType :: binary_t ; 9730using exception_t = typename BasicJsonType :: exception ; 9731 9732public: 9733static constexpr bool value = 9734is_detected_exact < bool , null_function_t , SAX > :: value && 9735is_detected_exact < bool , boolean_function_t , SAX > :: value && 9736is_detected_exact < bool , number_integer_function_t , SAX , number_integer_t > :: value && 9737is_detected_exact < bool , number_unsigned_function_t , SAX , number_unsigned_t > :: value && 9738is_detected_exact < bool , number_float_function_t , SAX , number_float_t , string_t > :: value && 9739is_detected_exact < bool , string_function_t , SAX , string_t > :: value && 9740is_detected_exact < bool , binary_function_t , SAX , binary_t > :: value && 9741is_detected_exact < bool , start_object_function_t , SAX > :: value && 9742is_detected_exact < bool , key_function_t , SAX , string_t > :: value && 9743is_detected_exact < bool , end_object_function_t , SAX > :: value && 9744is_detected_exact < bool , start_array_function_t , SAX > :: value && 9745is_detected_exact < bool , end_array_function_t , SAX > :: value && 9746is_detected_exact < bool , parse_error_function_t , SAX , exception_t > :: value ; 9747}; 9748 9749template < typename SAX , typename BasicJsonType > 9750struct is_sax_static_asserts 9751{ 9752private: 9753static_assert( is_basic_json < BasicJsonType > :: value , 9754"BasicJsonType must be of type basic_json<...>" ); 9755 9756using number_integer_t = typename BasicJsonType :: number_integer_t ; 9757using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 9758using number_float_t = typename BasicJsonType :: number_float_t ; 9759using string_t = typename BasicJsonType :: string_t ; 9760using binary_t = typename BasicJsonType :: binary_t ; 9761using exception_t = typename BasicJsonType :: exception ; 9762 9763public: 9764static_assert( is_detected_exact < bool , null_function_t , SAX > :: value , 9765"Missing/invalid function: bool null()" ); 9766static_assert( is_detected_exact < bool , boolean_function_t , SAX > :: value , 9767"Missing/invalid function: bool boolean(bool)" ); 9768static_assert( is_detected_exact < bool , boolean_function_t , SAX > :: value , 9769"Missing/invalid function: bool boolean(bool)" ); 9770static_assert( 9771is_detected_exact < bool , number_integer_function_t , SAX , 9772number_integer_t > :: value , 9773"Missing/invalid function: bool number_integer(number_integer_t)" ); 9774static_assert( 9775is_detected_exact < bool , number_unsigned_function_t , SAX , 9776number_unsigned_t > :: value , 9777"Missing/invalid function: bool number_unsigned(number_unsigned_t)" ); 9778static_assert( is_detected_exact < bool , number_float_function_t , SAX , 9779number_float_t , string_t > :: value , 9780"Missing/invalid function: bool number_float(number_float_t, const string_t&)" ); 9781static_assert( 9782is_detected_exact < bool , string_function_t , SAX , string_t > :: value , 9783"Missing/invalid function: bool string(string_t&)" ); 9784static_assert( 9785is_detected_exact < bool , binary_function_t , SAX , binary_t > :: value , 9786"Missing/invalid function: bool binary(binary_t&)" ); 9787static_assert( is_detected_exact < bool , start_object_function_t , SAX > :: value , 9788"Missing/invalid function: bool start_object(std::size_t)" ); 9789static_assert( is_detected_exact < bool , key_function_t , SAX , string_t > :: value , 9790"Missing/invalid function: bool key(string_t&)" ); 9791static_assert( is_detected_exact < bool , end_object_function_t , SAX > :: value , 9792"Missing/invalid function: bool end_object()" ); 9793static_assert( is_detected_exact < bool , start_array_function_t , SAX > :: value , 9794"Missing/invalid function: bool start_array(std::size_t)" ); 9795static_assert( is_detected_exact < bool , end_array_function_t , SAX > :: value , 9796"Missing/invalid function: bool end_array()" ); 9797static_assert( 9798is_detected_exact < bool , parse_error_function_t , SAX , exception_t > :: value , 9799"Missing/invalid function: bool parse_error(std::size_t, const " 9800"std::string&, const exception&)" ); 9801}; 9802 9803} // namespace detail 9804NLOHMANN_JSON_NAMESPACE_END 9805 9806// #include <nlohmann/detail/meta/type_traits.hpp> 9807 9808// #include <nlohmann/detail/string_concat.hpp> 9809 9810// #include <nlohmann/detail/value_t.hpp> 9811 9812 9813NLOHMANN_JSON_NAMESPACE_BEGIN 9814namespace detail 9815{ 9816 9817/// how to treat CBOR tags 9818enum class cbor_tag_handler_t 9819{ 9820error , ///< throw a parse_error exception in case of a tag 9821ignore , ///< ignore tags 9822store ///< store tags as binary type 9823}; 9824 9825/*! 9826@brief determine system byte order 9827 9828@return true if and only if system's byte order is little endian 9829 9830@note from https://stackoverflow.com/a/1001328/266378 9831*/ 9832static inline bool little_endianness ( int num = 1 ) noexcept 9833{ 9834return * reinterpret_cast < char *> ( & num ) == 1 ; 9835} 9836 9837/////////////////// 9838// binary reader // 9839/////////////////// 9840 9841/*! 9842@brief deserialization of CBOR, MessagePack, and UBJSON values 9843*/ 9844template < typename BasicJsonType , typename InputAdapterType , typename SAX = json_sax_dom_parser < BasicJsonType , InputAdapterType >> 9845class binary_reader 9846{ 9847using number_integer_t = typename BasicJsonType :: number_integer_t ; 9848using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 9849using number_float_t = typename BasicJsonType :: number_float_t ; 9850using string_t = typename BasicJsonType :: string_t ; 9851using binary_t = typename BasicJsonType :: binary_t ; 9852using json_sax_t = SAX ; 9853using char_type = typename InputAdapterType :: char_type ; 9854using char_int_type = typename char_traits < char_type > :: int_type ; 9855 9856public: 9857/*! 9858@brief create a binary reader 9859 9860@param[in] adapter input adapter to read from 9861*/ 9862explicit binary_reader ( InputAdapterType && adapter , const input_format_t format = input_format_t:: json ) noexcept : ia (std:: move ( adapter )), input_format ( format ) 9863{ 9864( void )detail:: is_sax_static_asserts < SAX , BasicJsonType > {}; 9865} 9866 9867// make class move-only 9868binary_reader (const binary_reader & ) = delete; 9869binary_reader ( binary_reader && ) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9870binary_reader & operator = (const binary_reader & ) = delete; 9871binary_reader & operator = ( binary_reader && ) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9872~ binary_reader () = default; 9873 9874/*! 9875@param[in] format the binary format to parse 9876@param[in] sax_ a SAX event processor 9877@param[in] strict whether to expect the input to be consumed completed 9878@param[in] tag_handler how to treat CBOR tags 9879 9880@return whether parsing was successful 9881*/ 9882JSON_HEDLEY_NON_NULL ( 3 ) 9883bool sax_parse (const input_format_t format , 9884json_sax_t * sax_ , 9885const bool strict = true, 9886const cbor_tag_handler_t tag_handler = cbor_tag_handler_t:: error ) 9887{ 9888sax = sax_ ; 9889bool result = false; 9890 9891switch ( format ) 9892{ 9893case input_format_t:: bson : 9894result = parse_bson_internal (); 9895break; 9896 9897case input_format_t:: cbor : 9898result = parse_cbor_internal (true, tag_handler ); 9899break; 9900 9901case input_format_t:: msgpack : 9902result = parse_msgpack_internal (); 9903break; 9904 9905case input_format_t:: ubjson : 9906case input_format_t:: bjdata : 9907result = parse_ubjson_internal (); 9908break; 9909 9910case input_format_t:: json : // LCOV_EXCL_LINE 9911default: // LCOV_EXCL_LINE 9912JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 9913} 9914 9915// strict mode: next byte must be EOF 9916if ( result && strict ) 9917{ 9918if ( input_format == input_format_t:: ubjson || input_format == input_format_t:: bjdata ) 9919{ 9920get_ignore_noop (); 9921} 9922else 9923{ 9924get (); 9925} 9926 9927if ( JSON_HEDLEY_UNLIKELY ( current != char_traits < char_type > :: eof ())) 9928{ 9929return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 110 , chars_read , 9930exception_message ( input_format , concat ( "expected end of input; last byte: 0x" , get_token_string ()), "value" ), nullptr )); 9931} 9932} 9933 9934return result ; 9935} 9936 9937private: 9938////////// 9939// BSON // 9940////////// 9941 9942/*! 9943@brief Reads in a BSON-object and passes it to the SAX-parser. 9944@return whether a valid BSON-value was passed to the SAX parser 9945*/ 9946bool parse_bson_internal () 9947{ 9948std:: int32_t document_size {}; 9949get_number < std:: int32_t , true > (input_format_t:: bson , document_size ); 9950 9951if ( JSON_HEDLEY_UNLIKELY (! sax -> start_object (detail:: unknown_size ()))) 9952{ 9953return false; 9954} 9955 9956if ( JSON_HEDLEY_UNLIKELY (! parse_bson_element_list ( /*is_array*/ false))) 9957{ 9958return false; 9959} 9960 9961return sax -> end_object (); 9962} 9963 9964/*! 9965@brief Parses a C-style string from the BSON input. 9966@param[in,out] result A reference to the string variable where the read 9967string is to be stored. 9968@return `true` if the \x00-byte indicating the end of the string was 9969encountered before the EOF; false` indicates an unexpected EOF. 9970*/ 9971bool get_bson_cstr ( string_t & result ) 9972{ 9973auto out = std:: back_inserter ( result ); 9974while (true) 9975{ 9976get (); 9977if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof (input_format_t:: bson , "cstring" ))) 9978{ 9979return false; 9980} 9981if ( current == 0x00 ) 9982{ 9983return true; 9984} 9985* out ++ = static_cast < typename string_t:: value_type > ( current ); 9986} 9987} 9988 9989/*! 9990@brief Parses a zero-terminated string of length @a len from the BSON 9991input. 9992@param[in] len The length (including the zero-byte at the end) of the 9993string to be read. 9994@param[in,out] result A reference to the string variable where the read 9995string is to be stored. 9996@tparam NumberType The type of the length @a len 9997@pre len >= 1 9998@return `true` if the string was successfully parsed 9999*/ 10000template < typename NumberType > 10001bool get_bson_string (const NumberType len , string_t & result ) 10002{ 10003if ( JSON_HEDLEY_UNLIKELY ( len < 1 )) 10004{ 10005auto last_token = get_token_string (); 10006return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 10007exception_message (input_format_t:: bson , concat ( "string length must be at least 1, is " , std:: to_string ( len )), "string" ), nullptr )); 10008} 10009 10010return get_string (input_format_t:: bson , len - static_cast < NumberType > ( 1 ), result ) && get () != char_traits < char_type > :: eof (); 10011} 10012 10013/*! 10014@brief Parses a byte array input of length @a len from the BSON input. 10015@param[in] len The length of the byte array to be read. 10016@param[in,out] result A reference to the binary variable where the read 10017array is to be stored. 10018@tparam NumberType The type of the length @a len 10019@pre len >= 0 10020@return `true` if the byte array was successfully parsed 10021*/ 10022template < typename NumberType > 10023bool get_bson_binary (const NumberType len , binary_t & result ) 10024{ 10025if ( JSON_HEDLEY_UNLIKELY ( len < 0 )) 10026{ 10027auto last_token = get_token_string (); 10028return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 10029exception_message (input_format_t:: bson , concat ( "byte array length cannot be negative, is " , std:: to_string ( len )), "binary" ), nullptr )); 10030} 10031 10032// All BSON binary values have a subtype 10033std:: uint8_t subtype {}; 10034get_number < std:: uint8_t > (input_format_t:: bson , subtype ); 10035result . set_subtype ( subtype ); 10036 10037return get_binary (input_format_t:: bson , len , result ); 10038} 10039 10040/*! 10041@brief Read a BSON document element of the given @a element_type. 10042@param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html 10043@param[in] element_type_parse_position The position in the input stream, 10044where the `element_type` was read. 10045@warning Not all BSON element types are supported yet. An unsupported 10046@a element_type will give rise to a parse_error.114: 10047Unsupported BSON record type 0x... 10048@return whether a valid BSON-object/array was passed to the SAX parser 10049*/ 10050bool parse_bson_element_internal (const char_int_type element_type , 10051const std:: size_t element_type_parse_position ) 10052{ 10053switch ( element_type ) 10054{ 10055case 0x01 : // double 10056{ 10057double number {}; 10058return get_number < double , true > (input_format_t:: bson , number ) && sax -> number_float ( static_cast < number_float_t > ( number ), "" ); 10059} 10060 10061case 0x02 : // string 10062{ 10063std:: int32_t len {}; 10064string_t value ; 10065return get_number < std:: int32_t , true > (input_format_t:: bson , len ) && get_bson_string ( len , value ) && sax -> string ( value ); 10066} 10067 10068case 0x03 : // object 10069{ 10070return parse_bson_internal (); 10071} 10072 10073case 0x04 : // array 10074{ 10075return parse_bson_array (); 10076} 10077 10078case 0x05 : // binary 10079{ 10080std:: int32_t len {}; 10081binary_t value ; 10082return get_number < std:: int32_t , true > (input_format_t:: bson , len ) && get_bson_binary ( len , value ) && sax -> binary ( value ); 10083} 10084 10085case 0x08 : // boolean 10086{ 10087return sax -> boolean ( get () != 0 ); 10088} 10089 10090case 0x0A : // null 10091{ 10092return sax -> null (); 10093} 10094 10095case 0x10 : // int32 10096{ 10097std:: int32_t value {}; 10098return get_number < std:: int32_t , true > (input_format_t:: bson , value ) && sax -> number_integer ( value ); 10099} 10100 10101case 0x12 : // int64 10102{ 10103std:: int64_t value {}; 10104return get_number < std:: int64_t , true > (input_format_t:: bson , value ) && sax -> number_integer ( value ); 10105} 10106 10107case 0x11 : // uint64 10108{ 10109std:: uint64_t value {}; 10110return get_number < std:: uint64_t , true > (input_format_t:: bson , value ) && sax -> number_unsigned ( value ); 10111} 10112 10113default: // anything else not supported (yet) 10114{ 10115std:: array < char , 3 > cr {{}}; 10116static_cast < void > ((std:: snprintf )( cr . data (), cr . size (), "%.2hhX" , static_cast < unsigned char > ( element_type ))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 10117const std:: string cr_str { cr . data ()}; 10118return sax -> parse_error ( element_type_parse_position , cr_str , 10119parse_error:: create ( 114 , element_type_parse_position , concat ( "Unsupported BSON record type 0x" , cr_str ), nullptr )); 10120} 10121} 10122} 10123 10124/*! 10125@brief Read a BSON element list (as specified in the BSON-spec) 10126 10127The same binary layout is used for objects and arrays, hence it must be 10128indicated with the argument @a is_array which one is expected 10129(true --> array, false --> object). 10130 10131@param[in] is_array Determines if the element list being read is to be 10132treated as an object (@a is_array == false), or as an 10133array (@a is_array == true). 10134@return whether a valid BSON-object/array was passed to the SAX parser 10135*/ 10136bool parse_bson_element_list (const bool is_array ) 10137{ 10138string_t key ; 10139 10140while ( auto element_type = get ()) 10141{ 10142if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof (input_format_t:: bson , "element list" ))) 10143{ 10144return false; 10145} 10146 10147const std:: size_t element_type_parse_position = chars_read ; 10148if ( JSON_HEDLEY_UNLIKELY (! get_bson_cstr ( key ))) 10149{ 10150return false; 10151} 10152 10153if (! is_array && ! sax -> key ( key )) 10154{ 10155return false; 10156} 10157 10158if ( JSON_HEDLEY_UNLIKELY (! parse_bson_element_internal ( element_type , element_type_parse_position ))) 10159{ 10160return false; 10161} 10162 10163// get_bson_cstr only appends 10164key . clear (); 10165} 10166 10167return true; 10168} 10169 10170/*! 10171@brief Reads an array from the BSON input and passes it to the SAX-parser. 10172@return whether a valid BSON-array was passed to the SAX parser 10173*/ 10174bool parse_bson_array () 10175{ 10176std:: int32_t document_size {}; 10177get_number < std:: int32_t , true > (input_format_t:: bson , document_size ); 10178 10179if ( JSON_HEDLEY_UNLIKELY (! sax -> start_array (detail:: unknown_size ()))) 10180{ 10181return false; 10182} 10183 10184if ( JSON_HEDLEY_UNLIKELY (! parse_bson_element_list ( /*is_array*/ true))) 10185{ 10186return false; 10187} 10188 10189return sax -> end_array (); 10190} 10191 10192////////// 10193// CBOR // 10194////////// 10195 10196/*! 10197@param[in] get_char whether a new character should be retrieved from the 10198input (true) or whether the last read character should 10199be considered instead (false) 10200@param[in] tag_handler how CBOR tags should be treated 10201 10202@return whether a valid CBOR value was passed to the SAX parser 10203*/ 10204bool parse_cbor_internal (const bool get_char , 10205const cbor_tag_handler_t tag_handler ) 10206{ 10207switch ( get_char ? get () : current ) 10208{ 10209// EOF 10210case char_traits < char_type > :: eof (): 10211return unexpect_eof (input_format_t:: cbor , "value" ); 10212 10213// Integer 0x00..0x17 (0..23) 10214case 0x00 : 10215case 0x01 : 10216case 0x02 : 10217case 0x03 : 10218case 0x04 : 10219case 0x05 : 10220case 0x06 : 10221case 0x07 : 10222case 0x08 : 10223case 0x09 : 10224case 0x0A : 10225case 0x0B : 10226case 0x0C : 10227case 0x0D : 10228case 0x0E : 10229case 0x0F : 10230case 0x10 : 10231case 0x11 : 10232case 0x12 : 10233case 0x13 : 10234case 0x14 : 10235case 0x15 : 10236case 0x16 : 10237case 0x17 : 10238return sax -> number_unsigned ( static_cast < number_unsigned_t > ( current )); 10239 10240case 0x18 : // Unsigned integer (one-byte uint8_t follows) 10241{ 10242std:: uint8_t number {}; 10243return get_number (input_format_t:: cbor , number ) && sax -> number_unsigned ( number ); 10244} 10245 10246case 0x19 : // Unsigned integer (two-byte uint16_t follows) 10247{ 10248std:: uint16_t number {}; 10249return get_number (input_format_t:: cbor , number ) && sax -> number_unsigned ( number ); 10250} 10251 10252case 0x1A : // Unsigned integer (four-byte uint32_t follows) 10253{ 10254std:: uint32_t number {}; 10255return get_number (input_format_t:: cbor , number ) && sax -> number_unsigned ( number ); 10256} 10257 10258case 0x1B : // Unsigned integer (eight-byte uint64_t follows) 10259{ 10260std:: uint64_t number {}; 10261return get_number (input_format_t:: cbor , number ) && sax -> number_unsigned ( number ); 10262} 10263 10264// Negative integer -1-0x00..-1-0x17 (-1..-24) 10265case 0x20 : 10266case 0x21 : 10267case 0x22 : 10268case 0x23 : 10269case 0x24 : 10270case 0x25 : 10271case 0x26 : 10272case 0x27 : 10273case 0x28 : 10274case 0x29 : 10275case 0x2A : 10276case 0x2B : 10277case 0x2C : 10278case 0x2D : 10279case 0x2E : 10280case 0x2F : 10281case 0x30 : 10282case 0x31 : 10283case 0x32 : 10284case 0x33 : 10285case 0x34 : 10286case 0x35 : 10287case 0x36 : 10288case 0x37 : 10289return sax -> number_integer ( static_cast < std:: int8_t > ( 0x20 - 1 - current )); 10290 10291case 0x38 : // Negative integer (one-byte uint8_t follows) 10292{ 10293std:: uint8_t number {}; 10294return get_number (input_format_t:: cbor , number ) && sax -> number_integer ( static_cast < number_integer_t > ( -1 ) - number ); 10295} 10296 10297case 0x39 : // Negative integer -1-n (two-byte uint16_t follows) 10298{ 10299std:: uint16_t number {}; 10300return get_number (input_format_t:: cbor , number ) && sax -> number_integer ( static_cast < number_integer_t > ( -1 ) - number ); 10301} 10302 10303case 0x3A : // Negative integer -1-n (four-byte uint32_t follows) 10304{ 10305std:: uint32_t number {}; 10306return get_number (input_format_t:: cbor , number ) && sax -> number_integer ( static_cast < number_integer_t > ( -1 ) - number ); 10307} 10308 10309case 0x3B : // Negative integer -1-n (eight-byte uint64_t follows) 10310{ 10311std:: uint64_t number {}; 10312return get_number (input_format_t:: cbor , number ) && sax -> number_integer ( static_cast < number_integer_t > ( -1 ) 10313- static_cast < number_integer_t > ( number )); 10314} 10315 10316// Binary data (0x00..0x17 bytes follow) 10317case 0x40 : 10318case 0x41 : 10319case 0x42 : 10320case 0x43 : 10321case 0x44 : 10322case 0x45 : 10323case 0x46 : 10324case 0x47 : 10325case 0x48 : 10326case 0x49 : 10327case 0x4A : 10328case 0x4B : 10329case 0x4C : 10330case 0x4D : 10331case 0x4E : 10332case 0x4F : 10333case 0x50 : 10334case 0x51 : 10335case 0x52 : 10336case 0x53 : 10337case 0x54 : 10338case 0x55 : 10339case 0x56 : 10340case 0x57 : 10341case 0x58 : // Binary data (one-byte uint8_t for n follows) 10342case 0x59 : // Binary data (two-byte uint16_t for n follow) 10343case 0x5A : // Binary data (four-byte uint32_t for n follow) 10344case 0x5B : // Binary data (eight-byte uint64_t for n follow) 10345case 0x5F : // Binary data (indefinite length) 10346{ 10347binary_t b ; 10348return get_cbor_binary ( b ) && sax -> binary ( b ); 10349} 10350 10351// UTF-8 string (0x00..0x17 bytes follow) 10352case 0x60 : 10353case 0x61 : 10354case 0x62 : 10355case 0x63 : 10356case 0x64 : 10357case 0x65 : 10358case 0x66 : 10359case 0x67 : 10360case 0x68 : 10361case 0x69 : 10362case 0x6A : 10363case 0x6B : 10364case 0x6C : 10365case 0x6D : 10366case 0x6E : 10367case 0x6F : 10368case 0x70 : 10369case 0x71 : 10370case 0x72 : 10371case 0x73 : 10372case 0x74 : 10373case 0x75 : 10374case 0x76 : 10375case 0x77 : 10376case 0x78 : // UTF-8 string (one-byte uint8_t for n follows) 10377case 0x79 : // UTF-8 string (two-byte uint16_t for n follow) 10378case 0x7A : // UTF-8 string (four-byte uint32_t for n follow) 10379case 0x7B : // UTF-8 string (eight-byte uint64_t for n follow) 10380case 0x7F : // UTF-8 string (indefinite length) 10381{ 10382string_t s ; 10383return get_cbor_string ( s ) && sax -> string ( s ); 10384} 10385 10386// array (0x00..0x17 data items follow) 10387case 0x80 : 10388case 0x81 : 10389case 0x82 : 10390case 0x83 : 10391case 0x84 : 10392case 0x85 : 10393case 0x86 : 10394case 0x87 : 10395case 0x88 : 10396case 0x89 : 10397case 0x8A : 10398case 0x8B : 10399case 0x8C : 10400case 0x8D : 10401case 0x8E : 10402case 0x8F : 10403case 0x90 : 10404case 0x91 : 10405case 0x92 : 10406case 0x93 : 10407case 0x94 : 10408case 0x95 : 10409case 0x96 : 10410case 0x97 : 10411return get_cbor_array ( 10412conditional_static_cast < std:: size_t > ( static_cast < unsigned int > ( current ) & 0x1Fu ), tag_handler ); 10413 10414case 0x98 : // array (one-byte uint8_t for n follows) 10415{ 10416std:: uint8_t len {}; 10417return get_number (input_format_t:: cbor , len ) && get_cbor_array ( static_cast < std:: size_t > ( len ), tag_handler ); 10418} 10419 10420case 0x99 : // array (two-byte uint16_t for n follow) 10421{ 10422std:: uint16_t len {}; 10423return get_number (input_format_t:: cbor , len ) && get_cbor_array ( static_cast < std:: size_t > ( len ), tag_handler ); 10424} 10425 10426case 0x9A : // array (four-byte uint32_t for n follow) 10427{ 10428std:: uint32_t len {}; 10429return get_number (input_format_t:: cbor , len ) && get_cbor_array ( conditional_static_cast < std:: size_t > ( len ), tag_handler ); 10430} 10431 10432case 0x9B : // array (eight-byte uint64_t for n follow) 10433{ 10434std:: uint64_t len {}; 10435return get_number (input_format_t:: cbor , len ) && get_cbor_array ( conditional_static_cast < std:: size_t > ( len ), tag_handler ); 10436} 10437 10438case 0x9F : // array (indefinite length) 10439return get_cbor_array (detail:: unknown_size (), tag_handler ); 10440 10441// map (0x00..0x17 pairs of data items follow) 10442case 0xA0 : 10443case 0xA1 : 10444case 0xA2 : 10445case 0xA3 : 10446case 0xA4 : 10447case 0xA5 : 10448case 0xA6 : 10449case 0xA7 : 10450case 0xA8 : 10451case 0xA9 : 10452case 0xAA : 10453case 0xAB : 10454case 0xAC : 10455case 0xAD : 10456case 0xAE : 10457case 0xAF : 10458case 0xB0 : 10459case 0xB1 : 10460case 0xB2 : 10461case 0xB3 : 10462case 0xB4 : 10463case 0xB5 : 10464case 0xB6 : 10465case 0xB7 : 10466return get_cbor_object ( conditional_static_cast < std:: size_t > ( static_cast < unsigned int > ( current ) & 0x1Fu ), tag_handler ); 10467 10468case 0xB8 : // map (one-byte uint8_t for n follows) 10469{ 10470std:: uint8_t len {}; 10471return get_number (input_format_t:: cbor , len ) && get_cbor_object ( static_cast < std:: size_t > ( len ), tag_handler ); 10472} 10473 10474case 0xB9 : // map (two-byte uint16_t for n follow) 10475{ 10476std:: uint16_t len {}; 10477return get_number (input_format_t:: cbor , len ) && get_cbor_object ( static_cast < std:: size_t > ( len ), tag_handler ); 10478} 10479 10480case 0xBA : // map (four-byte uint32_t for n follow) 10481{ 10482std:: uint32_t len {}; 10483return get_number (input_format_t:: cbor , len ) && get_cbor_object ( conditional_static_cast < std:: size_t > ( len ), tag_handler ); 10484} 10485 10486case 0xBB : // map (eight-byte uint64_t for n follow) 10487{ 10488std:: uint64_t len {}; 10489return get_number (input_format_t:: cbor , len ) && get_cbor_object ( conditional_static_cast < std:: size_t > ( len ), tag_handler ); 10490} 10491 10492case 0xBF : // map (indefinite length) 10493return get_cbor_object (detail:: unknown_size (), tag_handler ); 10494 10495case 0xC6 : // tagged item 10496case 0xC7 : 10497case 0xC8 : 10498case 0xC9 : 10499case 0xCA : 10500case 0xCB : 10501case 0xCC : 10502case 0xCD : 10503case 0xCE : 10504case 0xCF : 10505case 0xD0 : 10506case 0xD1 : 10507case 0xD2 : 10508case 0xD3 : 10509case 0xD4 : 10510case 0xD8 : // tagged item (1 bytes follow) 10511case 0xD9 : // tagged item (2 bytes follow) 10512case 0xDA : // tagged item (4 bytes follow) 10513case 0xDB : // tagged item (8 bytes follow) 10514{ 10515switch ( tag_handler ) 10516{ 10517case cbor_tag_handler_t:: error : 10518{ 10519auto last_token = get_token_string (); 10520return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 10521exception_message (input_format_t:: cbor , concat ( "invalid byte: 0x" , last_token ), "value" ), nullptr )); 10522} 10523 10524case cbor_tag_handler_t:: ignore : 10525{ 10526// ignore binary subtype 10527switch ( current ) 10528{ 10529case 0xD8 : 10530{ 10531std:: uint8_t subtype_to_ignore {}; 10532get_number (input_format_t:: cbor , subtype_to_ignore ); 10533break; 10534} 10535case 0xD9 : 10536{ 10537std:: uint16_t subtype_to_ignore {}; 10538get_number (input_format_t:: cbor , subtype_to_ignore ); 10539break; 10540} 10541case 0xDA : 10542{ 10543std:: uint32_t subtype_to_ignore {}; 10544get_number (input_format_t:: cbor , subtype_to_ignore ); 10545break; 10546} 10547case 0xDB : 10548{ 10549std:: uint64_t subtype_to_ignore {}; 10550get_number (input_format_t:: cbor , subtype_to_ignore ); 10551break; 10552} 10553default: 10554break; 10555} 10556return parse_cbor_internal (true, tag_handler ); 10557} 10558 10559case cbor_tag_handler_t:: store : 10560{ 10561binary_t b ; 10562// use binary subtype and store in binary container 10563switch ( current ) 10564{ 10565case 0xD8 : 10566{ 10567std:: uint8_t subtype {}; 10568get_number (input_format_t:: cbor , subtype ); 10569b . set_subtype (detail:: conditional_static_cast < typename binary_t:: subtype_type > ( subtype )); 10570break; 10571} 10572case 0xD9 : 10573{ 10574std:: uint16_t subtype {}; 10575get_number (input_format_t:: cbor , subtype ); 10576b . set_subtype (detail:: conditional_static_cast < typename binary_t:: subtype_type > ( subtype )); 10577break; 10578} 10579case 0xDA : 10580{ 10581std:: uint32_t subtype {}; 10582get_number (input_format_t:: cbor , subtype ); 10583b . set_subtype (detail:: conditional_static_cast < typename binary_t:: subtype_type > ( subtype )); 10584break; 10585} 10586case 0xDB : 10587{ 10588std:: uint64_t subtype {}; 10589get_number (input_format_t:: cbor , subtype ); 10590b . set_subtype (detail:: conditional_static_cast < typename binary_t:: subtype_type > ( subtype )); 10591break; 10592} 10593default: 10594return parse_cbor_internal (true, tag_handler ); 10595} 10596get (); 10597return get_cbor_binary ( b ) && sax -> binary ( b ); 10598} 10599 10600default: // LCOV_EXCL_LINE 10601JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 10602return false; // LCOV_EXCL_LINE 10603} 10604} 10605 10606case 0xF4 : // false 10607return sax -> boolean (false); 10608 10609case 0xF5 : // true 10610return sax -> boolean (true); 10611 10612case 0xF6 : // null 10613return sax -> null (); 10614 10615case 0xF9 : // Half-Precision Float (two-byte IEEE 754) 10616{ 10617const auto byte1_raw = get (); 10618if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof (input_format_t:: cbor , "number" ))) 10619{ 10620return false; 10621} 10622const auto byte2_raw = get (); 10623if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof (input_format_t:: cbor , "number" ))) 10624{ 10625return false; 10626} 10627 10628const auto byte1 = static_cast < unsigned char > ( byte1_raw ); 10629const auto byte2 = static_cast < unsigned char > ( byte2_raw ); 10630 10631// code from RFC 7049, Appendix D, Figure 3: 10632// As half-precision floating-point numbers were only added 10633// to IEEE 754 in 2008, today's programming platforms often 10634// still only have limited support for them. It is very 10635// easy to include at least decoding support for them even 10636// without such support. An example of a small decoder for 10637// half-precision floating-point numbers in the C language 10638// is shown in Fig. 3. 10639const auto half = static_cast < unsigned int > (( byte1 << 8u ) + byte2 ); 10640const double val = [ & half ] 10641{ 10642const int exp = ( half >> 10u ) & 0x1Fu ; 10643const unsigned int mant = half & 0x3FFu ; 10644JSON_ASSERT ( 0 <= exp && exp <= 32 ); 10645JSON_ASSERT ( mant <= 1024 ); 10646switch ( exp ) 10647{ 10648case 0 : 10649return std:: ldexp ( mant , -24 ); 10650case 31 : 10651return ( mant == 0 ) 10652? std:: numeric_limits < double > :: infinity () 10653: std:: numeric_limits < double > :: quiet_NaN (); 10654default: 10655return std:: ldexp ( mant + 1024 , exp - 25 ); 10656} 10657}(); 10658return sax -> number_float (( half & 0x8000u ) != 0 10659? static_cast < number_float_t > ( - val ) 10660: static_cast < number_float_t > ( val ), "" ); 10661} 10662 10663case 0xFA : // Single-Precision Float (four-byte IEEE 754) 10664{ 10665float number {}; 10666return get_number (input_format_t:: cbor , number ) && sax -> number_float ( static_cast < number_float_t > ( number ), "" ); 10667} 10668 10669case 0xFB : // Double-Precision Float (eight-byte IEEE 754) 10670{ 10671double number {}; 10672return get_number (input_format_t:: cbor , number ) && sax -> number_float ( static_cast < number_float_t > ( number ), "" ); 10673} 10674 10675default: // anything else (0xFF is handled inside the other types) 10676{ 10677auto last_token = get_token_string (); 10678return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 10679exception_message (input_format_t:: cbor , concat ( "invalid byte: 0x" , last_token ), "value" ), nullptr )); 10680} 10681} 10682} 10683 10684/*! 10685@brief reads a CBOR string 10686 10687This function first reads starting bytes to determine the expected 10688string length and then copies this number of bytes into a string. 10689Additionally, CBOR's strings with indefinite lengths are supported. 10690 10691@param[out] result created string 10692 10693@return whether string creation completed 10694*/ 10695bool get_cbor_string ( string_t & result ) 10696{ 10697if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof (input_format_t:: cbor , "string" ))) 10698{ 10699return false; 10700} 10701 10702switch ( current ) 10703{ 10704// UTF-8 string (0x00..0x17 bytes follow) 10705case 0x60 : 10706case 0x61 : 10707case 0x62 : 10708case 0x63 : 10709case 0x64 : 10710case 0x65 : 10711case 0x66 : 10712case 0x67 : 10713case 0x68 : 10714case 0x69 : 10715case 0x6A : 10716case 0x6B : 10717case 0x6C : 10718case 0x6D : 10719case 0x6E : 10720case 0x6F : 10721case 0x70 : 10722case 0x71 : 10723case 0x72 : 10724case 0x73 : 10725case 0x74 : 10726case 0x75 : 10727case 0x76 : 10728case 0x77 : 10729{ 10730return get_string (input_format_t:: cbor , static_cast < unsigned int > ( current ) & 0x1Fu , result ); 10731} 10732 10733case 0x78 : // UTF-8 string (one-byte uint8_t for n follows) 10734{ 10735std:: uint8_t len {}; 10736return get_number (input_format_t:: cbor , len ) && get_string (input_format_t:: cbor , len , result ); 10737} 10738 10739case 0x79 : // UTF-8 string (two-byte uint16_t for n follow) 10740{ 10741std:: uint16_t len {}; 10742return get_number (input_format_t:: cbor , len ) && get_string (input_format_t:: cbor , len , result ); 10743} 10744 10745case 0x7A : // UTF-8 string (four-byte uint32_t for n follow) 10746{ 10747std:: uint32_t len {}; 10748return get_number (input_format_t:: cbor , len ) && get_string (input_format_t:: cbor , len , result ); 10749} 10750 10751case 0x7B : // UTF-8 string (eight-byte uint64_t for n follow) 10752{ 10753std:: uint64_t len {}; 10754return get_number (input_format_t:: cbor , len ) && get_string (input_format_t:: cbor , len , result ); 10755} 10756 10757case 0x7F : // UTF-8 string (indefinite length) 10758{ 10759while ( get () != 0xFF ) 10760{ 10761string_t chunk ; 10762if (! get_cbor_string ( chunk )) 10763{ 10764return false; 10765} 10766result . append ( chunk ); 10767} 10768return true; 10769} 10770 10771default: 10772{ 10773auto last_token = get_token_string (); 10774return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 113 , chars_read , 10775exception_message (input_format_t:: cbor , concat ( "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" , last_token ), "string" ), nullptr )); 10776} 10777} 10778} 10779 10780/*! 10781@brief reads a CBOR byte array 10782 10783This function first reads starting bytes to determine the expected 10784byte array length and then copies this number of bytes into the byte array. 10785Additionally, CBOR's byte arrays with indefinite lengths are supported. 10786 10787@param[out] result created byte array 10788 10789@return whether byte array creation completed 10790*/ 10791bool get_cbor_binary ( binary_t & result ) 10792{ 10793if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof (input_format_t:: cbor , "binary" ))) 10794{ 10795return false; 10796} 10797 10798switch ( current ) 10799{ 10800// Binary data (0x00..0x17 bytes follow) 10801case 0x40 : 10802case 0x41 : 10803case 0x42 : 10804case 0x43 : 10805case 0x44 : 10806case 0x45 : 10807case 0x46 : 10808case 0x47 : 10809case 0x48 : 10810case 0x49 : 10811case 0x4A : 10812case 0x4B : 10813case 0x4C : 10814case 0x4D : 10815case 0x4E : 10816case 0x4F : 10817case 0x50 : 10818case 0x51 : 10819case 0x52 : 10820case 0x53 : 10821case 0x54 : 10822case 0x55 : 10823case 0x56 : 10824case 0x57 : 10825{ 10826return get_binary (input_format_t:: cbor , static_cast < unsigned int > ( current ) & 0x1Fu , result ); 10827} 10828 10829case 0x58 : // Binary data (one-byte uint8_t for n follows) 10830{ 10831std:: uint8_t len {}; 10832return get_number (input_format_t:: cbor , len ) && 10833get_binary (input_format_t:: cbor , len , result ); 10834} 10835 10836case 0x59 : // Binary data (two-byte uint16_t for n follow) 10837{ 10838std:: uint16_t len {}; 10839return get_number (input_format_t:: cbor , len ) && 10840get_binary (input_format_t:: cbor , len , result ); 10841} 10842 10843case 0x5A : // Binary data (four-byte uint32_t for n follow) 10844{ 10845std:: uint32_t len {}; 10846return get_number (input_format_t:: cbor , len ) && 10847get_binary (input_format_t:: cbor , len , result ); 10848} 10849 10850case 0x5B : // Binary data (eight-byte uint64_t for n follow) 10851{ 10852std:: uint64_t len {}; 10853return get_number (input_format_t:: cbor , len ) && 10854get_binary (input_format_t:: cbor , len , result ); 10855} 10856 10857case 0x5F : // Binary data (indefinite length) 10858{ 10859while ( get () != 0xFF ) 10860{ 10861binary_t chunk ; 10862if (! get_cbor_binary ( chunk )) 10863{ 10864return false; 10865} 10866result . insert ( result . end (), chunk . begin (), chunk . end ()); 10867} 10868return true; 10869} 10870 10871default: 10872{ 10873auto last_token = get_token_string (); 10874return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 113 , chars_read , 10875exception_message (input_format_t:: cbor , concat ( "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" , last_token ), "binary" ), nullptr )); 10876} 10877} 10878} 10879 10880/*! 10881@param[in] len the length of the array or detail::unknown_size() for an 10882array of indefinite size 10883@param[in] tag_handler how CBOR tags should be treated 10884@return whether array creation completed 10885*/ 10886bool get_cbor_array (const std:: size_t len , 10887const cbor_tag_handler_t tag_handler ) 10888{ 10889if ( JSON_HEDLEY_UNLIKELY (! sax -> start_array ( len ))) 10890{ 10891return false; 10892} 10893 10894if ( len != detail:: unknown_size ()) 10895{ 10896for (std:: size_t i = 0 ; i < len ; ++ i ) 10897{ 10898if ( JSON_HEDLEY_UNLIKELY (! parse_cbor_internal (true, tag_handler ))) 10899{ 10900return false; 10901} 10902} 10903} 10904else 10905{ 10906while ( get () != 0xFF ) 10907{ 10908if ( JSON_HEDLEY_UNLIKELY (! parse_cbor_internal (false, tag_handler ))) 10909{ 10910return false; 10911} 10912} 10913} 10914 10915return sax -> end_array (); 10916} 10917 10918/*! 10919@param[in] len the length of the object or detail::unknown_size() for an 10920object of indefinite size 10921@param[in] tag_handler how CBOR tags should be treated 10922@return whether object creation completed 10923*/ 10924bool get_cbor_object (const std:: size_t len , 10925const cbor_tag_handler_t tag_handler ) 10926{ 10927if ( JSON_HEDLEY_UNLIKELY (! sax -> start_object ( len ))) 10928{ 10929return false; 10930} 10931 10932if ( len != 0 ) 10933{ 10934string_t key ; 10935if ( len != detail:: unknown_size ()) 10936{ 10937for (std:: size_t i = 0 ; i < len ; ++ i ) 10938{ 10939get (); 10940if ( JSON_HEDLEY_UNLIKELY (! get_cbor_string ( key ) || ! sax -> key ( key ))) 10941{ 10942return false; 10943} 10944 10945if ( JSON_HEDLEY_UNLIKELY (! parse_cbor_internal (true, tag_handler ))) 10946{ 10947return false; 10948} 10949key . clear (); 10950} 10951} 10952else 10953{ 10954while ( get () != 0xFF ) 10955{ 10956if ( JSON_HEDLEY_UNLIKELY (! get_cbor_string ( key ) || ! sax -> key ( key ))) 10957{ 10958return false; 10959} 10960 10961if ( JSON_HEDLEY_UNLIKELY (! parse_cbor_internal (true, tag_handler ))) 10962{ 10963return false; 10964} 10965key . clear (); 10966} 10967} 10968} 10969 10970return sax -> end_object (); 10971} 10972 10973///////////// 10974// MsgPack // 10975///////////// 10976 10977/*! 10978@return whether a valid MessagePack value was passed to the SAX parser 10979*/ 10980bool parse_msgpack_internal () 10981{ 10982switch ( get ()) 10983{ 10984// EOF 10985case char_traits < char_type > :: eof (): 10986return unexpect_eof (input_format_t:: msgpack , "value" ); 10987 10988// positive fixint 10989case 0x00 : 10990case 0x01 : 10991case 0x02 : 10992case 0x03 : 10993case 0x04 : 10994case 0x05 : 10995case 0x06 : 10996case 0x07 : 10997case 0x08 : 10998case 0x09 : 10999case 0x0A : 11000case 0x0B : 11001case 0x0C : 11002case 0x0D : 11003case 0x0E : 11004case 0x0F : 11005case 0x10 : 11006case 0x11 : 11007case 0x12 : 11008case 0x13 : 11009case 0x14 : 11010case 0x15 : 11011case 0x16 : 11012case 0x17 : 11013case 0x18 : 11014case 0x19 : 11015case 0x1A : 11016case 0x1B : 11017case 0x1C : 11018case 0x1D : 11019case 0x1E : 11020case 0x1F : 11021case 0x20 : 11022case 0x21 : 11023case 0x22 : 11024case 0x23 : 11025case 0x24 : 11026case 0x25 : 11027case 0x26 : 11028case 0x27 : 11029case 0x28 : 11030case 0x29 : 11031case 0x2A : 11032case 0x2B : 11033case 0x2C : 11034case 0x2D : 11035case 0x2E : 11036case 0x2F : 11037case 0x30 : 11038case 0x31 : 11039case 0x32 : 11040case 0x33 : 11041case 0x34 : 11042case 0x35 : 11043case 0x36 : 11044case 0x37 : 11045case 0x38 : 11046case 0x39 : 11047case 0x3A : 11048case 0x3B : 11049case 0x3C : 11050case 0x3D : 11051case 0x3E : 11052case 0x3F : 11053case 0x40 : 11054case 0x41 : 11055case 0x42 : 11056case 0x43 : 11057case 0x44 : 11058case 0x45 : 11059case 0x46 : 11060case 0x47 : 11061case 0x48 : 11062case 0x49 : 11063case 0x4A : 11064case 0x4B : 11065case 0x4C : 11066case 0x4D : 11067case 0x4E : 11068case 0x4F : 11069case 0x50 : 11070case 0x51 : 11071case 0x52 : 11072case 0x53 : 11073case 0x54 : 11074case 0x55 : 11075case 0x56 : 11076case 0x57 : 11077case 0x58 : 11078case 0x59 : 11079case 0x5A : 11080case 0x5B : 11081case 0x5C : 11082case 0x5D : 11083case 0x5E : 11084case 0x5F : 11085case 0x60 : 11086case 0x61 : 11087case 0x62 : 11088case 0x63 : 11089case 0x64 : 11090case 0x65 : 11091case 0x66 : 11092case 0x67 : 11093case 0x68 : 11094case 0x69 : 11095case 0x6A : 11096case 0x6B : 11097case 0x6C : 11098case 0x6D : 11099case 0x6E : 11100case 0x6F : 11101case 0x70 : 11102case 0x71 : 11103case 0x72 : 11104case 0x73 : 11105case 0x74 : 11106case 0x75 : 11107case 0x76 : 11108case 0x77 : 11109case 0x78 : 11110case 0x79 : 11111case 0x7A : 11112case 0x7B : 11113case 0x7C : 11114case 0x7D : 11115case 0x7E : 11116case 0x7F : 11117return sax -> number_unsigned ( static_cast < number_unsigned_t > ( current )); 11118 11119// fixmap 11120case 0x80 : 11121case 0x81 : 11122case 0x82 : 11123case 0x83 : 11124case 0x84 : 11125case 0x85 : 11126case 0x86 : 11127case 0x87 : 11128case 0x88 : 11129case 0x89 : 11130case 0x8A : 11131case 0x8B : 11132case 0x8C : 11133case 0x8D : 11134case 0x8E : 11135case 0x8F : 11136return get_msgpack_object ( conditional_static_cast < std:: size_t > ( static_cast < unsigned int > ( current ) & 0x0Fu )); 11137 11138// fixarray 11139case 0x90 : 11140case 0x91 : 11141case 0x92 : 11142case 0x93 : 11143case 0x94 : 11144case 0x95 : 11145case 0x96 : 11146case 0x97 : 11147case 0x98 : 11148case 0x99 : 11149case 0x9A : 11150case 0x9B : 11151case 0x9C : 11152case 0x9D : 11153case 0x9E : 11154case 0x9F : 11155return get_msgpack_array ( conditional_static_cast < std:: size_t > ( static_cast < unsigned int > ( current ) & 0x0Fu )); 11156 11157// fixstr 11158case 0xA0 : 11159case 0xA1 : 11160case 0xA2 : 11161case 0xA3 : 11162case 0xA4 : 11163case 0xA5 : 11164case 0xA6 : 11165case 0xA7 : 11166case 0xA8 : 11167case 0xA9 : 11168case 0xAA : 11169case 0xAB : 11170case 0xAC : 11171case 0xAD : 11172case 0xAE : 11173case 0xAF : 11174case 0xB0 : 11175case 0xB1 : 11176case 0xB2 : 11177case 0xB3 : 11178case 0xB4 : 11179case 0xB5 : 11180case 0xB6 : 11181case 0xB7 : 11182case 0xB8 : 11183case 0xB9 : 11184case 0xBA : 11185case 0xBB : 11186case 0xBC : 11187case 0xBD : 11188case 0xBE : 11189case 0xBF : 11190case 0xD9 : // str 8 11191case 0xDA : // str 16 11192case 0xDB : // str 32 11193{ 11194string_t s ; 11195return get_msgpack_string ( s ) && sax -> string ( s ); 11196} 11197 11198case 0xC0 : // nil 11199return sax -> null (); 11200 11201case 0xC2 : // false 11202return sax -> boolean (false); 11203 11204case 0xC3 : // true 11205return sax -> boolean (true); 11206 11207case 0xC4 : // bin 8 11208case 0xC5 : // bin 16 11209case 0xC6 : // bin 32 11210case 0xC7 : // ext 8 11211case 0xC8 : // ext 16 11212case 0xC9 : // ext 32 11213case 0xD4 : // fixext 1 11214case 0xD5 : // fixext 2 11215case 0xD6 : // fixext 4 11216case 0xD7 : // fixext 8 11217case 0xD8 : // fixext 16 11218{ 11219binary_t b ; 11220return get_msgpack_binary ( b ) && sax -> binary ( b ); 11221} 11222 11223case 0xCA : // float 32 11224{ 11225float number {}; 11226return get_number (input_format_t:: msgpack , number ) && sax -> number_float ( static_cast < number_float_t > ( number ), "" ); 11227} 11228 11229case 0xCB : // float 64 11230{ 11231double number {}; 11232return get_number (input_format_t:: msgpack , number ) && sax -> number_float ( static_cast < number_float_t > ( number ), "" ); 11233} 11234 11235case 0xCC : // uint 8 11236{ 11237std:: uint8_t number {}; 11238return get_number (input_format_t:: msgpack , number ) && sax -> number_unsigned ( number ); 11239} 11240 11241case 0xCD : // uint 16 11242{ 11243std:: uint16_t number {}; 11244return get_number (input_format_t:: msgpack , number ) && sax -> number_unsigned ( number ); 11245} 11246 11247case 0xCE : // uint 32 11248{ 11249std:: uint32_t number {}; 11250return get_number (input_format_t:: msgpack , number ) && sax -> number_unsigned ( number ); 11251} 11252 11253case 0xCF : // uint 64 11254{ 11255std:: uint64_t number {}; 11256return get_number (input_format_t:: msgpack , number ) && sax -> number_unsigned ( number ); 11257} 11258 11259case 0xD0 : // int 8 11260{ 11261std:: int8_t number {}; 11262return get_number (input_format_t:: msgpack , number ) && sax -> number_integer ( number ); 11263} 11264 11265case 0xD1 : // int 16 11266{ 11267std:: int16_t number {}; 11268return get_number (input_format_t:: msgpack , number ) && sax -> number_integer ( number ); 11269} 11270 11271case 0xD2 : // int 32 11272{ 11273std:: int32_t number {}; 11274return get_number (input_format_t:: msgpack , number ) && sax -> number_integer ( number ); 11275} 11276 11277case 0xD3 : // int 64 11278{ 11279std:: int64_t number {}; 11280return get_number (input_format_t:: msgpack , number ) && sax -> number_integer ( number ); 11281} 11282 11283case 0xDC : // array 16 11284{ 11285std:: uint16_t len {}; 11286return get_number (input_format_t:: msgpack , len ) && get_msgpack_array ( static_cast < std:: size_t > ( len )); 11287} 11288 11289case 0xDD : // array 32 11290{ 11291std:: uint32_t len {}; 11292return get_number (input_format_t:: msgpack , len ) && get_msgpack_array ( conditional_static_cast < std:: size_t > ( len )); 11293} 11294 11295case 0xDE : // map 16 11296{ 11297std:: uint16_t len {}; 11298return get_number (input_format_t:: msgpack , len ) && get_msgpack_object ( static_cast < std:: size_t > ( len )); 11299} 11300 11301case 0xDF : // map 32 11302{ 11303std:: uint32_t len {}; 11304return get_number (input_format_t:: msgpack , len ) && get_msgpack_object ( conditional_static_cast < std:: size_t > ( len )); 11305} 11306 11307// negative fixint 11308case 0xE0 : 11309case 0xE1 : 11310case 0xE2 : 11311case 0xE3 : 11312case 0xE4 : 11313case 0xE5 : 11314case 0xE6 : 11315case 0xE7 : 11316case 0xE8 : 11317case 0xE9 : 11318case 0xEA : 11319case 0xEB : 11320case 0xEC : 11321case 0xED : 11322case 0xEE : 11323case 0xEF : 11324case 0xF0 : 11325case 0xF1 : 11326case 0xF2 : 11327case 0xF3 : 11328case 0xF4 : 11329case 0xF5 : 11330case 0xF6 : 11331case 0xF7 : 11332case 0xF8 : 11333case 0xF9 : 11334case 0xFA : 11335case 0xFB : 11336case 0xFC : 11337case 0xFD : 11338case 0xFE : 11339case 0xFF : 11340return sax -> number_integer ( static_cast < std:: int8_t > ( current )); 11341 11342default: // anything else 11343{ 11344auto last_token = get_token_string (); 11345return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 11346exception_message (input_format_t:: msgpack , concat ( "invalid byte: 0x" , last_token ), "value" ), nullptr )); 11347} 11348} 11349} 11350 11351/*! 11352@brief reads a MessagePack string 11353 11354This function first reads starting bytes to determine the expected 11355string length and then copies this number of bytes into a string. 11356 11357@param[out] result created string 11358 11359@return whether string creation completed 11360*/ 11361bool get_msgpack_string ( string_t & result ) 11362{ 11363if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof (input_format_t:: msgpack , "string" ))) 11364{ 11365return false; 11366} 11367 11368switch ( current ) 11369{ 11370// fixstr 11371case 0xA0 : 11372case 0xA1 : 11373case 0xA2 : 11374case 0xA3 : 11375case 0xA4 : 11376case 0xA5 : 11377case 0xA6 : 11378case 0xA7 : 11379case 0xA8 : 11380case 0xA9 : 11381case 0xAA : 11382case 0xAB : 11383case 0xAC : 11384case 0xAD : 11385case 0xAE : 11386case 0xAF : 11387case 0xB0 : 11388case 0xB1 : 11389case 0xB2 : 11390case 0xB3 : 11391case 0xB4 : 11392case 0xB5 : 11393case 0xB6 : 11394case 0xB7 : 11395case 0xB8 : 11396case 0xB9 : 11397case 0xBA : 11398case 0xBB : 11399case 0xBC : 11400case 0xBD : 11401case 0xBE : 11402case 0xBF : 11403{ 11404return get_string (input_format_t:: msgpack , static_cast < unsigned int > ( current ) & 0x1Fu , result ); 11405} 11406 11407case 0xD9 : // str 8 11408{ 11409std:: uint8_t len {}; 11410return get_number (input_format_t:: msgpack , len ) && get_string (input_format_t:: msgpack , len , result ); 11411} 11412 11413case 0xDA : // str 16 11414{ 11415std:: uint16_t len {}; 11416return get_number (input_format_t:: msgpack , len ) && get_string (input_format_t:: msgpack , len , result ); 11417} 11418 11419case 0xDB : // str 32 11420{ 11421std:: uint32_t len {}; 11422return get_number (input_format_t:: msgpack , len ) && get_string (input_format_t:: msgpack , len , result ); 11423} 11424 11425default: 11426{ 11427auto last_token = get_token_string (); 11428return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 113 , chars_read , 11429exception_message (input_format_t:: msgpack , concat ( "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" , last_token ), "string" ), nullptr )); 11430} 11431} 11432} 11433 11434/*! 11435@brief reads a MessagePack byte array 11436 11437This function first reads starting bytes to determine the expected 11438byte array length and then copies this number of bytes into a byte array. 11439 11440@param[out] result created byte array 11441 11442@return whether byte array creation completed 11443*/ 11444bool get_msgpack_binary ( binary_t & result ) 11445{ 11446// helper function to set the subtype 11447auto assign_and_return_true = [ & result ](std:: int8_t subtype ) 11448{ 11449result . set_subtype ( static_cast < std:: uint8_t > ( subtype )); 11450return true; 11451}; 11452 11453switch ( current ) 11454{ 11455case 0xC4 : // bin 8 11456{ 11457std:: uint8_t len {}; 11458return get_number (input_format_t:: msgpack , len ) && 11459get_binary (input_format_t:: msgpack , len , result ); 11460} 11461 11462case 0xC5 : // bin 16 11463{ 11464std:: uint16_t len {}; 11465return get_number (input_format_t:: msgpack , len ) && 11466get_binary (input_format_t:: msgpack , len , result ); 11467} 11468 11469case 0xC6 : // bin 32 11470{ 11471std:: uint32_t len {}; 11472return get_number (input_format_t:: msgpack , len ) && 11473get_binary (input_format_t:: msgpack , len , result ); 11474} 11475 11476case 0xC7 : // ext 8 11477{ 11478std:: uint8_t len {}; 11479std:: int8_t subtype {}; 11480return get_number (input_format_t:: msgpack , len ) && 11481get_number (input_format_t:: msgpack , subtype ) && 11482get_binary (input_format_t:: msgpack , len , result ) && 11483assign_and_return_true ( subtype ); 11484} 11485 11486case 0xC8 : // ext 16 11487{ 11488std:: uint16_t len {}; 11489std:: int8_t subtype {}; 11490return get_number (input_format_t:: msgpack , len ) && 11491get_number (input_format_t:: msgpack , subtype ) && 11492get_binary (input_format_t:: msgpack , len , result ) && 11493assign_and_return_true ( subtype ); 11494} 11495 11496case 0xC9 : // ext 32 11497{ 11498std:: uint32_t len {}; 11499std:: int8_t subtype {}; 11500return get_number (input_format_t:: msgpack , len ) && 11501get_number (input_format_t:: msgpack , subtype ) && 11502get_binary (input_format_t:: msgpack , len , result ) && 11503assign_and_return_true ( subtype ); 11504} 11505 11506case 0xD4 : // fixext 1 11507{ 11508std:: int8_t subtype {}; 11509return get_number (input_format_t:: msgpack , subtype ) && 11510get_binary (input_format_t:: msgpack , 1 , result ) && 11511assign_and_return_true ( subtype ); 11512} 11513 11514case 0xD5 : // fixext 2 11515{ 11516std:: int8_t subtype {}; 11517return get_number (input_format_t:: msgpack , subtype ) && 11518get_binary (input_format_t:: msgpack , 2 , result ) && 11519assign_and_return_true ( subtype ); 11520} 11521 11522case 0xD6 : // fixext 4 11523{ 11524std:: int8_t subtype {}; 11525return get_number (input_format_t:: msgpack , subtype ) && 11526get_binary (input_format_t:: msgpack , 4 , result ) && 11527assign_and_return_true ( subtype ); 11528} 11529 11530case 0xD7 : // fixext 8 11531{ 11532std:: int8_t subtype {}; 11533return get_number (input_format_t:: msgpack , subtype ) && 11534get_binary (input_format_t:: msgpack , 8 , result ) && 11535assign_and_return_true ( subtype ); 11536} 11537 11538case 0xD8 : // fixext 16 11539{ 11540std:: int8_t subtype {}; 11541return get_number (input_format_t:: msgpack , subtype ) && 11542get_binary (input_format_t:: msgpack , 16 , result ) && 11543assign_and_return_true ( subtype ); 11544} 11545 11546default: // LCOV_EXCL_LINE 11547return false; // LCOV_EXCL_LINE 11548} 11549} 11550 11551/*! 11552@param[in] len the length of the array 11553@return whether array creation completed 11554*/ 11555bool get_msgpack_array (const std:: size_t len ) 11556{ 11557if ( JSON_HEDLEY_UNLIKELY (! sax -> start_array ( len ))) 11558{ 11559return false; 11560} 11561 11562for (std:: size_t i = 0 ; i < len ; ++ i ) 11563{ 11564if ( JSON_HEDLEY_UNLIKELY (! parse_msgpack_internal ())) 11565{ 11566return false; 11567} 11568} 11569 11570return sax -> end_array (); 11571} 11572 11573/*! 11574@param[in] len the length of the object 11575@return whether object creation completed 11576*/ 11577bool get_msgpack_object (const std:: size_t len ) 11578{ 11579if ( JSON_HEDLEY_UNLIKELY (! sax -> start_object ( len ))) 11580{ 11581return false; 11582} 11583 11584string_t key ; 11585for (std:: size_t i = 0 ; i < len ; ++ i ) 11586{ 11587get (); 11588if ( JSON_HEDLEY_UNLIKELY (! get_msgpack_string ( key ) || ! sax -> key ( key ))) 11589{ 11590return false; 11591} 11592 11593if ( JSON_HEDLEY_UNLIKELY (! parse_msgpack_internal ())) 11594{ 11595return false; 11596} 11597key . clear (); 11598} 11599 11600return sax -> end_object (); 11601} 11602 11603//////////// 11604// UBJSON // 11605//////////// 11606 11607/*! 11608@param[in] get_char whether a new character should be retrieved from the 11609input (true, default) or whether the last read 11610character should be considered instead 11611 11612@return whether a valid UBJSON value was passed to the SAX parser 11613*/ 11614bool parse_ubjson_internal (const bool get_char = true) 11615{ 11616return get_ubjson_value ( get_char ? get_ignore_noop () : current ); 11617} 11618 11619/*! 11620@brief reads a UBJSON string 11621 11622This function is either called after reading the 'S' byte explicitly 11623indicating a string, or in case of an object key where the 'S' byte can be 11624left out. 11625 11626@param[out] result created string 11627@param[in] get_char whether a new character should be retrieved from the 11628input (true, default) or whether the last read 11629character should be considered instead 11630 11631@return whether string creation completed 11632*/ 11633bool get_ubjson_string ( string_t & result , const bool get_char = true) 11634{ 11635if ( get_char ) 11636{ 11637get (); // TODO(niels): may we ignore N here? 11638} 11639 11640if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( input_format , "value" ))) 11641{ 11642return false; 11643} 11644 11645switch ( current ) 11646{ 11647case 'U' : 11648{ 11649std:: uint8_t len {}; 11650return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11651} 11652 11653case 'i' : 11654{ 11655std:: int8_t len {}; 11656return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11657} 11658 11659case 'I' : 11660{ 11661std:: int16_t len {}; 11662return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11663} 11664 11665case 'l' : 11666{ 11667std:: int32_t len {}; 11668return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11669} 11670 11671case 'L' : 11672{ 11673std:: int64_t len {}; 11674return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11675} 11676 11677case 'u' : 11678{ 11679if ( input_format != input_format_t:: bjdata ) 11680{ 11681break; 11682} 11683std:: uint16_t len {}; 11684return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11685} 11686 11687case 'm' : 11688{ 11689if ( input_format != input_format_t:: bjdata ) 11690{ 11691break; 11692} 11693std:: uint32_t len {}; 11694return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11695} 11696 11697case 'M' : 11698{ 11699if ( input_format != input_format_t:: bjdata ) 11700{ 11701break; 11702} 11703std:: uint64_t len {}; 11704return get_number ( input_format , len ) && get_string ( input_format , len , result ); 11705} 11706 11707default: 11708break; 11709} 11710auto last_token = get_token_string (); 11711std:: string message ; 11712 11713if ( input_format != input_format_t:: bjdata ) 11714{ 11715message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token ; 11716} 11717else 11718{ 11719message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token ; 11720} 11721return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 113 , chars_read , exception_message ( input_format , message , "string" ), nullptr )); 11722} 11723 11724/*! 11725@param[out] dim an integer vector storing the ND array dimensions 11726@return whether reading ND array size vector is successful 11727*/ 11728bool get_ubjson_ndarray_size (std:: vector < size_t >& dim ) 11729{ 11730std:: pair < std:: size_t , char_int_type > size_and_type ; 11731size_t dimlen = 0 ; 11732bool no_ndarray = true; 11733 11734if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_size_type ( size_and_type , no_ndarray ))) 11735{ 11736return false; 11737} 11738 11739if ( size_and_type . first != npos ) 11740{ 11741if ( size_and_type . second != 0 ) 11742{ 11743if ( size_and_type . second != 'N' ) 11744{ 11745for (std:: size_t i = 0 ; i < size_and_type . first ; ++ i ) 11746{ 11747if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_size_value ( dimlen , no_ndarray , size_and_type . second ))) 11748{ 11749return false; 11750} 11751dim . push_back ( dimlen ); 11752} 11753} 11754} 11755else 11756{ 11757for (std:: size_t i = 0 ; i < size_and_type . first ; ++ i ) 11758{ 11759if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_size_value ( dimlen , no_ndarray ))) 11760{ 11761return false; 11762} 11763dim . push_back ( dimlen ); 11764} 11765} 11766} 11767else 11768{ 11769while ( current != ']' ) 11770{ 11771if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_size_value ( dimlen , no_ndarray , current ))) 11772{ 11773return false; 11774} 11775dim . push_back ( dimlen ); 11776get_ignore_noop (); 11777} 11778} 11779return true; 11780} 11781 11782/*! 11783@param[out] result determined size 11784@param[in,out] is_ndarray for input, `true` means already inside an ndarray vector 11785or ndarray dimension is not allowed; `false` means ndarray 11786is allowed; for output, `true` means an ndarray is found; 11787is_ndarray can only return `true` when its initial value 11788is `false` 11789@param[in] prefix type marker if already read, otherwise set to 0 11790 11791@return whether size determination completed 11792*/ 11793bool get_ubjson_size_value (std:: size_t & result , bool & is_ndarray , char_int_type prefix = 0 ) 11794{ 11795if ( prefix == 0 ) 11796{ 11797prefix = get_ignore_noop (); 11798} 11799 11800switch ( prefix ) 11801{ 11802case 'U' : 11803{ 11804std:: uint8_t number {}; 11805if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11806{ 11807return false; 11808} 11809result = static_cast < std:: size_t > ( number ); 11810return true; 11811} 11812 11813case 'i' : 11814{ 11815std:: int8_t number {}; 11816if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11817{ 11818return false; 11819} 11820if ( number < 0 ) 11821{ 11822return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 113 , chars_read , 11823exception_message ( input_format , "count in an optimized container must be positive" , "size" ), nullptr )); 11824} 11825result = static_cast < std:: size_t > ( number ); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char 11826return true; 11827} 11828 11829case 'I' : 11830{ 11831std:: int16_t number {}; 11832if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11833{ 11834return false; 11835} 11836if ( number < 0 ) 11837{ 11838return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 113 , chars_read , 11839exception_message ( input_format , "count in an optimized container must be positive" , "size" ), nullptr )); 11840} 11841result = static_cast < std:: size_t > ( number ); 11842return true; 11843} 11844 11845case 'l' : 11846{ 11847std:: int32_t number {}; 11848if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11849{ 11850return false; 11851} 11852if ( number < 0 ) 11853{ 11854return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 113 , chars_read , 11855exception_message ( input_format , "count in an optimized container must be positive" , "size" ), nullptr )); 11856} 11857result = static_cast < std:: size_t > ( number ); 11858return true; 11859} 11860 11861case 'L' : 11862{ 11863std:: int64_t number {}; 11864if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11865{ 11866return false; 11867} 11868if ( number < 0 ) 11869{ 11870return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 113 , chars_read , 11871exception_message ( input_format , "count in an optimized container must be positive" , "size" ), nullptr )); 11872} 11873if (! value_in_range_of < std:: size_t > ( number )) 11874{ 11875return sax -> parse_error ( chars_read , get_token_string (), out_of_range:: create ( 408 , 11876exception_message ( input_format , "integer value overflow" , "size" ), nullptr )); 11877} 11878result = static_cast < std:: size_t > ( number ); 11879return true; 11880} 11881 11882case 'u' : 11883{ 11884if ( input_format != input_format_t:: bjdata ) 11885{ 11886break; 11887} 11888std:: uint16_t number {}; 11889if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11890{ 11891return false; 11892} 11893result = static_cast < std:: size_t > ( number ); 11894return true; 11895} 11896 11897case 'm' : 11898{ 11899if ( input_format != input_format_t:: bjdata ) 11900{ 11901break; 11902} 11903std:: uint32_t number {}; 11904if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11905{ 11906return false; 11907} 11908result = conditional_static_cast < std:: size_t > ( number ); 11909return true; 11910} 11911 11912case 'M' : 11913{ 11914if ( input_format != input_format_t:: bjdata ) 11915{ 11916break; 11917} 11918std:: uint64_t number {}; 11919if ( JSON_HEDLEY_UNLIKELY (! get_number ( input_format , number ))) 11920{ 11921return false; 11922} 11923if (! value_in_range_of < std:: size_t > ( number )) 11924{ 11925return sax -> parse_error ( chars_read , get_token_string (), out_of_range:: create ( 408 , 11926exception_message ( input_format , "integer value overflow" , "size" ), nullptr )); 11927} 11928result = detail:: conditional_static_cast < std:: size_t > ( number ); 11929return true; 11930} 11931 11932case '[' : 11933{ 11934if ( input_format != input_format_t:: bjdata ) 11935{ 11936break; 11937} 11938if ( is_ndarray ) // ndarray dimensional vector can only contain integers, and can not embed another array 11939{ 11940return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 113 , chars_read , exception_message ( input_format , "ndarray dimensional vector is not allowed" , "size" ), nullptr )); 11941} 11942std:: vector < size_t > dim ; 11943if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_ndarray_size ( dim ))) 11944{ 11945return false; 11946} 11947if ( dim . size () == 1 || ( dim . size () == 2 && dim . at ( 0 ) == 1 )) // return normal array size if 1D row vector 11948{ 11949result = dim . at ( dim . size () - 1 ); 11950return true; 11951} 11952if (! dim . empty ()) // if ndarray, convert to an object in JData annotated array format 11953{ 11954for ( auto i : dim ) // test if any dimension in an ndarray is 0, if so, return a 1D empty container 11955{ 11956if ( i == 0 ) 11957{ 11958result = 0 ; 11959return true; 11960} 11961} 11962 11963string_t key = "_ArraySize_" ; 11964if ( JSON_HEDLEY_UNLIKELY (! sax -> start_object ( 3 ) || ! sax -> key ( key ) || ! sax -> start_array ( dim . size ()))) 11965{ 11966return false; 11967} 11968result = 1 ; 11969for ( auto i : dim ) 11970{ 11971result *= i ; 11972if ( result == 0 || result == npos ) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type() 11973{ 11974return sax -> parse_error ( chars_read , get_token_string (), out_of_range:: create ( 408 , exception_message ( input_format , "excessive ndarray size caused overflow" , "size" ), nullptr )); 11975} 11976if ( JSON_HEDLEY_UNLIKELY (! sax -> number_unsigned ( static_cast < number_unsigned_t > ( i )))) 11977{ 11978return false; 11979} 11980} 11981is_ndarray = true; 11982return sax -> end_array (); 11983} 11984result = 0 ; 11985return true; 11986} 11987 11988default: 11989break; 11990} 11991auto last_token = get_token_string (); 11992std:: string message ; 11993 11994if ( input_format != input_format_t:: bjdata ) 11995{ 11996message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token ; 11997} 11998else 11999{ 12000message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token ; 12001} 12002return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 113 , chars_read , exception_message ( input_format , message , "size" ), nullptr )); 12003} 12004 12005/*! 12006@brief determine the type and size for a container 12007 12008In the optimized UBJSON format, a type and a size can be provided to allow 12009for a more compact representation. 12010 12011@param[out] result pair of the size and the type 12012@param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector 12013 12014@return whether pair creation completed 12015*/ 12016bool get_ubjson_size_type (std:: pair < std:: size_t , char_int_type >& result , bool inside_ndarray = false) 12017{ 12018result . first = npos ; // size 12019result . second = 0 ; // type 12020bool is_ndarray = false; 12021 12022get_ignore_noop (); 12023 12024if ( current == '$' ) 12025{ 12026result . second = get (); // must not ignore 'N', because 'N' maybe the type 12027if ( input_format == input_format_t:: bjdata 12028&& JSON_HEDLEY_UNLIKELY (std:: binary_search ( bjd_optimized_type_markers . begin (), bjd_optimized_type_markers . end (), result . second ))) 12029{ 12030auto last_token = get_token_string (); 12031return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 12032exception_message ( input_format , concat ( "marker 0x" , last_token , " is not a permitted optimized array type" ), "type" ), nullptr )); 12033} 12034 12035if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( input_format , "type" ))) 12036{ 12037return false; 12038} 12039 12040get_ignore_noop (); 12041if ( JSON_HEDLEY_UNLIKELY ( current != '#' )) 12042{ 12043if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( input_format , "value" ))) 12044{ 12045return false; 12046} 12047auto last_token = get_token_string (); 12048return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 12049exception_message ( input_format , concat ( "expected '#' after type information; last byte: 0x" , last_token ), "size" ), nullptr )); 12050} 12051 12052const bool is_error = get_ubjson_size_value ( result . first , is_ndarray ); 12053if ( input_format == input_format_t:: bjdata && is_ndarray ) 12054{ 12055if ( inside_ndarray ) 12056{ 12057return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 112 , chars_read , 12058exception_message ( input_format , "ndarray can not be recursive" , "size" ), nullptr )); 12059} 12060result . second |= ( 1 << 8 ); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters 12061} 12062return is_error ; 12063} 12064 12065if ( current == '#' ) 12066{ 12067const bool is_error = get_ubjson_size_value ( result . first , is_ndarray ); 12068if ( input_format == input_format_t:: bjdata && is_ndarray ) 12069{ 12070return sax -> parse_error ( chars_read , get_token_string (), parse_error:: create ( 112 , chars_read , 12071exception_message ( input_format , "ndarray requires both type and size" , "size" ), nullptr )); 12072} 12073return is_error ; 12074} 12075 12076return true; 12077} 12078 12079/*! 12080@param prefix the previously read or set type prefix 12081@return whether value creation completed 12082*/ 12083bool get_ubjson_value (const char_int_type prefix ) 12084{ 12085switch ( prefix ) 12086{ 12087case char_traits < char_type > :: eof (): // EOF 12088return unexpect_eof ( input_format , "value" ); 12089 12090case 'T' : // true 12091return sax -> boolean (true); 12092case 'F' : // false 12093return sax -> boolean (false); 12094 12095case 'Z' : // null 12096return sax -> null (); 12097 12098case 'B' : // byte 12099{ 12100if ( input_format != input_format_t:: bjdata ) 12101{ 12102break; 12103} 12104std:: uint8_t number {}; 12105return get_number ( input_format , number ) && sax -> number_unsigned ( number ); 12106} 12107 12108case 'U' : 12109{ 12110std:: uint8_t number {}; 12111return get_number ( input_format , number ) && sax -> number_unsigned ( number ); 12112} 12113 12114case 'i' : 12115{ 12116std:: int8_t number {}; 12117return get_number ( input_format , number ) && sax -> number_integer ( number ); 12118} 12119 12120case 'I' : 12121{ 12122std:: int16_t number {}; 12123return get_number ( input_format , number ) && sax -> number_integer ( number ); 12124} 12125 12126case 'l' : 12127{ 12128std:: int32_t number {}; 12129return get_number ( input_format , number ) && sax -> number_integer ( number ); 12130} 12131 12132case 'L' : 12133{ 12134std:: int64_t number {}; 12135return get_number ( input_format , number ) && sax -> number_integer ( number ); 12136} 12137 12138case 'u' : 12139{ 12140if ( input_format != input_format_t:: bjdata ) 12141{ 12142break; 12143} 12144std:: uint16_t number {}; 12145return get_number ( input_format , number ) && sax -> number_unsigned ( number ); 12146} 12147 12148case 'm' : 12149{ 12150if ( input_format != input_format_t:: bjdata ) 12151{ 12152break; 12153} 12154std:: uint32_t number {}; 12155return get_number ( input_format , number ) && sax -> number_unsigned ( number ); 12156} 12157 12158case 'M' : 12159{ 12160if ( input_format != input_format_t:: bjdata ) 12161{ 12162break; 12163} 12164std:: uint64_t number {}; 12165return get_number ( input_format , number ) && sax -> number_unsigned ( number ); 12166} 12167 12168case 'h' : 12169{ 12170if ( input_format != input_format_t:: bjdata ) 12171{ 12172break; 12173} 12174const auto byte1_raw = get (); 12175if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( input_format , "number" ))) 12176{ 12177return false; 12178} 12179const auto byte2_raw = get (); 12180if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( input_format , "number" ))) 12181{ 12182return false; 12183} 12184 12185const auto byte1 = static_cast < unsigned char > ( byte1_raw ); 12186const auto byte2 = static_cast < unsigned char > ( byte2_raw ); 12187 12188// code from RFC 7049, Appendix D, Figure 3: 12189// As half-precision floating-point numbers were only added 12190// to IEEE 754 in 2008, today's programming platforms often 12191// still only have limited support for them. It is very 12192// easy to include at least decoding support for them even 12193// without such support. An example of a small decoder for 12194// half-precision floating-point numbers in the C language 12195// is shown in Fig. 3. 12196const auto half = static_cast < unsigned int > (( byte2 << 8u ) + byte1 ); 12197const double val = [ & half ] 12198{ 12199const int exp = ( half >> 10u ) & 0x1Fu ; 12200const unsigned int mant = half & 0x3FFu ; 12201JSON_ASSERT ( 0 <= exp && exp <= 32 ); 12202JSON_ASSERT ( mant <= 1024 ); 12203switch ( exp ) 12204{ 12205case 0 : 12206return std:: ldexp ( mant , -24 ); 12207case 31 : 12208return ( mant == 0 ) 12209? std:: numeric_limits < double > :: infinity () 12210: std:: numeric_limits < double > :: quiet_NaN (); 12211default: 12212return std:: ldexp ( mant + 1024 , exp - 25 ); 12213} 12214}(); 12215return sax -> number_float (( half & 0x8000u ) != 0 12216? static_cast < number_float_t > ( - val ) 12217: static_cast < number_float_t > ( val ), "" ); 12218} 12219 12220case 'd' : 12221{ 12222float number {}; 12223return get_number ( input_format , number ) && sax -> number_float ( static_cast < number_float_t > ( number ), "" ); 12224} 12225 12226case 'D' : 12227{ 12228double number {}; 12229return get_number ( input_format , number ) && sax -> number_float ( static_cast < number_float_t > ( number ), "" ); 12230} 12231 12232case 'H' : 12233{ 12234return get_ubjson_high_precision_number (); 12235} 12236 12237case 'C' : // char 12238{ 12239get (); 12240if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( input_format , "char" ))) 12241{ 12242return false; 12243} 12244if ( JSON_HEDLEY_UNLIKELY ( current > 127 )) 12245{ 12246auto last_token = get_token_string (); 12247return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 113 , chars_read , 12248exception_message ( input_format , concat ( "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" , last_token ), "char" ), nullptr )); 12249} 12250string_t s ( 1 , static_cast < typename string_t:: value_type > ( current )); 12251return sax -> string ( s ); 12252} 12253 12254case 'S' : // string 12255{ 12256string_t s ; 12257return get_ubjson_string ( s ) && sax -> string ( s ); 12258} 12259 12260case '[' : // array 12261return get_ubjson_array (); 12262 12263case '{' : // object 12264return get_ubjson_object (); 12265 12266default: // anything else 12267break; 12268} 12269auto last_token = get_token_string (); 12270return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , exception_message ( input_format , "invalid byte: 0x" + last_token , "value" ), nullptr )); 12271} 12272 12273/*! 12274@return whether array creation completed 12275*/ 12276bool get_ubjson_array () 12277{ 12278std:: pair < std:: size_t , char_int_type > size_and_type ; 12279if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_size_type ( size_and_type ))) 12280{ 12281return false; 12282} 12283 12284// if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): 12285// {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} 12286 12287if ( input_format == input_format_t:: bjdata && size_and_type . first != npos && ( size_and_type . second & ( 1 << 8 )) != 0 ) 12288{ 12289size_and_type . second &= ~( static_cast < char_int_type > ( 1 ) << 8 ); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker 12290auto it = std:: lower_bound ( bjd_types_map . begin (), bjd_types_map . end (), size_and_type . second , [](const bjd_type & p , char_int_type t ) 12291{ 12292return p . first < t ; 12293}); 12294string_t key = "_ArrayType_" ; 12295if ( JSON_HEDLEY_UNLIKELY ( it == bjd_types_map . end () || it -> first != size_and_type . second )) 12296{ 12297auto last_token = get_token_string (); 12298return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 12299exception_message ( input_format , "invalid byte: 0x" + last_token , "type" ), nullptr )); 12300} 12301 12302string_t type = it -> second ; // sax->string() takes a reference 12303if ( JSON_HEDLEY_UNLIKELY (! sax -> key ( key ) || ! sax -> string ( type ))) 12304{ 12305return false; 12306} 12307 12308if ( size_and_type . second == 'C' || size_and_type . second == 'B' ) 12309{ 12310size_and_type . second = 'U' ; 12311} 12312 12313key = "_ArrayData_" ; 12314if ( JSON_HEDLEY_UNLIKELY (! sax -> key ( key ) || ! sax -> start_array ( size_and_type . first ) )) 12315{ 12316return false; 12317} 12318 12319for (std:: size_t i = 0 ; i < size_and_type . first ; ++ i ) 12320{ 12321if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_value ( size_and_type . second ))) 12322{ 12323return false; 12324} 12325} 12326 12327return ( sax -> end_array () && sax -> end_object ()); 12328} 12329 12330// If BJData type marker is 'B' decode as binary 12331if ( input_format == input_format_t:: bjdata && size_and_type . first != npos && size_and_type . second == 'B' ) 12332{ 12333binary_t result ; 12334return get_binary ( input_format , size_and_type . first , result ) && sax -> binary ( result ); 12335} 12336 12337if ( size_and_type . first != npos ) 12338{ 12339if ( JSON_HEDLEY_UNLIKELY (! sax -> start_array ( size_and_type . first ))) 12340{ 12341return false; 12342} 12343 12344if ( size_and_type . second != 0 ) 12345{ 12346if ( size_and_type . second != 'N' ) 12347{ 12348for (std:: size_t i = 0 ; i < size_and_type . first ; ++ i ) 12349{ 12350if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_value ( size_and_type . second ))) 12351{ 12352return false; 12353} 12354} 12355} 12356} 12357else 12358{ 12359for (std:: size_t i = 0 ; i < size_and_type . first ; ++ i ) 12360{ 12361if ( JSON_HEDLEY_UNLIKELY (! parse_ubjson_internal ())) 12362{ 12363return false; 12364} 12365} 12366} 12367} 12368else 12369{ 12370if ( JSON_HEDLEY_UNLIKELY (! sax -> start_array (detail:: unknown_size ()))) 12371{ 12372return false; 12373} 12374 12375while ( current != ']' ) 12376{ 12377if ( JSON_HEDLEY_UNLIKELY (! parse_ubjson_internal (false))) 12378{ 12379return false; 12380} 12381get_ignore_noop (); 12382} 12383} 12384 12385return sax -> end_array (); 12386} 12387 12388/*! 12389@return whether object creation completed 12390*/ 12391bool get_ubjson_object () 12392{ 12393std:: pair < std:: size_t , char_int_type > size_and_type ; 12394if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_size_type ( size_and_type ))) 12395{ 12396return false; 12397} 12398 12399// do not accept ND-array size in objects in BJData 12400if ( input_format == input_format_t:: bjdata && size_and_type . first != npos && ( size_and_type . second & ( 1 << 8 )) != 0 ) 12401{ 12402auto last_token = get_token_string (); 12403return sax -> parse_error ( chars_read , last_token , parse_error:: create ( 112 , chars_read , 12404exception_message ( input_format , "BJData object does not support ND-array size in optimized format" , "object" ), nullptr )); 12405} 12406 12407string_t key ; 12408if ( size_and_type . first != npos ) 12409{ 12410if ( JSON_HEDLEY_UNLIKELY (! sax -> start_object ( size_and_type . first ))) 12411{ 12412return false; 12413} 12414 12415if ( size_and_type . second != 0 ) 12416{ 12417for (std:: size_t i = 0 ; i < size_and_type . first ; ++ i ) 12418{ 12419if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_string ( key ) || ! sax -> key ( key ))) 12420{ 12421return false; 12422} 12423if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_value ( size_and_type . second ))) 12424{ 12425return false; 12426} 12427key . clear (); 12428} 12429} 12430else 12431{ 12432for (std:: size_t i = 0 ; i < size_and_type . first ; ++ i ) 12433{ 12434if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_string ( key ) || ! sax -> key ( key ))) 12435{ 12436return false; 12437} 12438if ( JSON_HEDLEY_UNLIKELY (! parse_ubjson_internal ())) 12439{ 12440return false; 12441} 12442key . clear (); 12443} 12444} 12445} 12446else 12447{ 12448if ( JSON_HEDLEY_UNLIKELY (! sax -> start_object (detail:: unknown_size ()))) 12449{ 12450return false; 12451} 12452 12453while ( current != '}' ) 12454{ 12455if ( JSON_HEDLEY_UNLIKELY (! get_ubjson_string ( key , false) || ! sax -> key ( key ))) 12456{ 12457return false; 12458} 12459if ( JSON_HEDLEY_UNLIKELY (! parse_ubjson_internal ())) 12460{ 12461return false; 12462} 12463get_ignore_noop (); 12464key . clear (); 12465} 12466} 12467 12468return sax -> end_object (); 12469} 12470 12471// Note, no reader for UBJSON binary types is implemented because they do 12472// not exist 12473 12474bool get_ubjson_high_precision_number () 12475{ 12476// get size of following number string 12477std:: size_t size {}; 12478bool no_ndarray = true; 12479auto res = get_ubjson_size_value ( size , no_ndarray ); 12480if ( JSON_HEDLEY_UNLIKELY (! res )) 12481{ 12482return res ; 12483} 12484 12485// get number string 12486std:: vector < char > number_vector ; 12487for (std:: size_t i = 0 ; i < size ; ++ i ) 12488{ 12489get (); 12490if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( input_format , "number" ))) 12491{ 12492return false; 12493} 12494number_vector . push_back ( static_cast < char > ( current )); 12495} 12496 12497// parse number string 12498using ia_type = decltype(detail:: input_adapter ( number_vector )); 12499auto number_lexer = detail:: lexer < BasicJsonType , ia_type > (detail:: input_adapter ( number_vector ), false); 12500const auto result_number = number_lexer . scan (); 12501const auto number_string = number_lexer . get_token_string (); 12502const auto result_remainder = number_lexer . scan (); 12503 12504using token_type = typename detail:: lexer_base < BasicJsonType > :: token_type ; 12505 12506if ( JSON_HEDLEY_UNLIKELY ( result_remainder != token_type:: end_of_input )) 12507{ 12508return sax -> parse_error ( chars_read , number_string , parse_error:: create ( 115 , chars_read , 12509exception_message ( input_format , concat ( "invalid number text: " , number_lexer . get_token_string ()), "high-precision number" ), nullptr )); 12510} 12511 12512switch ( result_number ) 12513{ 12514case token_type:: value_integer : 12515return sax -> number_integer ( number_lexer . get_number_integer ()); 12516case token_type:: value_unsigned : 12517return sax -> number_unsigned ( number_lexer . get_number_unsigned ()); 12518case token_type:: value_float : 12519return sax -> number_float ( number_lexer . get_number_float (), std:: move ( number_string )); 12520case token_type:: uninitialized : 12521case token_type:: literal_true : 12522case token_type:: literal_false : 12523case token_type:: literal_null : 12524case token_type:: value_string : 12525case token_type:: begin_array : 12526case token_type:: begin_object : 12527case token_type:: end_array : 12528case token_type:: end_object : 12529case token_type:: name_separator : 12530case token_type:: value_separator : 12531case token_type:: parse_error : 12532case token_type:: end_of_input : 12533case token_type:: literal_or_value : 12534default: 12535return sax -> parse_error ( chars_read , number_string , parse_error:: create ( 115 , chars_read , 12536exception_message ( input_format , concat ( "invalid number text: " , number_lexer . get_token_string ()), "high-precision number" ), nullptr )); 12537} 12538} 12539 12540/////////////////////// 12541// Utility functions // 12542/////////////////////// 12543 12544/*! 12545@brief get next character from the input 12546 12547This function provides the interface to the used input adapter. It does 12548not throw in case the input reached EOF, but returns a -'ve valued 12549`char_traits<char_type>::eof()` in that case. 12550 12551@return character read from the input 12552*/ 12553char_int_type get () 12554{ 12555++ chars_read ; 12556return current = ia . get_character (); 12557} 12558 12559/*! 12560@brief get_to read into a primitive type 12561 12562This function provides the interface to the used input adapter. It does 12563not throw in case the input reached EOF, but returns false instead 12564 12565@return bool, whether the read was successful 12566*/ 12567template < class T > 12568bool get_to ( T & dest , const input_format_t format , const char * context ) 12569{ 12570auto new_chars_read = ia . get_elements ( & dest ); 12571chars_read += new_chars_read ; 12572if ( JSON_HEDLEY_UNLIKELY ( new_chars_read < sizeof( T ))) 12573{ 12574// in case of failure, advance position by 1 to report failing location 12575++ chars_read ; 12576sax -> parse_error ( chars_read , "<end of file>" , parse_error:: create ( 110 , chars_read , exception_message ( format , "unexpected end of input" , context ), nullptr )); 12577return false; 12578} 12579return true; 12580} 12581 12582/*! 12583@return character read from the input after ignoring all 'N' entries 12584*/ 12585char_int_type get_ignore_noop () 12586{ 12587do 12588{ 12589get (); 12590} 12591while ( current == 'N' ); 12592 12593return current ; 12594} 12595 12596template < class NumberType > 12597static void byte_swap ( NumberType & number ) 12598{ 12599constexpr std:: size_t sz = sizeof( number ); 12600#ifdef __cpp_lib_byteswap 12601if constexpr ( sz == 1 ) 12602{ 12603return; 12604} 12605if constexpr(std:: is_integral_v < NumberType > ) 12606{ 12607number = std:: byteswap ( number ); 12608return; 12609} 12610#endif 12611auto * ptr = reinterpret_cast < std:: uint8_t *> ( & number ); 12612for (std:: size_t i = 0 ; i < sz / 2 ; ++ i ) 12613{ 12614std:: swap ( ptr [ i ], ptr [ sz - i - 1 ]); 12615} 12616} 12617 12618/* 12619@brief read a number from the input 12620 12621@tparam NumberType the type of the number 12622@param[in] format the current format (for diagnostics) 12623@param[out] result number of type @a NumberType 12624 12625@return whether conversion completed 12626 12627@note This function needs to respect the system's endianness, because 12628bytes in CBOR, MessagePack, and UBJSON are stored in network order 12629(big endian) and therefore need reordering on little endian systems. 12630On the other hand, BSON and BJData use little endian and should reorder 12631on big endian systems. 12632*/ 12633template < typename NumberType , bool InputIsLittleEndian = false > 12634bool get_number (const input_format_t format , NumberType & result ) 12635{ 12636// read in the original format 12637 12638if ( JSON_HEDLEY_UNLIKELY (! get_to ( result , format , "number" ))) 12639{ 12640return false; 12641} 12642if ( is_little_endian != ( InputIsLittleEndian || format == input_format_t:: bjdata )) 12643{ 12644byte_swap ( result ); 12645} 12646return true; 12647} 12648 12649/*! 12650@brief create a string by reading characters from the input 12651 12652@tparam NumberType the type of the number 12653@param[in] format the current format (for diagnostics) 12654@param[in] len number of characters to read 12655@param[out] result string created by reading @a len bytes 12656 12657@return whether string creation completed 12658 12659@note We can not reserve @a len bytes for the result, because @a len 12660may be too large. Usually, @ref unexpect_eof() detects the end of 12661the input before we run out of string memory. 12662*/ 12663template < typename NumberType > 12664bool get_string (const input_format_t format , 12665const NumberType len , 12666string_t & result ) 12667{ 12668bool success = true; 12669for ( NumberType i = 0 ; i < len ; i ++ ) 12670{ 12671get (); 12672if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( format , "string" ))) 12673{ 12674success = false; 12675break; 12676} 12677result . push_back ( static_cast < typename string_t:: value_type > ( current )); 12678} 12679return success ; 12680} 12681 12682/*! 12683@brief create a byte array by reading bytes from the input 12684 12685@tparam NumberType the type of the number 12686@param[in] format the current format (for diagnostics) 12687@param[in] len number of bytes to read 12688@param[out] result byte array created by reading @a len bytes 12689 12690@return whether byte array creation completed 12691 12692@note We can not reserve @a len bytes for the result, because @a len 12693may be too large. Usually, @ref unexpect_eof() detects the end of 12694the input before we run out of memory. 12695*/ 12696template < typename NumberType > 12697bool get_binary (const input_format_t format , 12698const NumberType len , 12699binary_t & result ) 12700{ 12701bool success = true; 12702for ( NumberType i = 0 ; i < len ; i ++ ) 12703{ 12704get (); 12705if ( JSON_HEDLEY_UNLIKELY (! unexpect_eof ( format , "binary" ))) 12706{ 12707success = false; 12708break; 12709} 12710result . push_back ( static_cast < std:: uint8_t > ( current )); 12711} 12712return success ; 12713} 12714 12715/*! 12716@param[in] format the current format (for diagnostics) 12717@param[in] context further context information (for diagnostics) 12718@return whether the last read character is not EOF 12719*/ 12720JSON_HEDLEY_NON_NULL ( 3 ) 12721bool unexpect_eof (const input_format_t format , const char * context ) const 12722{ 12723if ( JSON_HEDLEY_UNLIKELY ( current == char_traits < char_type > :: eof ())) 12724{ 12725return sax -> parse_error ( chars_read , "<end of file>" , 12726parse_error:: create ( 110 , chars_read , exception_message ( format , "unexpected end of input" , context ), nullptr )); 12727} 12728return true; 12729} 12730 12731/*! 12732@return a string representation of the last read byte 12733*/ 12734std:: string get_token_string () const 12735{ 12736std:: array < char , 3 > cr {{}}; 12737static_cast < void > ((std:: snprintf )( cr . data (), cr . size (), "%.2hhX" , static_cast < unsigned char > ( current ))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 12738return std:: string { cr . data ()}; 12739} 12740 12741/*! 12742@param[in] format the current format 12743@param[in] detail a detailed error message 12744@param[in] context further context information 12745@return a message string to use in the parse_error exceptions 12746*/ 12747std:: string exception_message (const input_format_t format , 12748const std:: string & detail , 12749const std:: string & context ) const 12750{ 12751std:: string error_msg = "syntax error while parsing " ; 12752 12753switch ( format ) 12754{ 12755case input_format_t:: cbor : 12756error_msg += "CBOR" ; 12757break; 12758 12759case input_format_t:: msgpack : 12760error_msg += "MessagePack" ; 12761break; 12762 12763case input_format_t:: ubjson : 12764error_msg += "UBJSON" ; 12765break; 12766 12767case input_format_t:: bson : 12768error_msg += "BSON" ; 12769break; 12770 12771case input_format_t:: bjdata : 12772error_msg += "BJData" ; 12773break; 12774 12775case input_format_t:: json : // LCOV_EXCL_LINE 12776default: // LCOV_EXCL_LINE 12777JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 12778} 12779 12780return concat ( error_msg , ' ' , context , ": " , detail ); 12781} 12782 12783private: 12784static JSON_INLINE_VARIABLE constexpr std :: size_t npos = detail:: unknown_size (); 12785 12786/// input adapter 12787InputAdapterType ia ; 12788 12789/// the current character 12790char_int_type current = char_traits < char_type > :: eof (); 12791 12792/// the number of characters read 12793std:: size_t chars_read = 0 ; 12794 12795/// whether we can assume little endianness 12796const bool is_little_endian = little_endianness (); 12797 12798/// input format 12799const input_format_t input_format = input_format_t:: json ; 12800 12801/// the SAX parser 12802json_sax_t * sax = nullptr ; 12803 12804// excluded markers in bjdata optimized type 12805#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ 12806make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') 12807 12808#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ 12809make_array<bjd_type>( \ 12810bjd_type{'B', "byte"}, \ 12811bjd_type{'C', "char"}, \ 12812bjd_type{'D', "double"}, \ 12813bjd_type{'I', "int16"}, \ 12814bjd_type{'L', "int64"}, \ 12815bjd_type{'M', "uint64"}, \ 12816bjd_type{'U', "uint8"}, \ 12817bjd_type{'d', "single"}, \ 12818bjd_type{'i', "int8"}, \ 12819bjd_type{'l', "int32"}, \ 12820bjd_type{'m', "uint32"}, \ 12821bjd_type{'u', "uint16"}) 12822 12823JSON_PRIVATE_UNLESS_TESTED : 12824// lookup tables 12825// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12826const decltype ( JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ ) bjd_optimized_type_markers = 12827JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ ; 12828 12829using bjd_type = std:: pair < char_int_type , string_t > ; 12830// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12831const decltype( JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ ) bjd_types_map = 12832JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ ; 12833 12834#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ 12835#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ 12836}; 12837 12838#ifndef JSON_HAS_CPP_17 12839template < typename BasicJsonType , typename InputAdapterType , typename SAX > 12840constexpr std:: size_t binary_reader < BasicJsonType , InputAdapterType , SAX > :: npos ; 12841#endif 12842 12843} // namespace detail 12844NLOHMANN_JSON_NAMESPACE_END 12845 12846// #include <nlohmann/detail/input/input_adapters.hpp> 12847 12848// #include <nlohmann/detail/input/lexer.hpp> 12849 12850// #include <nlohmann/detail/input/parser.hpp> 12851// __ _____ _____ _____ 12852// __| | __| | | | JSON for Modern C++ 12853// | | |__ | | | | | | version 3.12.0 12854// |_____|_____|_____|_|___| https://github.com/nlohmann/json 12855// 12856// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 12857// SPDX-License-Identifier: MIT 12858 12859 12860 12861#include <cmath> // isfinite 12862#include <cstdint> // uint8_t 12863#include <functional> // function 12864#include <string> // string 12865#include <utility> // move 12866#include <vector> // vector 12867 12868// #include <nlohmann/detail/exceptions.hpp> 12869 12870// #include <nlohmann/detail/input/input_adapters.hpp> 12871 12872// #include <nlohmann/detail/input/json_sax.hpp> 12873 12874// #include <nlohmann/detail/input/lexer.hpp> 12875 12876// #include <nlohmann/detail/macro_scope.hpp> 12877 12878// #include <nlohmann/detail/meta/is_sax.hpp> 12879 12880// #include <nlohmann/detail/string_concat.hpp> 12881 12882// #include <nlohmann/detail/value_t.hpp> 12883 12884 12885NLOHMANN_JSON_NAMESPACE_BEGIN 12886namespace detail 12887{ 12888//////////// 12889// parser // 12890//////////// 12891 12892enum class parse_event_t : std:: uint8_t 12893{ 12894/// the parser read `{` and started to process a JSON object 12895object_start , 12896/// the parser read `}` and finished processing a JSON object 12897object_end , 12898/// the parser read `[` and started to process a JSON array 12899array_start , 12900/// the parser read `]` and finished processing a JSON array 12901array_end , 12902/// the parser read a key of a value in an object 12903key , 12904/// the parser finished reading a JSON value 12905value 12906}; 12907 12908template < typename BasicJsonType > 12909using parser_callback_t = 12910std:: function < bool ( int /*depth*/ , parse_event_t /*event*/ , BasicJsonType & /*parsed*/ ) > ; 12911 12912/*! 12913@brief syntax analysis 12914 12915This class implements a recursive descent parser. 12916*/ 12917template < typename BasicJsonType , typename InputAdapterType > 12918class parser 12919{ 12920using number_integer_t = typename BasicJsonType :: number_integer_t ; 12921using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 12922using number_float_t = typename BasicJsonType :: number_float_t ; 12923using string_t = typename BasicJsonType :: string_t ; 12924using lexer_t = lexer < BasicJsonType , InputAdapterType > ; 12925using token_type = typename lexer_t:: token_type ; 12926 12927public: 12928/// a parser reading from an input adapter 12929explicit parser ( InputAdapterType && adapter , 12930parser_callback_t < BasicJsonType > cb = nullptr , 12931const bool allow_exceptions_ = true, 12932const bool skip_comments = false) 12933: callback (std:: move ( cb )) 12934, m_lexer (std:: move ( adapter ), skip_comments ) 12935, allow_exceptions ( allow_exceptions_ ) 12936{ 12937// read first token 12938get_token (); 12939} 12940 12941/*! 12942@brief public parser interface 12943 12944@param[in] strict whether to expect the last token to be EOF 12945@param[in,out] result parsed JSON value 12946 12947@throw parse_error.101 in case of an unexpected token 12948@throw parse_error.102 if to_unicode fails or surrogate error 12949@throw parse_error.103 if to_unicode fails 12950*/ 12951void parse (const bool strict , BasicJsonType & result ) 12952{ 12953if ( callback ) 12954{ 12955json_sax_dom_callback_parser < BasicJsonType , InputAdapterType > sdp ( result , callback , allow_exceptions , & m_lexer ); 12956sax_parse_internal ( & sdp ); 12957 12958// in strict mode, input must be completely read 12959if ( strict && ( get_token () != token_type:: end_of_input )) 12960{ 12961sdp . parse_error ( m_lexer . get_position (), 12962m_lexer . get_token_string (), 12963parse_error:: create ( 101 , m_lexer . get_position (), 12964exception_message (token_type:: end_of_input , "value" ), nullptr )); 12965} 12966 12967// in case of an error, return discarded value 12968if ( sdp . is_errored ()) 12969{ 12970result = value_t:: discarded ; 12971return; 12972} 12973 12974// set top-level value to null if it was discarded by the callback 12975// function 12976if ( result . is_discarded ()) 12977{ 12978result = nullptr ; 12979} 12980} 12981else 12982{ 12983json_sax_dom_parser < BasicJsonType , InputAdapterType > sdp ( result , allow_exceptions , & m_lexer ); 12984sax_parse_internal ( & sdp ); 12985 12986// in strict mode, input must be completely read 12987if ( strict && ( get_token () != token_type:: end_of_input )) 12988{ 12989sdp . parse_error ( m_lexer . get_position (), 12990m_lexer . get_token_string (), 12991parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: end_of_input , "value" ), nullptr )); 12992} 12993 12994// in case of an error, return discarded value 12995if ( sdp . is_errored ()) 12996{ 12997result = value_t:: discarded ; 12998return; 12999} 13000} 13001 13002result . assert_invariant (); 13003} 13004 13005/*! 13006@brief public accept interface 13007 13008@param[in] strict whether to expect the last token to be EOF 13009@return whether the input is a proper JSON text 13010*/ 13011bool accept (const bool strict = true) 13012{ 13013json_sax_acceptor < BasicJsonType > sax_acceptor ; 13014return sax_parse ( & sax_acceptor , strict ); 13015} 13016 13017template < typename SAX > 13018JSON_HEDLEY_NON_NULL ( 2 ) 13019bool sax_parse ( SAX * sax , const bool strict = true) 13020{ 13021( void )detail:: is_sax_static_asserts < SAX , BasicJsonType > {}; 13022const bool result = sax_parse_internal ( sax ); 13023 13024// strict mode: next byte must be EOF 13025if ( result && strict && ( get_token () != token_type:: end_of_input )) 13026{ 13027return sax -> parse_error ( m_lexer . get_position (), 13028m_lexer . get_token_string (), 13029parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: end_of_input , "value" ), nullptr )); 13030} 13031 13032return result ; 13033} 13034 13035private: 13036template < typename SAX > 13037JSON_HEDLEY_NON_NULL ( 2 ) 13038bool sax_parse_internal ( SAX * sax ) 13039{ 13040// stack to remember the hierarchy of structured values we are parsing 13041// true = array; false = object 13042std:: vector < bool > states ; 13043// value to avoid a goto (see comment where set to true) 13044bool skip_to_state_evaluation = false; 13045 13046while (true) 13047{ 13048if (! skip_to_state_evaluation ) 13049{ 13050// invariant: get_token() was called before each iteration 13051switch ( last_token ) 13052{ 13053case token_type:: begin_object : 13054{ 13055if ( JSON_HEDLEY_UNLIKELY (! sax -> start_object (detail:: unknown_size ()))) 13056{ 13057return false; 13058} 13059 13060// closing } -> we are done 13061if ( get_token () == token_type:: end_object ) 13062{ 13063if ( JSON_HEDLEY_UNLIKELY (! sax -> end_object ())) 13064{ 13065return false; 13066} 13067break; 13068} 13069 13070// parse key 13071if ( JSON_HEDLEY_UNLIKELY ( last_token != token_type:: value_string )) 13072{ 13073return sax -> parse_error ( m_lexer . get_position (), 13074m_lexer . get_token_string (), 13075parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: value_string , "object key" ), nullptr )); 13076} 13077if ( JSON_HEDLEY_UNLIKELY (! sax -> key ( m_lexer . get_string ()))) 13078{ 13079return false; 13080} 13081 13082// parse separator (:) 13083if ( JSON_HEDLEY_UNLIKELY ( get_token () != token_type:: name_separator )) 13084{ 13085return sax -> parse_error ( m_lexer . get_position (), 13086m_lexer . get_token_string (), 13087parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: name_separator , "object separator" ), nullptr )); 13088} 13089 13090// remember we are now inside an object 13091states . push_back (false); 13092 13093// parse values 13094get_token (); 13095continue; 13096} 13097 13098case token_type:: begin_array : 13099{ 13100if ( JSON_HEDLEY_UNLIKELY (! sax -> start_array (detail:: unknown_size ()))) 13101{ 13102return false; 13103} 13104 13105// closing ] -> we are done 13106if ( get_token () == token_type:: end_array ) 13107{ 13108if ( JSON_HEDLEY_UNLIKELY (! sax -> end_array ())) 13109{ 13110return false; 13111} 13112break; 13113} 13114 13115// remember we are now inside an array 13116states . push_back (true); 13117 13118// parse values (no need to call get_token) 13119continue; 13120} 13121 13122case token_type:: value_float : 13123{ 13124const auto res = m_lexer . get_number_float (); 13125 13126if ( JSON_HEDLEY_UNLIKELY (!std:: isfinite ( res ))) 13127{ 13128return sax -> parse_error ( m_lexer . get_position (), 13129m_lexer . get_token_string (), 13130out_of_range:: create ( 406 , concat ( "number overflow parsing '" , m_lexer . get_token_string (), '\'' ), nullptr )); 13131} 13132 13133if ( JSON_HEDLEY_UNLIKELY (! sax -> number_float ( res , m_lexer . get_string ()))) 13134{ 13135return false; 13136} 13137 13138break; 13139} 13140 13141case token_type:: literal_false : 13142{ 13143if ( JSON_HEDLEY_UNLIKELY (! sax -> boolean (false))) 13144{ 13145return false; 13146} 13147break; 13148} 13149 13150case token_type:: literal_null : 13151{ 13152if ( JSON_HEDLEY_UNLIKELY (! sax -> null ())) 13153{ 13154return false; 13155} 13156break; 13157} 13158 13159case token_type:: literal_true : 13160{ 13161if ( JSON_HEDLEY_UNLIKELY (! sax -> boolean (true))) 13162{ 13163return false; 13164} 13165break; 13166} 13167 13168case token_type:: value_integer : 13169{ 13170if ( JSON_HEDLEY_UNLIKELY (! sax -> number_integer ( m_lexer . get_number_integer ()))) 13171{ 13172return false; 13173} 13174break; 13175} 13176 13177case token_type:: value_string : 13178{ 13179if ( JSON_HEDLEY_UNLIKELY (! sax -> string ( m_lexer . get_string ()))) 13180{ 13181return false; 13182} 13183break; 13184} 13185 13186case token_type:: value_unsigned : 13187{ 13188if ( JSON_HEDLEY_UNLIKELY (! sax -> number_unsigned ( m_lexer . get_number_unsigned ()))) 13189{ 13190return false; 13191} 13192break; 13193} 13194 13195case token_type:: parse_error : 13196{ 13197// using "uninitialized" to avoid "expected" message 13198return sax -> parse_error ( m_lexer . get_position (), 13199m_lexer . get_token_string (), 13200parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: uninitialized , "value" ), nullptr )); 13201} 13202case token_type:: end_of_input : 13203{ 13204if ( JSON_HEDLEY_UNLIKELY ( m_lexer . get_position (). chars_read_total == 1 )) 13205{ 13206return sax -> parse_error ( m_lexer . get_position (), 13207m_lexer . get_token_string (), 13208parse_error:: create ( 101 , m_lexer . get_position (), 13209"attempting to parse an empty input; check that your input string or stream contains the expected JSON" , nullptr )); 13210} 13211 13212return sax -> parse_error ( m_lexer . get_position (), 13213m_lexer . get_token_string (), 13214parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: literal_or_value , "value" ), nullptr )); 13215} 13216case token_type:: uninitialized : 13217case token_type:: end_array : 13218case token_type:: end_object : 13219case token_type:: name_separator : 13220case token_type:: value_separator : 13221case token_type:: literal_or_value : 13222default: // the last token was unexpected 13223{ 13224return sax -> parse_error ( m_lexer . get_position (), 13225m_lexer . get_token_string (), 13226parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: literal_or_value , "value" ), nullptr )); 13227} 13228} 13229} 13230else 13231{ 13232skip_to_state_evaluation = false; 13233} 13234 13235// we reached this line after we successfully parsed a value 13236if ( states . empty ()) 13237{ 13238// empty stack: we reached the end of the hierarchy: done 13239return true; 13240} 13241 13242if ( states . back ()) // array 13243{ 13244// comma -> next value 13245if ( get_token () == token_type:: value_separator ) 13246{ 13247// parse a new value 13248get_token (); 13249continue; 13250} 13251 13252// closing ] 13253if ( JSON_HEDLEY_LIKELY ( last_token == token_type:: end_array )) 13254{ 13255if ( JSON_HEDLEY_UNLIKELY (! sax -> end_array ())) 13256{ 13257return false; 13258} 13259 13260// We are done with this array. Before we can parse a 13261// new value, we need to evaluate the new state first. 13262// By setting skip_to_state_evaluation to false, we 13263// are effectively jumping to the beginning of this if. 13264JSON_ASSERT (! states . empty ()); 13265states . pop_back (); 13266skip_to_state_evaluation = true; 13267continue; 13268} 13269 13270return sax -> parse_error ( m_lexer . get_position (), 13271m_lexer . get_token_string (), 13272parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: end_array , "array" ), nullptr )); 13273} 13274 13275// states.back() is false -> object 13276 13277// comma -> next value 13278if ( get_token () == token_type:: value_separator ) 13279{ 13280// parse key 13281if ( JSON_HEDLEY_UNLIKELY ( get_token () != token_type:: value_string )) 13282{ 13283return sax -> parse_error ( m_lexer . get_position (), 13284m_lexer . get_token_string (), 13285parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: value_string , "object key" ), nullptr )); 13286} 13287 13288if ( JSON_HEDLEY_UNLIKELY (! sax -> key ( m_lexer . get_string ()))) 13289{ 13290return false; 13291} 13292 13293// parse separator (:) 13294if ( JSON_HEDLEY_UNLIKELY ( get_token () != token_type:: name_separator )) 13295{ 13296return sax -> parse_error ( m_lexer . get_position (), 13297m_lexer . get_token_string (), 13298parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: name_separator , "object separator" ), nullptr )); 13299} 13300 13301// parse values 13302get_token (); 13303continue; 13304} 13305 13306// closing } 13307if ( JSON_HEDLEY_LIKELY ( last_token == token_type:: end_object )) 13308{ 13309if ( JSON_HEDLEY_UNLIKELY (! sax -> end_object ())) 13310{ 13311return false; 13312} 13313 13314// We are done with this object. Before we can parse a 13315// new value, we need to evaluate the new state first. 13316// By setting skip_to_state_evaluation to false, we 13317// are effectively jumping to the beginning of this if. 13318JSON_ASSERT (! states . empty ()); 13319states . pop_back (); 13320skip_to_state_evaluation = true; 13321continue; 13322} 13323 13324return sax -> parse_error ( m_lexer . get_position (), 13325m_lexer . get_token_string (), 13326parse_error:: create ( 101 , m_lexer . get_position (), exception_message (token_type:: end_object , "object" ), nullptr )); 13327} 13328} 13329 13330/// get next token from lexer 13331token_type get_token () 13332{ 13333return last_token = m_lexer . scan (); 13334} 13335 13336std:: string exception_message (const token_type expected , const std:: string & context ) 13337{ 13338std:: string error_msg = "syntax error " ; 13339 13340if (! context . empty ()) 13341{ 13342error_msg += concat ( "while parsing " , context , ' ' ); 13343} 13344 13345error_msg += "- " ; 13346 13347if ( last_token == token_type:: parse_error ) 13348{ 13349error_msg += concat ( m_lexer . get_error_message (), "; last read: '" , 13350m_lexer . get_token_string (), '\'' ); 13351} 13352else 13353{ 13354error_msg += concat ( "unexpected " , lexer_t:: token_type_name ( last_token )); 13355} 13356 13357if ( expected != token_type:: uninitialized ) 13358{ 13359error_msg += concat ( "; expected " , lexer_t:: token_type_name ( expected )); 13360} 13361 13362return error_msg ; 13363} 13364 13365private: 13366/// callback function 13367const parser_callback_t < BasicJsonType > callback = nullptr ; 13368/// the type of the last read token 13369token_type last_token = token_type:: uninitialized ; 13370/// the lexer 13371lexer_t m_lexer ; 13372/// whether to throw exceptions in case of errors 13373const bool allow_exceptions = true; 13374}; 13375 13376} // namespace detail 13377NLOHMANN_JSON_NAMESPACE_END 13378 13379// #include <nlohmann/detail/iterators/internal_iterator.hpp> 13380// __ _____ _____ _____ 13381// __| | __| | | | JSON for Modern C++ 13382// | | |__ | | | | | | version 3.12.0 13383// |_____|_____|_____|_|___| https://github.com/nlohmann/json 13384// 13385// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 13386// SPDX-License-Identifier: MIT 13387 13388 13389 13390// #include <nlohmann/detail/abi_macros.hpp> 13391 13392// #include <nlohmann/detail/iterators/primitive_iterator.hpp> 13393// __ _____ _____ _____ 13394// __| | __| | | | JSON for Modern C++ 13395// | | |__ | | | | | | version 3.12.0 13396// |_____|_____|_____|_|___| https://github.com/nlohmann/json 13397// 13398// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 13399// SPDX-License-Identifier: MIT 13400 13401 13402 13403#include <cstddef> // ptrdiff_t 13404#include <limits> // numeric_limits 13405 13406// #include <nlohmann/detail/macro_scope.hpp> 13407 13408 13409NLOHMANN_JSON_NAMESPACE_BEGIN 13410namespace detail 13411{ 13412 13413/* 13414@brief an iterator for primitive JSON types 13415 13416This class models an iterator for primitive JSON types (boolean, number, 13417string). It's only purpose is to allow the iterator/const_iterator classes 13418to "iterate" over primitive values. Internally, the iterator is modeled by 13419a `difference_type` variable. Value begin_value (`0`) models the begin, 13420end_value (`1`) models past the end. 13421*/ 13422class primitive_iterator_t 13423{ 13424private: 13425using difference_type = std:: ptrdiff_t ; 13426static constexpr difference_type begin_value = 0 ; 13427static constexpr difference_type end_value = begin_value + 1 ; 13428 13429JSON_PRIVATE_UNLESS_TESTED : 13430/// iterator as signed integer type 13431difference_type m_it = (std:: numeric_limits < std:: ptrdiff_t > :: min )(); 13432 13433public: 13434constexpr difference_type get_value () const noexcept 13435{ 13436return m_it ; 13437} 13438 13439/// set iterator to a defined beginning 13440void set_begin () noexcept 13441{ 13442m_it = begin_value ; 13443} 13444 13445/// set iterator to a defined past the end 13446void set_end () noexcept 13447{ 13448m_it = end_value ; 13449} 13450 13451/// return whether the iterator can be dereferenced 13452constexpr bool is_begin () const noexcept 13453{ 13454return m_it == begin_value ; 13455} 13456 13457/// return whether the iterator is at end 13458constexpr bool is_end () const noexcept 13459{ 13460return m_it == end_value ; 13461} 13462 13463friend constexpr bool operator == ( primitive_iterator_t lhs , primitive_iterator_t rhs ) noexcept 13464{ 13465return lhs . m_it == rhs . m_it ; 13466} 13467 13468friend constexpr bool operator < ( primitive_iterator_t lhs , primitive_iterator_t rhs ) noexcept 13469{ 13470return lhs . m_it < rhs . m_it ; 13471} 13472 13473primitive_iterator_t operator + ( difference_type n ) noexcept 13474{ 13475auto result = * this ; 13476result += n ; 13477return result ; 13478} 13479 13480friend constexpr difference_type operator - ( primitive_iterator_t lhs , primitive_iterator_t rhs ) noexcept 13481{ 13482return lhs . m_it - rhs . m_it ; 13483} 13484 13485primitive_iterator_t & operator ++ () noexcept 13486{ 13487++ m_it ; 13488return * this ; 13489} 13490 13491primitive_iterator_t operator ++ ( int ) & noexcept // NOLINT(cert-dcl21-cpp) 13492{ 13493auto result = * this ; 13494++ m_it ; 13495return result ; 13496} 13497 13498primitive_iterator_t & operator -- () noexcept 13499{ 13500-- m_it ; 13501return * this ; 13502} 13503 13504primitive_iterator_t operator -- ( int ) & noexcept // NOLINT(cert-dcl21-cpp) 13505{ 13506auto result = * this ; 13507-- m_it ; 13508return result ; 13509} 13510 13511primitive_iterator_t & operator += ( difference_type n ) noexcept 13512{ 13513m_it += n ; 13514return * this ; 13515} 13516 13517primitive_iterator_t & operator -= ( difference_type n ) noexcept 13518{ 13519m_it -= n ; 13520return * this ; 13521} 13522}; 13523 13524} // namespace detail 13525NLOHMANN_JSON_NAMESPACE_END 13526 13527 13528NLOHMANN_JSON_NAMESPACE_BEGIN 13529namespace detail 13530{ 13531 13532/*! 13533@brief an iterator value 13534 13535@note This structure could easily be a union, but MSVC currently does not allow 13536unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. 13537*/ 13538template < typename BasicJsonType > struct internal_iterator 13539{ 13540/// iterator for JSON objects 13541typename BasicJsonType ::object_t:: iterator object_iterator {}; 13542/// iterator for JSON arrays 13543typename BasicJsonType ::array_t:: iterator array_iterator {}; 13544/// generic iterator for all other types 13545primitive_iterator_t primitive_iterator {}; 13546}; 13547 13548} // namespace detail 13549NLOHMANN_JSON_NAMESPACE_END 13550 13551// #include <nlohmann/detail/iterators/iter_impl.hpp> 13552// __ _____ _____ _____ 13553// __| | __| | | | JSON for Modern C++ 13554// | | |__ | | | | | | version 3.12.0 13555// |_____|_____|_____|_|___| https://github.com/nlohmann/json 13556// 13557// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 13558// SPDX-License-Identifier: MIT 13559 13560 13561 13562#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next 13563#include <type_traits> // conditional, is_const, remove_const 13564 13565// #include <nlohmann/detail/exceptions.hpp> 13566 13567// #include <nlohmann/detail/iterators/internal_iterator.hpp> 13568 13569// #include <nlohmann/detail/iterators/primitive_iterator.hpp> 13570 13571// #include <nlohmann/detail/macro_scope.hpp> 13572 13573// #include <nlohmann/detail/meta/cpp_future.hpp> 13574 13575// #include <nlohmann/detail/meta/type_traits.hpp> 13576 13577// #include <nlohmann/detail/value_t.hpp> 13578 13579 13580NLOHMANN_JSON_NAMESPACE_BEGIN 13581namespace detail 13582{ 13583 13584// forward declare, to be able to friend it later on 13585template < typename IteratorType > class iteration_proxy ; 13586template < typename IteratorType > class iteration_proxy_value ; 13587 13588/*! 13589@brief a template for a bidirectional iterator for the @ref basic_json class 13590This class implements a both iterators (iterator and const_iterator) for the 13591@ref basic_json class. 13592@note An iterator is called *initialized* when a pointer to a JSON value has 13593been set (e.g., by a constructor or a copy assignment). If the iterator is 13594default-constructed, it is *uninitialized* and most methods are undefined. 13595**The library uses assertions to detect calls on uninitialized iterators.** 13596@requirement The class satisfies the following concept requirements: 13597- 13598[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 13599The iterator that can be moved can be moved in both directions (i.e. 13600incremented and decremented). 13601@since version 1.0.0, simplified in version 2.0.9, change to bidirectional 13602iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) 13603*/ 13604template < typename BasicJsonType > 13605class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 13606{ 13607/// the iterator with BasicJsonType of different const-ness 13608using other_iter_impl = iter_impl < typename std:: conditional < std:: is_const < BasicJsonType > :: value , typename std:: remove_const < BasicJsonType > :: type , const BasicJsonType > :: type > ; 13609/// allow basic_json to access private members 13610friend other_iter_impl ; 13611friend BasicJsonType ; 13612friend iteration_proxy < iter_impl > ; 13613friend iteration_proxy_value < iter_impl > ; 13614 13615using object_t = typename BasicJsonType :: object_t ; 13616using array_t = typename BasicJsonType :: array_t ; 13617// make sure BasicJsonType is basic_json or const basic_json 13618static_assert( is_basic_json < typename std:: remove_const < BasicJsonType > :: type > :: value , 13619"iter_impl only accepts (const) basic_json" ); 13620// superficial check for the LegacyBidirectionalIterator named requirement 13621static_assert(std:: is_base_of < std:: bidirectional_iterator_tag , std:: bidirectional_iterator_tag > :: value 13622&& std:: is_base_of < std:: bidirectional_iterator_tag , typename std:: iterator_traits < typename array_t:: iterator > :: iterator_category > :: value , 13623"basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement." ); 13624 13625public: 13626/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. 13627/// The C++ Standard has never required user-defined iterators to derive from std::iterator. 13628/// A user-defined iterator should provide publicly accessible typedefs named 13629/// iterator_category, value_type, difference_type, pointer, and reference. 13630/// Note that value_type is required to be non-const, even for constant iterators. 13631using iterator_category = std:: bidirectional_iterator_tag ; 13632 13633/// the type of the values when the iterator is dereferenced 13634using value_type = typename BasicJsonType :: value_type ; 13635/// a type to represent differences between iterators 13636using difference_type = typename BasicJsonType :: difference_type ; 13637/// defines a pointer to the type iterated over (value_type) 13638using pointer = typename std:: conditional < std:: is_const < BasicJsonType > :: value , 13639typename BasicJsonType :: const_pointer , 13640typename BasicJsonType :: pointer > :: type ; 13641/// defines a reference to the type iterated over (value_type) 13642using reference = 13643typename std:: conditional < std:: is_const < BasicJsonType > :: value , 13644typename BasicJsonType :: const_reference , 13645typename BasicJsonType :: reference > :: type ; 13646 13647iter_impl () = default; 13648~ iter_impl () = default; 13649iter_impl ( iter_impl && ) noexcept = default; 13650iter_impl & operator = ( iter_impl && ) noexcept = default; 13651 13652/*! 13653@brief constructor for a given JSON instance 13654@param[in] object pointer to a JSON object for this iterator 13655@pre object != nullptr 13656@post The iterator is initialized; i.e. `m_object != nullptr`. 13657*/ 13658explicit iter_impl ( pointer object ) noexcept : m_object ( object ) 13659{ 13660JSON_ASSERT ( m_object != nullptr ); 13661 13662switch ( m_object -> m_data . m_type ) 13663{ 13664case value_t:: object : 13665{ 13666m_it . object_iterator = typename object_t:: iterator (); 13667break; 13668} 13669 13670case value_t:: array : 13671{ 13672m_it . array_iterator = typename array_t:: iterator (); 13673break; 13674} 13675 13676case value_t:: null : 13677case value_t:: string : 13678case value_t:: boolean : 13679case value_t:: number_integer : 13680case value_t:: number_unsigned : 13681case value_t:: number_float : 13682case value_t:: binary : 13683case value_t:: discarded : 13684default: 13685{ 13686m_it . primitive_iterator = primitive_iterator_t (); 13687break; 13688} 13689} 13690} 13691 13692/*! 13693@note The conventional copy constructor and copy assignment are implicitly 13694defined. Combined with the following converting constructor and 13695assignment, they support: (1) copy from iterator to iterator, (2) 13696copy from const iterator to const iterator, and (3) conversion from 13697iterator to const iterator. However conversion from const iterator 13698to iterator is not defined. 13699*/ 13700 13701/*! 13702@brief const copy constructor 13703@param[in] other const iterator to copy from 13704@note This copy constructor had to be defined explicitly to circumvent a bug 13705occurring on msvc v19.0 compiler (VS 2015) debug build. For more 13706information refer to: https://github.com/nlohmann/json/issues/1608 13707*/ 13708iter_impl (const iter_impl < const BasicJsonType >& other ) noexcept 13709: m_object ( other . m_object ), m_it ( other . m_it ) 13710{} 13711 13712/*! 13713@brief converting assignment 13714@param[in] other const iterator to copy from 13715@return const/non-const iterator 13716@note It is not checked whether @a other is initialized. 13717*/ 13718iter_impl & operator = (const iter_impl < const BasicJsonType >& other ) noexcept 13719{ 13720if ( & other != this ) 13721{ 13722m_object = other . m_object ; 13723m_it = other . m_it ; 13724} 13725return * this ; 13726} 13727 13728/*! 13729@brief converting constructor 13730@param[in] other non-const iterator to copy from 13731@note It is not checked whether @a other is initialized. 13732*/ 13733iter_impl (const iter_impl < typename std:: remove_const < BasicJsonType > :: type >& other ) noexcept 13734: m_object ( other . m_object ), m_it ( other . m_it ) 13735{} 13736 13737/*! 13738@brief converting assignment 13739@param[in] other non-const iterator to copy from 13740@return const/non-const iterator 13741@note It is not checked whether @a other is initialized. 13742*/ 13743iter_impl & operator = (const iter_impl < typename std:: remove_const < BasicJsonType > :: type >& other ) noexcept // NOLINT(cert-oop54-cpp) 13744{ 13745m_object = other . m_object ; 13746m_it = other . m_it ; 13747return * this ; 13748} 13749 13750JSON_PRIVATE_UNLESS_TESTED : 13751/*! 13752@brief set the iterator to the first value 13753@pre The iterator is initialized; i.e. `m_object != nullptr`. 13754*/ 13755void set_begin () noexcept 13756{ 13757JSON_ASSERT ( m_object != nullptr ); 13758 13759switch (m_object -> m_data . m_type ) 13760{ 13761case value_t:: object : 13762{ 13763m_it .object_iterator = m_object -> m_data.m_value.object -> begin (); 13764break ; 13765} 13766 13767case value_t:: array : 13768{ 13769m_it .array_iterator = m_object -> m_data.m_value.array -> begin (); 13770break ; 13771} 13772 13773case value_t:: null : 13774{ 13775// set to end so begin()==end() is true: null is empty 13776m_it .primitive_iterator. set_end (); 13777break ; 13778} 13779 13780case value_t:: string : 13781case value_t:: boolean : 13782case value_t:: number_integer : 13783case value_t:: number_unsigned : 13784case value_t:: number_float : 13785case value_t:: binary : 13786case value_t:: discarded : 13787default : 13788{ 13789m_it .primitive_iterator. set_begin (); 13790break ; 13791} 13792} 13793} 13794 13795/*! 13796@brief set the iterator past the last value 13797@pre The iterator is initialized; i.e. `m_object != nullptr`. 13798*/ 13799void set_end () noexcept 13800{ 13801JSON_ASSERT ( m_object != nullptr ); 13802 13803switch ( m_object -> m_data.m_type) 13804{ 13805case value_t:: object : 13806{ 13807m_it .object_iterator = m_object -> m_data.m_value.object -> end (); 13808break ; 13809} 13810 13811case value_t:: array : 13812{ 13813m_it .array_iterator = m_object -> m_data.m_value.array -> end (); 13814break ; 13815} 13816 13817case value_t:: null : 13818case value_t:: string : 13819case value_t:: boolean : 13820case value_t:: number_integer : 13821case value_t:: number_unsigned : 13822case value_t:: number_float : 13823case value_t:: binary : 13824case value_t:: discarded : 13825default : 13826{ 13827m_it .primitive_iterator. set_end (); 13828break ; 13829} 13830} 13831} 13832 13833public : 13834/*! 13835@brief return a reference to the value pointed to by the iterator 13836@pre The iterator is initialized; i.e. `m_object != nullptr`. 13837*/ 13838reference operator * () const 13839{ 13840JSON_ASSERT ( m_object != nullptr ); 13841 13842switch ( m_object -> m_data.m_type) 13843{ 13844case value_t:: object : 13845{ 13846JSON_ASSERT ( m_it .object_iterator != m_object -> m_data.m_value.object -> end ()); 13847return m_it .object_iterator -> second; 13848} 13849 13850case value_t:: array : 13851{ 13852JSON_ASSERT ( m_it .array_iterator != m_object -> m_data.m_value.array -> end ()); 13853return * m_it .array_iterator; 13854} 13855 13856case value_t:: null : 13857JSON_THROW (invalid_iterator:: create ( 214 , "cannot get value" , m_object )); 13858 13859case value_t:: string : 13860case value_t:: boolean : 13861case value_t:: number_integer : 13862case value_t:: number_unsigned : 13863case value_t:: number_float : 13864case value_t:: binary : 13865case value_t:: discarded : 13866default : 13867{ 13868if ( JSON_HEDLEY_LIKELY ( m_it .primitive_iterator. is_begin ())) 13869{ 13870return * m_object ; 13871} 13872 13873JSON_THROW (invalid_iterator:: create ( 214 , "cannot get value" , m_object )); 13874} 13875} 13876} 13877 13878/*! 13879@brief dereference the iterator 13880@pre The iterator is initialized; i.e. `m_object != nullptr`. 13881*/ 13882pointer operator -> () const 13883{ 13884JSON_ASSERT ( m_object != nullptr ); 13885 13886switch ( m_object -> m_data.m_type) 13887{ 13888case value_t:: object : 13889{ 13890JSON_ASSERT ( m_it .object_iterator != m_object -> m_data.m_value.object -> end ()); 13891return & ( m_it .object_iterator -> second); 13892} 13893 13894case value_t:: array : 13895{ 13896JSON_ASSERT ( m_it .array_iterator != m_object -> m_data.m_value.array -> end ()); 13897return &* m_it .array_iterator; 13898} 13899 13900case value_t:: null : 13901case value_t:: string : 13902case value_t:: boolean : 13903case value_t:: number_integer : 13904case value_t:: number_unsigned : 13905case value_t:: number_float : 13906case value_t:: binary : 13907case value_t:: discarded : 13908default : 13909{ 13910if ( JSON_HEDLEY_LIKELY ( m_it .primitive_iterator. is_begin ())) 13911{ 13912return m_object ; 13913} 13914 13915JSON_THROW (invalid_iterator:: create ( 214 , "cannot get value" , m_object )); 13916} 13917} 13918} 13919 13920/*! 13921@brief post-increment (it++) 13922@pre The iterator is initialized; i.e. `m_object != nullptr`. 13923*/ 13924iter_impl operator ++ ( int ) & // NOLINT(cert-dcl21-cpp) 13925{ 13926auto result = * this ; 13927++ ( * this ); 13928return result ; 13929} 13930 13931/*! 13932@brief pre-increment (++it) 13933@pre The iterator is initialized; i.e. `m_object != nullptr`. 13934*/ 13935iter_impl & operator ++ () 13936{ 13937JSON_ASSERT ( m_object != nullptr ); 13938 13939switch ( m_object -> m_data.m_type) 13940{ 13941case value_t:: object : 13942{ 13943std:: advance ( m_it .object_iterator, 1 ); 13944break ; 13945} 13946 13947case value_t:: array : 13948{ 13949std:: advance ( m_it .array_iterator, 1 ); 13950break ; 13951} 13952 13953case value_t:: null : 13954case value_t:: string : 13955case value_t:: boolean : 13956case value_t:: number_integer : 13957case value_t:: number_unsigned : 13958case value_t:: number_float : 13959case value_t:: binary : 13960case value_t:: discarded : 13961default : 13962{ 13963++ m_it .primitive_iterator; 13964break ; 13965} 13966} 13967 13968return * this ; 13969} 13970 13971/*! 13972@brief post-decrement (it--) 13973@pre The iterator is initialized; i.e. `m_object != nullptr`. 13974*/ 13975iter_impl operator -- ( int ) & // NOLINT(cert-dcl21-cpp) 13976{ 13977auto result = * this ; 13978-- ( * this ); 13979return result ; 13980} 13981 13982/*! 13983@brief pre-decrement (--it) 13984@pre The iterator is initialized; i.e. `m_object != nullptr`. 13985*/ 13986iter_impl & operator -- () 13987{ 13988JSON_ASSERT ( m_object != nullptr ); 13989 13990switch ( m_object -> m_data.m_type) 13991{ 13992case value_t:: object : 13993{ 13994std:: advance ( m_it .object_iterator, -1 ); 13995break ; 13996} 13997 13998case value_t:: array : 13999{ 14000std:: advance ( m_it .array_iterator, -1 ); 14001break ; 14002} 14003 14004case value_t:: null : 14005case value_t:: string : 14006case value_t:: boolean : 14007case value_t:: number_integer : 14008case value_t:: number_unsigned : 14009case value_t:: number_float : 14010case value_t:: binary : 14011case value_t:: discarded : 14012default : 14013{ 14014-- m_it .primitive_iterator; 14015break ; 14016} 14017} 14018 14019return * this ; 14020} 14021 14022/*! 14023@brief comparison: equal 14024@pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 14025*/ 14026template < typename IterImpl , detail:: enable_if_t < (std:: is_same < IterImpl , iter_impl > :: value || std:: is_same < IterImpl , other_iter_impl > :: value ), std:: nullptr_t > = nullptr > 14027bool operator == ( const IterImpl & other ) const 14028{ 14029// if objects are not the same, the comparison is undefined 14030if ( JSON_HEDLEY_UNLIKELY ( m_object != other .m_object)) 14031{ 14032JSON_THROW (invalid_iterator:: create ( 212 , "cannot compare iterators of different containers" , m_object )); 14033} 14034 14035// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 14036if ( m_object == nullptr ) 14037{ 14038return true; 14039} 14040 14041switch ( m_object -> m_data.m_type) 14042{ 14043case value_t:: object : 14044return ( m_it .object_iterator == other .m_it.object_iterator); 14045 14046case value_t:: array : 14047return ( m_it .array_iterator == other .m_it.array_iterator); 14048 14049case value_t:: null : 14050case value_t:: string : 14051case value_t:: boolean : 14052case value_t:: number_integer : 14053case value_t:: number_unsigned : 14054case value_t:: number_float : 14055case value_t:: binary : 14056case value_t:: discarded : 14057default : 14058return ( m_it .primitive_iterator == other .m_it.primitive_iterator); 14059} 14060} 14061 14062/*! 14063@brief comparison: not equal 14064@pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 14065*/ 14066template < typename IterImpl , detail:: enable_if_t < (std:: is_same < IterImpl , iter_impl > :: value || std:: is_same < IterImpl , other_iter_impl > :: value ), std:: nullptr_t > = nullptr > 14067bool operator != ( const IterImpl & other ) const 14068{ 14069return ! operator == ( other ); 14070} 14071 14072/*! 14073@brief comparison: smaller 14074@pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 14075*/ 14076bool operator < ( const iter_impl & other ) const 14077{ 14078// if objects are not the same, the comparison is undefined 14079if ( JSON_HEDLEY_UNLIKELY ( m_object != other .m_object)) 14080{ 14081JSON_THROW (invalid_iterator:: create ( 212 , "cannot compare iterators of different containers" , m_object )); 14082} 14083 14084// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 14085if ( m_object == nullptr ) 14086{ 14087// the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false 14088return false; 14089} 14090 14091switch ( m_object -> m_data.m_type) 14092{ 14093case value_t:: object : 14094JSON_THROW (invalid_iterator:: create ( 213 , "cannot compare order of object iterators" , m_object )); 14095 14096case value_t:: array : 14097return ( m_it .array_iterator < other .m_it.array_iterator); 14098 14099case value_t:: null : 14100case value_t:: string : 14101case value_t:: boolean : 14102case value_t:: number_integer : 14103case value_t:: number_unsigned : 14104case value_t:: number_float : 14105case value_t:: binary : 14106case value_t:: discarded : 14107default : 14108return ( m_it .primitive_iterator < other .m_it.primitive_iterator); 14109} 14110} 14111 14112/*! 14113@brief comparison: less than or equal 14114@pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 14115*/ 14116bool operator<=( const iter_impl & other ) const 14117{ 14118return ! other .operator < ( * this ); 14119} 14120 14121/*! 14122@brief comparison: greater than 14123@pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 14124*/ 14125bool operator > ( const iter_impl & other ) const 14126{ 14127return ! operator <=( other ); 14128} 14129 14130/*! 14131@brief comparison: greater than or equal 14132@pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized. 14133*/ 14134bool operator>=( const iter_impl & other ) const 14135{ 14136return ! operator < ( other ); 14137} 14138 14139/*! 14140@brief add to iterator 14141@pre The iterator is initialized; i.e. `m_object != nullptr`. 14142*/ 14143iter_impl & operator += ( difference_type i ) 14144{ 14145JSON_ASSERT ( m_object != nullptr ); 14146 14147switch ( m_object -> m_data.m_type) 14148{ 14149case value_t:: object : 14150JSON_THROW (invalid_iterator:: create ( 209 , "cannot use offsets with object iterators" , m_object )); 14151 14152case value_t:: array : 14153{ 14154std:: advance ( m_it .array_iterator, i ); 14155break ; 14156} 14157 14158case value_t:: null : 14159case value_t:: string : 14160case value_t:: boolean : 14161case value_t:: number_integer : 14162case value_t:: number_unsigned : 14163case value_t:: number_float : 14164case value_t:: binary : 14165case value_t:: discarded : 14166default : 14167{ 14168m_it .primitive_iterator += i ; 14169break ; 14170} 14171} 14172 14173return * this ; 14174} 14175 14176/*! 14177@brief subtract from iterator 14178@pre The iterator is initialized; i.e. `m_object != nullptr`. 14179*/ 14180iter_impl & operator -= ( difference_type i ) 14181{ 14182return operator += ( - i ); 14183} 14184 14185/*! 14186@brief add to iterator 14187@pre The iterator is initialized; i.e. `m_object != nullptr`. 14188*/ 14189iter_impl operator + ( difference_type i ) const 14190{ 14191auto result = * this ; 14192result += i ; 14193return result ; 14194} 14195 14196/*! 14197@brief addition of distance and iterator 14198@pre The iterator is initialized; i.e. `m_object != nullptr`. 14199*/ 14200friend iter_impl operator + ( difference_type i , const iter_impl & it ) 14201{ 14202auto result = it ; 14203result += i ; 14204return result ; 14205} 14206 14207/*! 14208@brief subtract from iterator 14209@pre The iterator is initialized; i.e. `m_object != nullptr`. 14210*/ 14211iter_impl operator - ( difference_type i ) const 14212{ 14213auto result = * this ; 14214result -= i ; 14215return result ; 14216} 14217 14218/*! 14219@brief return difference 14220@pre The iterator is initialized; i.e. `m_object != nullptr`. 14221*/ 14222difference_type operator - ( const iter_impl & other ) const 14223{ 14224JSON_ASSERT ( m_object != nullptr ); 14225 14226switch ( m_object -> m_data.m_type) 14227{ 14228case value_t:: object : 14229JSON_THROW (invalid_iterator:: create ( 209 , "cannot use offsets with object iterators" , m_object )); 14230 14231case value_t:: array : 14232return m_it .array_iterator - other .m_it.array_iterator; 14233 14234case value_t:: null : 14235case value_t:: string : 14236case value_t:: boolean : 14237case value_t:: number_integer : 14238case value_t:: number_unsigned : 14239case value_t:: number_float : 14240case value_t:: binary : 14241case value_t:: discarded : 14242default : 14243return m_it .primitive_iterator - other .m_it.primitive_iterator; 14244} 14245} 14246 14247/*! 14248@brief access to successor 14249@pre The iterator is initialized; i.e. `m_object != nullptr`. 14250*/ 14251reference operator[]( difference_type n ) const 14252{ 14253JSON_ASSERT ( m_object != nullptr ); 14254 14255switch ( m_object -> m_data.m_type) 14256{ 14257case value_t:: object : 14258JSON_THROW (invalid_iterator:: create ( 208 , "cannot use operator[] for object iterators" , m_object )); 14259 14260case value_t:: array : 14261return * std:: next ( m_it .array_iterator, n ); 14262 14263case value_t:: null : 14264JSON_THROW (invalid_iterator:: create ( 214 , "cannot get value" , m_object )); 14265 14266case value_t:: string : 14267case value_t:: boolean : 14268case value_t:: number_integer : 14269case value_t:: number_unsigned : 14270case value_t:: number_float : 14271case value_t:: binary : 14272case value_t:: discarded : 14273default : 14274{ 14275if ( JSON_HEDLEY_LIKELY ( m_it .primitive_iterator. get_value () == - n )) 14276{ 14277return * m_object ; 14278} 14279 14280JSON_THROW (invalid_iterator:: create ( 214 , "cannot get value" , m_object )); 14281} 14282} 14283} 14284 14285/*! 14286@brief return the key of an object iterator 14287@pre The iterator is initialized; i.e. `m_object != nullptr`. 14288*/ 14289const typename object_t:: key_type & key () const 14290{ 14291JSON_ASSERT ( m_object != nullptr ); 14292 14293if ( JSON_HEDLEY_LIKELY ( m_object -> is_object ())) 14294{ 14295return m_it .object_iterator -> first; 14296} 14297 14298JSON_THROW (invalid_iterator:: create ( 207 , "cannot use key() for non-object iterators" , m_object )); 14299} 14300 14301/*! 14302@brief return the value of an iterator 14303@pre The iterator is initialized; i.e. `m_object != nullptr`. 14304*/ 14305reference value () const 14306{ 14307return operator * ( ); 14308} 14309 14310JSON_PRIVATE_UNLESS_TESTED : 14311/// associated JSON instance 14312pointer m_object = nullptr ; 14313/// the actual iterator of the associated instance 14314internal_iterator < typename std:: remove_const < BasicJsonType > :: type > m_it {}; 14315}; 14316 14317} // namespace detail 14318NLOHMANN_JSON_NAMESPACE_END 14319 14320// #include <nlohmann/detail/iterators/iteration_proxy.hpp> 14321 14322// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> 14323// __ _____ _____ _____ 14324// __| | __| | | | JSON for Modern C++ 14325// | | |__ | | | | | | version 3.12.0 14326// |_____|_____|_____|_|___| https://github.com/nlohmann/json 14327// 14328// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 14329// SPDX-License-Identifier: MIT 14330 14331 14332 14333#include <cstddef> // ptrdiff_t 14334#include <iterator> // reverse_iterator 14335#include <utility> // declval 14336 14337// #include <nlohmann/detail/abi_macros.hpp> 14338 14339 14340NLOHMANN_JSON_NAMESPACE_BEGIN 14341namespace detail 14342{ 14343 14344////////////////////// 14345// reverse_iterator // 14346////////////////////// 14347 14348/*! 14349@brief a template for a reverse iterator class 14350 14351@tparam Base the base iterator type to reverse. Valid types are @ref 14352iterator (to create @ref reverse_iterator) and @ref const_iterator (to 14353create @ref const_reverse_iterator). 14354 14355@requirement The class satisfies the following concept requirements: 14356- 14357[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 14358The iterator that can be moved can be moved in both directions (i.e. 14359incremented and decremented). 14360- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): 14361It is possible to write to the pointed-to element (only if @a Base is 14362@ref iterator). 14363 14364@since version 1.0.0 14365*/ 14366template < typename Base > 14367class json_reverse_iterator : public std:: reverse_iterator < Base > 14368{ 14369public : 14370using difference_type = std:: ptrdiff_t ; 14371/// shortcut to the reverse iterator adapter 14372using base_iterator = std:: reverse_iterator < Base > ; 14373/// the reference type for the pointed-to element 14374using reference = typename Base :: reference ; 14375 14376/// create reverse iterator from iterator 14377explicit json_reverse_iterator ( const typename base_iterator:: iterator_type & it) noexcept 14378: base_iterator (it) {} 14379 14380/// create reverse iterator from base class 14381explicit json_reverse_iterator ( const base_iterator & it) noexcept : base_iterator (it) {} 14382 14383/// post-increment (it++) 14384json_reverse_iterator operator ++ ( int ) & // NOLINT(cert-dcl21-cpp) 14385{ 14386return static_cast < json_reverse_iterator > (base_iterator::operator ++ ( 1 )); 14387} 14388 14389/// pre-increment (++it) 14390json_reverse_iterator & operator ++ () 14391{ 14392return static_cast < json_reverse_iterator &> (base_iterator::operator ++ ()); 14393} 14394 14395/// post-decrement (it--) 14396json_reverse_iterator operator -- ( int ) & // NOLINT(cert-dcl21-cpp) 14397{ 14398return static_cast < json_reverse_iterator > (base_iterator::operator -- ( 1 )); 14399} 14400 14401/// pre-decrement (--it) 14402json_reverse_iterator & operator -- () 14403{ 14404return static_cast < json_reverse_iterator &> (base_iterator::operator -- ()); 14405} 14406 14407/// add to iterator 14408json_reverse_iterator & operator += ( difference_type i) 14409{ 14410return static_cast < json_reverse_iterator &> (base_iterator::operator += (i)); 14411} 14412 14413/// add to iterator 14414json_reverse_iterator operator + ( difference_type i) const 14415{ 14416return static_cast < json_reverse_iterator > (base_iterator::operator + (i)); 14417} 14418 14419/// subtract from iterator 14420json_reverse_iterator operator - ( difference_type i) const 14421{ 14422return static_cast < json_reverse_iterator > (base_iterator::operator - (i)); 14423} 14424 14425/// return difference 14426difference_type operator - ( const json_reverse_iterator & other) const 14427{ 14428return base_iterator ( * this) - base_iterator (other); 14429} 14430 14431/// access to successor 14432reference operator[]( difference_type n) const 14433{ 14434return * (this -> operator + (n)); 14435} 14436 14437/// return the key of an object iterator 14438auto key () const -> decltype(std:: declval < Base > (). key ()) 14439{ 14440auto it = -- this -> base (); 14441return it. key (); 14442} 14443 14444/// return the value of an iterator 14445reference value () const 14446{ 14447auto it = -- this -> base (); 14448return it.operator * (); 14449} 14450}; 14451 14452} // namespace detail 14453NLOHMANN_JSON_NAMESPACE_END 14454 14455// #include <nlohmann/detail/iterators/primitive_iterator.hpp> 14456 14457// #include <nlohmann/detail/json_custom_base_class.hpp> 14458// __ _____ _____ _____ 14459// __| | __| | | | JSON for Modern C++ 14460// | | |__ | | | | | | version 3.12.0 14461// |_____|_____|_____|_|___| https://github.com/nlohmann/json 14462// 14463// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 14464// SPDX-License-Identifier: MIT 14465 14466 14467 14468#include <type_traits> // conditional, is_same 14469 14470// #include <nlohmann/detail/abi_macros.hpp> 14471 14472 14473NLOHMANN_JSON_NAMESPACE_BEGIN 14474namespace detail 14475{ 14476 14477/*! 14478@brief Default base class of the @ref basic_json class. 14479 14480So that the correct implementations of the copy / move ctors / assign operators 14481of @ref basic_json do not require complex case distinctions 14482(no base class / custom base class used as customization point), 14483@ref basic_json always has a base class. 14484By default, this class is used because it is empty and thus has no effect 14485on the behavior of @ref basic_json. 14486*/ 14487struct json_default_base {}; 14488 14489template < class T > 14490using json_base_class = typename std:: conditional < 14491std:: is_same < T , void > :: value , 14492json_default_base , 14493T 14494> :: type ; 14495 14496} // namespace detail 14497NLOHMANN_JSON_NAMESPACE_END 14498 14499// #include <nlohmann/detail/json_pointer.hpp> 14500// __ _____ _____ _____ 14501// __| | __| | | | JSON for Modern C++ 14502// | | |__ | | | | | | version 3.12.0 14503// |_____|_____|_____|_|___| https://github.com/nlohmann/json 14504// 14505// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 14506// SPDX-License-Identifier: MIT 14507 14508 14509 14510#include <algorithm> // all_of 14511#include <cctype> // isdigit 14512#include <cerrno> // errno, ERANGE 14513#include <cstdlib> // strtoull 14514#ifndef JSON_NO_IO 14515#include <iosfwd> // ostream 14516#endif // JSON_NO_IO 14517#include <limits> // max 14518#include <numeric> // accumulate 14519#include <string> // string 14520#include <utility> // move 14521#include <vector> // vector 14522 14523// #include <nlohmann/detail/exceptions.hpp> 14524 14525// #include <nlohmann/detail/macro_scope.hpp> 14526 14527// #include <nlohmann/detail/string_concat.hpp> 14528 14529// #include <nlohmann/detail/string_escape.hpp> 14530 14531// #include <nlohmann/detail/value_t.hpp> 14532 14533 14534NLOHMANN_JSON_NAMESPACE_BEGIN 14535 14536/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 14537/// @sa https://json.nlohmann.me/api/json_pointer/ 14538template < typename RefStringType > 14539class json_pointer 14540{ 14541// allow basic_json to access private members 14542NLOHMANN_BASIC_JSON_TPL_DECLARATION 14543friend class basic_json; 14544 14545template < typename > 14546friend class json_pointer; 14547 14548template < typename T > 14549struct string_t_helper 14550{ 14551using type = T ; 14552}; 14553 14554NLOHMANN_BASIC_JSON_TPL_DECLARATION 14555struct string_t_helper < NLOHMANN_BASIC_JSON_TPL > 14556{ 14557using type = StringType ; 14558}; 14559 14560public : 14561// for backwards compatibility accept BasicJsonType 14562using string_t = typename string_t_helper < RefStringType > ::type; 14563 14564/// @brief create JSON pointer 14565/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ 14566explicit json_pointer ( const string_t & s = "" ) 14567: reference_tokens ( split (s)) 14568{} 14569 14570/// @brief return a string representation of the JSON pointer 14571/// @sa https://json.nlohmann.me/api/json_pointer/to_string/ 14572string_t to_string () const 14573{ 14574return std:: accumulate (reference_tokens. begin (), reference_tokens. end (), 14575string_t {}, 14576[]( const string_t & a, const string_t & b) 14577{ 14578return detail:: concat (a, '/' , detail:: escape (b)); 14579}); 14580} 14581 14582/// @brief return a string representation of the JSON pointer 14583/// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ 14584JSON_HEDLEY_DEPRECATED_FOR ( 3.11 . 0 , to_string ()) 14585operator string_t () const 14586{ 14587return to_string (); 14588} 14589 14590#ifndef JSON_NO_IO 14591/// @brief write string representation of the JSON pointer to stream 14592/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 14593friend std::ostream & operator<<(std:: ostream & o, const json_pointer & ptr) 14594{ 14595o << ptr. to_string (); 14596return o; 14597} 14598#endif 14599 14600/// @brief append another JSON pointer at the end of this JSON pointer 14601/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 14602json_pointer & operator/=( const json_pointer & ptr) 14603{ 14604reference_tokens. insert (reference_tokens. end (), 14605ptr. reference_tokens . begin (), 14606ptr. reference_tokens . end ()); 14607return * this; 14608} 14609 14610/// @brief append an unescaped reference token at the end of this JSON pointer 14611/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 14612json_pointer & operator/=( string_t token) 14613{ 14614push_back (std:: move (token)); 14615return * this; 14616} 14617 14618/// @brief append an array index at the end of this JSON pointer 14619/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 14620json_pointer & operator/=(std:: size_t array_idx) 14621{ 14622return * this /= std:: to_string (array_idx); 14623} 14624 14625/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer 14626/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 14627friend json_pointer operator/( const json_pointer & lhs, 14628const json_pointer & rhs) 14629{ 14630return json_pointer (lhs) /= rhs; 14631} 14632 14633/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer 14634/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 14635friend json_pointer operator/( const json_pointer & lhs, string_t token) // NOLINT(performance-unnecessary-value-param) 14636{ 14637return json_pointer (lhs) /= std:: move (token); 14638} 14639 14640/// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer 14641/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 14642friend json_pointer operator/( const json_pointer & lhs, std:: size_t array_idx) 14643{ 14644return json_pointer (lhs) /= array_idx; 14645} 14646 14647/// @brief returns the parent of this JSON pointer 14648/// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ 14649json_pointer parent_pointer () const 14650{ 14651if ( empty ()) 14652{ 14653return * this; 14654} 14655 14656json_pointer res = * this; 14657res. pop_back (); 14658return res; 14659} 14660 14661/// @brief remove last reference token 14662/// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ 14663void pop_back () 14664{ 14665if ( JSON_HEDLEY_UNLIKELY ( empty ())) 14666{ 14667JSON_THROW (detail::out_of_range::create( 405 , "JSON pointer has no parent" , nullptr )); 14668} 14669 14670reference_tokens. pop_back (); 14671} 14672 14673/// @brief return last reference token 14674/// @sa https://json.nlohmann.me/api/json_pointer/back/ 14675const string_t & back () const 14676{ 14677if ( JSON_HEDLEY_UNLIKELY ( empty ())) 14678{ 14679JSON_THROW (detail::out_of_range::create( 405 , "JSON pointer has no parent" , nullptr )); 14680} 14681 14682return reference_tokens. back (); 14683} 14684 14685/// @brief append an unescaped token at the end of the reference pointer 14686/// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 14687void push_back ( const string_t & token) 14688{ 14689reference_tokens. push_back (token); 14690} 14691 14692/// @brief append an unescaped token at the end of the reference pointer 14693/// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 14694void push_back ( string_t && token) 14695{ 14696reference_tokens. push_back (std:: move (token)); 14697} 14698 14699/// @brief return whether pointer points to the root document 14700/// @sa https://json.nlohmann.me/api/json_pointer/empty/ 14701bool empty () const noexcept 14702{ 14703return reference_tokens. empty (); 14704} 14705 14706private : 14707/*! 14708@param[in] s reference token to be converted into an array index 14709 14710@return integer representation of @a s 14711 14712@throw parse_error.106 if an array index begins with '0' 14713@throw parse_error.109 if an array index begins not with a digit 14714@throw out_of_range.404 if string @a s could not be converted to an integer 14715@throw out_of_range.410 if an array index exceeds size_type 14716*/ 14717template < typename BasicJsonType > 14718static typename BasicJsonType ::size_type array_index ( const string_t & s) 14719{ 14720using size_type = typename BasicJsonType ::size_type; 14721 14722// error condition (cf. RFC 6901, Sect. 4) 14723if ( JSON_HEDLEY_UNLIKELY (s. size () > 1 && s[ 0 ] == '0' )) 14724{ 14725JSON_THROW (detail::parse_error::create( 106 , 0 , detail:: concat ( "array index '" , s, "' must not begin with '0'" ), nullptr )); 14726} 14727 14728// error condition (cf. RFC 6901, Sect. 4) 14729if ( JSON_HEDLEY_UNLIKELY (s. size () > 1 && !(s[ 0 ] >= '1' && s[ 0 ] <= '9' ))) 14730{ 14731JSON_THROW (detail::parse_error::create( 109 , 0 , detail:: concat ( "array index '" , s, "' is not a number" ), nullptr )); 14732} 14733 14734const char * p = s. c_str (); 14735char * p_end = nullptr ; // NOLINT(misc-const-correctness) 14736errno = 0 ; // strtoull doesn't reset errno 14737const unsigned long long res = std:: strtoull (p, & p_end, 10 ); // NOLINT(runtime/int) 14738if (p == p_end // invalid input or empty string 14739|| errno == ERANGE // out of range 14740|| JSON_HEDLEY_UNLIKELY ( static_cast < std:: size_t > (p_end - p) != s. size ())) // incomplete read 14741{ 14742JSON_THROW (detail::out_of_range::create( 404 , detail:: concat ( "unresolved reference token '" , s, "'" ), nullptr )); 14743} 14744 14745// only triggered on special platforms (like 32bit), see also 14746// https://github.com/nlohmann/json/pull/2203 14747if (res >= static_cast < unsigned long long > ((std:: numeric_limits < size_type > ::max)())) // NOLINT(runtime/int) 14748{ 14749JSON_THROW (detail::out_of_range::create( 410 , detail:: concat ( "array index " , s, " exceeds size_type" ), nullptr )); // LCOV_EXCL_LINE 14750} 14751 14752return static_cast < size_type > (res); 14753} 14754 14755JSON_PRIVATE_UNLESS_TESTED : 14756json_pointer top () const 14757{ 14758if ( JSON_HEDLEY_UNLIKELY ( empty ())) 14759{ 14760JSON_THROW (detail::out_of_range::create( 405 , "JSON pointer has no parent" , nullptr )); 14761} 14762 14763json_pointer result = * this; 14764result. reference_tokens = {reference_tokens[ 0 ]}; 14765return result; 14766} 14767 14768private : 14769/*! 14770@brief create and return a reference to the pointed to value 14771 14772@complexity Linear in the number of reference tokens. 14773 14774@throw parse_error.109 if array index is not a number 14775@throw type_error.313 if value cannot be unflattened 14776*/ 14777template < typename BasicJsonType > 14778BasicJsonType & get_and_create ( BasicJsonType & j) const 14779{ 14780auto * result = & j; 14781 14782// in case no reference tokens exist, return a reference to the JSON value 14783// j which will be overwritten by a primitive value 14784for ( const auto & reference_token : reference_tokens) 14785{ 14786switch (result -> type ()) 14787{ 14788case detail::value_t::null: 14789{ 14790if (reference_token == "0" ) 14791{ 14792// start a new array if reference token is 0 14793result = & result -> operator[]( 0 ); 14794} 14795else 14796{ 14797// start a new object otherwise 14798result = & result -> operator[](reference_token); 14799} 14800break ; 14801} 14802 14803case detail::value_t::object: 14804{ 14805// create an entry in the object 14806result = & result -> operator[](reference_token); 14807break ; 14808} 14809 14810case detail::value_t::array: 14811{ 14812// create an entry in the array 14813result = & result -> operator[]( array_index < BasicJsonType > (reference_token)); 14814break ; 14815} 14816 14817/* 14818The following code is only reached if there exists a reference 14819token _and_ the current value is primitive. In this case, we have 14820an error situation, because primitive values may only occur as 14821single value; that is, with an empty list of reference tokens. 14822*/ 14823case detail::value_t::string: 14824case detail::value_t::boolean: 14825case detail::value_t::number_integer: 14826case detail::value_t::number_unsigned: 14827case detail::value_t::number_float: 14828case detail::value_t::binary: 14829case detail::value_t::discarded: 14830default : 14831JSON_THROW (detail::type_error::create( 313 , "invalid value to unflatten" , & j)); 14832} 14833} 14834 14835return * result; 14836} 14837 14838/*! 14839@brief return a reference to the pointed to value 14840 14841@note This version does not throw if a value is not present, but tries to 14842create nested values instead. For instance, calling this function 14843with pointer `"/this/that"` on a null value is equivalent to calling 14844`operator[]("this").operator[]("that")` on that value, effectively 14845changing the null value to an object. 14846 14847@param[in] ptr a JSON value 14848 14849@return reference to the JSON value pointed to by the JSON pointer 14850 14851@complexity Linear in the length of the JSON pointer. 14852 14853@throw parse_error.106 if an array index begins with '0' 14854@throw parse_error.109 if an array index was not a number 14855@throw out_of_range.404 if the JSON pointer can not be resolved 14856*/ 14857template < typename BasicJsonType > 14858BasicJsonType & get_unchecked ( BasicJsonType * ptr) const 14859{ 14860for ( const auto & reference_token : reference_tokens) 14861{ 14862// convert null values to arrays or objects before continuing 14863if (ptr -> is_null ()) 14864{ 14865// check if reference token is a number 14866const bool nums = 14867std:: all_of (reference_token. begin (), reference_token. end (), 14868[]( const unsigned char x) 14869{ 14870return std:: isdigit (x); 14871}); 14872 14873// change value to array for numbers or "-" or to object otherwise 14874* ptr = (nums || reference_token == "-" ) 14875? detail::value_t::array 14876: detail::value_t::object; 14877} 14878 14879switch (ptr -> type ()) 14880{ 14881case detail::value_t::object: 14882{ 14883// use unchecked object access 14884ptr = & ptr -> operator[](reference_token); 14885break ; 14886} 14887 14888case detail::value_t::array: 14889{ 14890if (reference_token == "-" ) 14891{ 14892// explicitly treat "-" as index beyond the end 14893ptr = & ptr -> operator[](ptr -> m_data . m_value . array -> size ()); 14894} 14895else 14896{ 14897// convert array index to number; unchecked access 14898ptr = & ptr -> operator[]( array_index < BasicJsonType > (reference_token)); 14899} 14900break ; 14901} 14902 14903case detail::value_t::null: 14904case detail::value_t::string: 14905case detail::value_t::boolean: 14906case detail::value_t::number_integer: 14907case detail::value_t::number_unsigned: 14908case detail::value_t::number_float: 14909case detail::value_t::binary: 14910case detail::value_t::discarded: 14911default : 14912JSON_THROW (detail::out_of_range::create( 404 , detail:: concat ( "unresolved reference token '" , reference_token, "'" ), ptr)); 14913} 14914} 14915 14916return * ptr; 14917} 14918 14919/*! 14920@throw parse_error.106 if an array index begins with '0' 14921@throw parse_error.109 if an array index was not a number 14922@throw out_of_range.402 if the array index '-' is used 14923@throw out_of_range.404 if the JSON pointer can not be resolved 14924*/ 14925template < typename BasicJsonType > 14926BasicJsonType & get_checked ( BasicJsonType * ptr) const 14927{ 14928for ( const auto & reference_token : reference_tokens) 14929{ 14930switch (ptr -> type ()) 14931{ 14932case detail::value_t::object: 14933{ 14934// note: at performs range check 14935ptr = & ptr -> at (reference_token); 14936break ; 14937} 14938 14939case detail::value_t::array: 14940{ 14941if ( JSON_HEDLEY_UNLIKELY (reference_token == "-" )) 14942{ 14943// "-" always fails the range check 14944JSON_THROW (detail::out_of_range::create( 402 , detail:: concat ( 14945"array index '-' (" , std:: to_string (ptr -> m_data . m_value . array -> size ()), 14946") is out of range" ), ptr)); 14947} 14948 14949// note: at performs range check 14950ptr = & ptr -> at ( array_index < BasicJsonType > (reference_token)); 14951break ; 14952} 14953 14954case detail::value_t::null: 14955case detail::value_t::string: 14956case detail::value_t::boolean: 14957case detail::value_t::number_integer: 14958case detail::value_t::number_unsigned: 14959case detail::value_t::number_float: 14960case detail::value_t::binary: 14961case detail::value_t::discarded: 14962default : 14963JSON_THROW (detail::out_of_range::create( 404 , detail:: concat ( "unresolved reference token '" , reference_token, "'" ), ptr)); 14964} 14965} 14966 14967return * ptr; 14968} 14969 14970/*! 14971@brief return a const reference to the pointed to value 14972 14973@param[in] ptr a JSON value 14974 14975@return const reference to the JSON value pointed to by the JSON 14976pointer 14977 14978@throw parse_error.106 if an array index begins with '0' 14979@throw parse_error.109 if an array index was not a number 14980@throw out_of_range.402 if the array index '-' is used 14981@throw out_of_range.404 if the JSON pointer can not be resolved 14982*/ 14983template < typename BasicJsonType > 14984const BasicJsonType & get_unchecked ( const BasicJsonType * ptr) const 14985{ 14986for ( const auto & reference_token : reference_tokens) 14987{ 14988switch (ptr -> type ()) 14989{ 14990case detail::value_t::object: 14991{ 14992// use unchecked object access 14993ptr = & ptr -> operator[](reference_token); 14994break ; 14995} 14996 14997case detail::value_t::array: 14998{ 14999if ( JSON_HEDLEY_UNLIKELY (reference_token == "-" )) 15000{ 15001// "-" cannot be used for const access 15002JSON_THROW (detail::out_of_range::create( 402 , detail:: concat ( "array index '-' (" , std:: to_string (ptr -> m_data . m_value . array -> size ()), ") is out of range" ), ptr)); 15003} 15004 15005// use unchecked array access 15006ptr = & ptr -> operator[]( array_index < BasicJsonType > (reference_token)); 15007break ; 15008} 15009 15010case detail::value_t::null: 15011case detail::value_t::string: 15012case detail::value_t::boolean: 15013case detail::value_t::number_integer: 15014case detail::value_t::number_unsigned: 15015case detail::value_t::number_float: 15016case detail::value_t::binary: 15017case detail::value_t::discarded: 15018default : 15019JSON_THROW (detail::out_of_range::create( 404 , detail:: concat ( "unresolved reference token '" , reference_token, "'" ), ptr)); 15020} 15021} 15022 15023return * ptr; 15024} 15025 15026/*! 15027@throw parse_error.106 if an array index begins with '0' 15028@throw parse_error.109 if an array index was not a number 15029@throw out_of_range.402 if the array index '-' is used 15030@throw out_of_range.404 if the JSON pointer can not be resolved 15031*/ 15032template < typename BasicJsonType > 15033const BasicJsonType & get_checked ( const BasicJsonType * ptr) const 15034{ 15035for ( const auto & reference_token : reference_tokens) 15036{ 15037switch (ptr -> type ()) 15038{ 15039case detail::value_t::object: 15040{ 15041// note: at performs range check 15042ptr = & ptr -> at (reference_token); 15043break ; 15044} 15045 15046case detail::value_t::array: 15047{ 15048if ( JSON_HEDLEY_UNLIKELY (reference_token == "-" )) 15049{ 15050// "-" always fails the range check 15051JSON_THROW (detail::out_of_range::create( 402 , detail:: concat ( 15052"array index '-' (" , std:: to_string (ptr -> m_data . m_value . array -> size ()), 15053") is out of range" ), ptr)); 15054} 15055 15056// note: at performs range check 15057ptr = & ptr -> at ( array_index < BasicJsonType > (reference_token)); 15058break ; 15059} 15060 15061case detail::value_t::null: 15062case detail::value_t::string: 15063case detail::value_t::boolean: 15064case detail::value_t::number_integer: 15065case detail::value_t::number_unsigned: 15066case detail::value_t::number_float: 15067case detail::value_t::binary: 15068case detail::value_t::discarded: 15069default : 15070JSON_THROW (detail::out_of_range::create( 404 , detail:: concat ( "unresolved reference token '" , reference_token, "'" ), ptr)); 15071} 15072} 15073 15074return * ptr; 15075} 15076 15077/*! 15078@throw parse_error.106 if an array index begins with '0' 15079@throw parse_error.109 if an array index was not a number 15080*/ 15081template < typename BasicJsonType > 15082bool contains ( const BasicJsonType * ptr) const 15083{ 15084for ( const auto & reference_token : reference_tokens) 15085{ 15086switch (ptr -> type ()) 15087{ 15088case detail::value_t::object: 15089{ 15090if (!ptr -> contains (reference_token)) 15091{ 15092// we did not find the key in the object 15093return false; 15094} 15095 15096ptr = & ptr -> operator[](reference_token); 15097break ; 15098} 15099 15100case detail::value_t::array: 15101{ 15102if ( JSON_HEDLEY_UNLIKELY (reference_token == "-" )) 15103{ 15104// "-" always fails the range check 15105return false; 15106} 15107if ( JSON_HEDLEY_UNLIKELY (reference_token. size () == 1 && !( "0" <= reference_token && reference_token <= "9" ))) 15108{ 15109// invalid char 15110return false; 15111} 15112if ( JSON_HEDLEY_UNLIKELY (reference_token. size () > 1 )) 15113{ 15114if ( JSON_HEDLEY_UNLIKELY (!( '1' <= reference_token[ 0 ] && reference_token[ 0 ] <= '9' ))) 15115{ 15116// first char should be between '1' and '9' 15117return false; 15118} 15119for (std:: size_t i = 1 ; i < reference_token. size (); i ++ ) 15120{ 15121if ( JSON_HEDLEY_UNLIKELY (!( '0' <= reference_token[i] && reference_token[i] <= '9' ))) 15122{ 15123// other char should be between '0' and '9' 15124return false; 15125} 15126} 15127} 15128 15129const auto idx = array_index < BasicJsonType > (reference_token); 15130if (idx >= ptr -> size ()) 15131{ 15132// index out of range 15133return false; 15134} 15135 15136ptr = & ptr -> operator[](idx); 15137break ; 15138} 15139 15140case detail::value_t::null: 15141case detail::value_t::string: 15142case detail::value_t::boolean: 15143case detail::value_t::number_integer: 15144case detail::value_t::number_unsigned: 15145case detail::value_t::number_float: 15146case detail::value_t::binary: 15147case detail::value_t::discarded: 15148default : 15149{ 15150// we do not expect primitive values if there is still a 15151// reference token to process 15152return false; 15153} 15154} 15155} 15156 15157// no reference token left means we found a primitive value 15158return true; 15159} 15160 15161/*! 15162@brief split the string input to reference tokens 15163 15164@note This function is only called by the json_pointer constructor. 15165All exceptions below are documented there. 15166 15167@throw parse_error.107 if the pointer is not empty or begins with '/' 15168@throw parse_error.108 if character '~' is not followed by '0' or '1' 15169*/ 15170static std:: vector < string_t > split ( const string_t & reference_string) 15171{ 15172std:: vector < string_t > result; 15173 15174// special case: empty reference string -> no reference tokens 15175if (reference_string. empty ()) 15176{ 15177return result; 15178} 15179 15180// check if nonempty reference string begins with slash 15181if ( JSON_HEDLEY_UNLIKELY (reference_string[ 0 ] != '/' )) 15182{ 15183JSON_THROW (detail::parse_error::create( 107 , 1 , detail:: concat ( "JSON pointer must be empty or begin with '/' - was: '" , reference_string, "'" ), nullptr )); 15184} 15185 15186// extract the reference tokens: 15187// - slash: position of the last read slash (or end of string) 15188// - start: position after the previous slash 15189for ( 15190// search for the first slash after the first character 15191std:: size_t slash = reference_string. find_first_of ( '/' , 1 ), 15192// set the beginning of the first reference token 15193start = 1 ; 15194// we can stop if start == 0 (if slash == string_t::npos) 15195start != 0 ; 15196// set the beginning of the next reference token 15197// (will eventually be 0 if slash == string_t::npos) 15198start = (slash == string_t::npos) ? 0 : slash + 1 , 15199// find next slash 15200slash = reference_string. find_first_of ( '/' , start)) 15201{ 15202// use the text between the beginning of the reference token 15203// (start) and the last slash (slash). 15204auto reference_token = reference_string. substr (start, slash - start); 15205 15206// check reference tokens are properly escaped 15207for (std:: size_t pos = reference_token. find_first_of ( '~' ); 15208pos != string_t::npos; 15209pos = reference_token. find_first_of ( '~' , pos + 1 )) 15210{ 15211JSON_ASSERT (reference_token[pos] == '~' ); 15212 15213// ~ must be followed by 0 or 1 15214if ( JSON_HEDLEY_UNLIKELY (pos == reference_token. size () - 1 || 15215(reference_token[pos + 1 ] != '0' && 15216reference_token[pos + 1 ] != '1' ))) 15217{ 15218JSON_THROW (detail::parse_error::create( 108 , 0 , "escape character '~' must be followed with '0' or '1'" , nullptr )); 15219} 15220} 15221 15222// finally, store the reference token 15223detail:: unescape (reference_token); 15224result. push_back (reference_token); 15225} 15226 15227return result; 15228} 15229 15230private : 15231/*! 15232@param[in] reference_string the reference string to the current value 15233@param[in] value the value to consider 15234@param[in,out] result the result object to insert values to 15235 15236@note Empty objects or arrays are flattened to `null`. 15237*/ 15238template < typename BasicJsonType > 15239static void flatten ( const string_t & reference_string, 15240const BasicJsonType & value, 15241BasicJsonType & result) 15242{ 15243switch (value. type ()) 15244{ 15245case detail::value_t::array: 15246{ 15247if (value. m_data . m_value . array -> empty ()) 15248{ 15249// flatten empty array as null 15250result[reference_string] = nullptr ; 15251} 15252else 15253{ 15254// iterate array and use index as reference string 15255for (std::size_t i = 0 ; i < value. m_data . m_value . array -> size (); ++ i) 15256{ 15257flatten (detail:: concat < string_t > (reference_string, '/' , std:: to_string (i)), 15258value. m_data . m_value . array -> operator[](i), result); 15259} 15260} 15261break; 15262} 15263 15264case detail::value_t::object: 15265{ 15266if (value. m_data . m_value . object -> empty ()) 15267{ 15268// flatten empty object as null 15269result[reference_string] = nullptr ; 15270} 15271else 15272{ 15273// iterate object and use keys as reference string 15274for (const auto & element : * value. m_data . m_value . object ) 15275{ 15276flatten (detail:: concat < string_t > (reference_string, '/' , detail:: escape (element. first )), element. second , result); 15277} 15278} 15279break; 15280} 15281 15282case detail::value_t::null: 15283case detail::value_t::string: 15284case detail::value_t::boolean: 15285case detail::value_t::number_integer: 15286case detail::value_t::number_unsigned: 15287case detail::value_t::number_float: 15288case detail::value_t::binary: 15289case detail::value_t::discarded: 15290default : 15291{ 15292// add primitive value with its reference string 15293result[reference_string] = value; 15294break ; 15295} 15296} 15297} 15298 15299/*! 15300@param[in] value flattened JSON 15301 15302@return unflattened JSON 15303 15304@throw parse_error.109 if array index is not a number 15305@throw type_error.314 if value is not an object 15306@throw type_error.315 if object values are not primitive 15307@throw type_error.313 if value cannot be unflattened 15308*/ 15309template < typename BasicJsonType > 15310static BasicJsonType 15311unflatten ( const BasicJsonType & value) 15312{ 15313if ( JSON_HEDLEY_UNLIKELY (!value. is_object ())) 15314{ 15315JSON_THROW (detail::type_error::create( 314 , "only objects can be unflattened" , & value)); 15316} 15317 15318BasicJsonType result; 15319 15320// iterate the JSON object values 15321for ( const auto & element : * value. m_data . m_value . object ) 15322{ 15323if ( JSON_HEDLEY_UNLIKELY (!element. second . is_primitive ())) 15324{ 15325JSON_THROW (detail::type_error::create( 315 , "values in object must be primitive" , & element. second )); 15326} 15327 15328// assign value to reference pointed to by JSON pointer; Note that if 15329// the JSON pointer is "" (i.e., points to the whole value), function 15330// get_and_create returns a reference to result itself. An assignment 15331// will then create a primitive value. 15332json_pointer (element. first ). get_and_create (result) = element. second ; 15333} 15334 15335return result; 15336} 15337 15338// can't use conversion operator because of ambiguity 15339json_pointer < string_t > convert () const & 15340{ 15341json_pointer < string_t > result; 15342result. reference_tokens = reference_tokens; 15343return result; 15344} 15345 15346json_pointer < string_t > convert () && 15347{ 15348json_pointer < string_t > result; 15349result. reference_tokens = std:: move (reference_tokens); 15350return result; 15351} 15352 15353public : 15354#if JSON_HAS_THREE_WAY_COMPARISON 15355/// @brief compares two JSON pointers for equality 15356/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 15357template < typename RefStringTypeRhs > 15358bool operator == ( const json_pointer < RefStringTypeRhs >& rhs) const noexcept 15359{ 15360return reference_tokens == rhs. reference_tokens ; 15361} 15362 15363/// @brief compares JSON pointer and string for equality 15364/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 15365JSON_HEDLEY_DEPRECATED_FOR ( 3.11 . 2 , operator == (json_pointer)) 15366bool operator == ( const string_t & rhs) const 15367{ 15368return * this == json_pointer (rhs); 15369} 15370 15371/// @brief 3-way compares two JSON pointers 15372template < typename RefStringTypeRhs > 15373std:: strong_ordering operator<=>( const json_pointer < RefStringTypeRhs >& rhs) const noexcept // *NOPAD* 15374{ 15375return reference_tokens <=> rhs. reference_tokens ; // *NOPAD* 15376} 15377#else 15378/// @brief compares two JSON pointers for equality 15379/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 15380template < typename RefStringTypeLhs , typename RefStringTypeRhs > 15381// NOLINTNEXTLINE(readability-redundant-declaration) 15382friend bool operator == ( const json_pointer < RefStringTypeLhs >& lhs, 15383const json_pointer < RefStringTypeRhs >& rhs) noexcept ; 15384 15385/// @brief compares JSON pointer and string for equality 15386/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 15387template < typename RefStringTypeLhs , typename StringType > 15388// NOLINTNEXTLINE(readability-redundant-declaration) 15389friend bool operator == ( const json_pointer < RefStringTypeLhs >& lhs, 15390const StringType & rhs); 15391 15392/// @brief compares string and JSON pointer for equality 15393/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 15394template < typename RefStringTypeRhs , typename StringType > 15395// NOLINTNEXTLINE(readability-redundant-declaration) 15396friend bool operator == ( const StringType & lhs, 15397const json_pointer < RefStringTypeRhs >& rhs); 15398 15399/// @brief compares two JSON pointers for inequality 15400/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 15401template < typename RefStringTypeLhs , typename RefStringTypeRhs > 15402// NOLINTNEXTLINE(readability-redundant-declaration) 15403friend bool operator != ( const json_pointer < RefStringTypeLhs >& lhs, 15404const json_pointer < RefStringTypeRhs >& rhs) noexcept ; 15405 15406/// @brief compares JSON pointer and string for inequality 15407/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 15408template < typename RefStringTypeLhs , typename StringType > 15409// NOLINTNEXTLINE(readability-redundant-declaration) 15410friend bool operator != ( const json_pointer < RefStringTypeLhs >& lhs, 15411const StringType & rhs); 15412 15413/// @brief compares string and JSON pointer for inequality 15414/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 15415template < typename RefStringTypeRhs , typename StringType > 15416// NOLINTNEXTLINE(readability-redundant-declaration) 15417friend bool operator != ( const StringType & lhs, 15418const json_pointer < RefStringTypeRhs >& rhs); 15419 15420/// @brief compares two JSON pointer for less-than 15421template < typename RefStringTypeLhs , typename RefStringTypeRhs > 15422// NOLINTNEXTLINE(readability-redundant-declaration) 15423friend bool operator < ( const json_pointer < RefStringTypeLhs >& lhs, 15424const json_pointer < RefStringTypeRhs >& rhs) noexcept ; 15425#endif 15426 15427private : 15428/// the reference tokens 15429std:: vector < string_t > reference_tokens; 15430}; 15431 15432#if ! JSON_HAS_THREE_WAY_COMPARISON 15433// functions cannot be defined inside class due to ODR violations 15434template < typename RefStringTypeLhs , typename RefStringTypeRhs > 15435inline bool operator == ( const json_pointer < RefStringTypeLhs >& lhs, 15436const json_pointer < RefStringTypeRhs >& rhs) noexcept 15437{ 15438return lhs. reference_tokens == rhs. reference_tokens ; 15439} 15440 15441template < typename RefStringTypeLhs , 15442typename StringType = typename json_pointer < RefStringTypeLhs > :: string_t > 15443JSON_HEDLEY_DEPRECATED_FOR ( 3.11.2 , operator == ( json_pointer , json_pointer )) 15444inline bool operator == ( const json_pointer < RefStringTypeLhs >& lhs, 15445const StringType & rhs) 15446{ 15447return lhs == json_pointer < RefStringTypeLhs > (rhs); 15448} 15449 15450template < typename RefStringTypeRhs , 15451typename StringType = typename json_pointer < RefStringTypeRhs > :: string_t > 15452JSON_HEDLEY_DEPRECATED_FOR ( 3.11.2 , operator == ( json_pointer , json_pointer )) 15453inline bool operator == ( const StringType & lhs, 15454const json_pointer < RefStringTypeRhs >& rhs) 15455{ 15456return json_pointer < RefStringTypeRhs > (lhs) == rhs; 15457} 15458 15459template < typename RefStringTypeLhs , typename RefStringTypeRhs > 15460inline bool operator != ( const json_pointer < RefStringTypeLhs >& lhs, 15461const json_pointer < RefStringTypeRhs >& rhs) noexcept 15462{ 15463return !(lhs == rhs); 15464} 15465 15466template < typename RefStringTypeLhs , 15467typename StringType = typename json_pointer < RefStringTypeLhs > :: string_t > 15468JSON_HEDLEY_DEPRECATED_FOR ( 3.11.2 , operator != ( json_pointer , json_pointer )) 15469inline bool operator != ( const json_pointer < RefStringTypeLhs >& lhs, 15470const StringType & rhs) 15471{ 15472return !(lhs == rhs); 15473} 15474 15475template < typename RefStringTypeRhs , 15476typename StringType = typename json_pointer < RefStringTypeRhs > :: string_t > 15477JSON_HEDLEY_DEPRECATED_FOR ( 3.11.2 , operator != ( json_pointer , json_pointer )) 15478inline bool operator != ( const StringType & lhs, 15479const json_pointer < RefStringTypeRhs >& rhs) 15480{ 15481return !(lhs == rhs); 15482} 15483 15484template < typename RefStringTypeLhs , typename RefStringTypeRhs > 15485inline bool operator < ( const json_pointer < RefStringTypeLhs >& lhs, 15486const json_pointer < RefStringTypeRhs >& rhs) noexcept 15487{ 15488return lhs. reference_tokens < rhs. reference_tokens ; 15489} 15490#endif 15491 15492NLOHMANN_JSON_NAMESPACE_END 15493 15494// #include <nlohmann/detail/json_ref.hpp> 15495// __ _____ _____ _____ 15496// __| | __| | | | JSON for Modern C++ 15497// | | |__ | | | | | | version 3.12.0 15498// |_____|_____|_____|_|___| https://github.com/nlohmann/json 15499// 15500// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 15501// SPDX-License-Identifier: MIT 15502 15503 15504 15505#include <initializer_list> 15506#include <utility> 15507 15508// #include <nlohmann/detail/abi_macros.hpp> 15509 15510// #include <nlohmann/detail/meta/type_traits.hpp> 15511 15512 15513NLOHMANN_JSON_NAMESPACE_BEGIN 15514namespace detail 15515{ 15516 15517template < typename BasicJsonType > 15518class json_ref 15519{ 15520public : 15521using value_type = BasicJsonType ; 15522 15523json_ref ( value_type && value) 15524: owned_value (std:: move (value)) 15525{} 15526 15527json_ref ( const value_type & value) 15528: value_ref ( & value) 15529{} 15530 15531json_ref (std:: initializer_list < json_ref > init) 15532: owned_value (init) 15533{} 15534 15535template < 15536class ... Args , 15537enable_if_t < std:: is_constructible < value_type , Args ... > :: value , int > = 0 > 15538json_ref ( Args && ... args) 15539: owned_value (std:: forward < Args > (args)...) 15540{} 15541 15542// class should be movable only 15543json_ref ( json_ref && ) noexcept = default ; 15544json_ref ( const json_ref & ) = delete ; 15545json_ref & operator = ( const json_ref & ) = delete ; 15546json_ref & operator = ( json_ref && ) = delete ; 15547~json_ref() = default ; 15548 15549value_type moved_or_copied () const 15550{ 15551if (value_ref == nullptr ) 15552{ 15553return std:: move (owned_value); 15554} 15555return * value_ref; 15556} 15557 15558value_type const & operator * () const 15559{ 15560return value_ref ? * value_ref : owned_value; 15561} 15562 15563value_type const * operator -> () const 15564{ 15565return &** this; 15566} 15567 15568private : 15569mutable value_type owned_value = nullptr ; 15570value_type const * value_ref = nullptr ; 15571}; 15572 15573} // namespace detail 15574NLOHMANN_JSON_NAMESPACE_END 15575 15576// #include <nlohmann/detail/macro_scope.hpp> 15577 15578// #include <nlohmann/detail/string_concat.hpp> 15579 15580// #include <nlohmann/detail/string_escape.hpp> 15581 15582// #include <nlohmann/detail/string_utils.hpp> 15583 15584// #include <nlohmann/detail/meta/cpp_future.hpp> 15585 15586// #include <nlohmann/detail/meta/type_traits.hpp> 15587 15588// #include <nlohmann/detail/output/binary_writer.hpp> 15589// __ _____ _____ _____ 15590// __| | __| | | | JSON for Modern C++ 15591// | | |__ | | | | | | version 3.12.0 15592// |_____|_____|_____|_|___| https://github.com/nlohmann/json 15593// 15594// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 15595// SPDX-License-Identifier: MIT 15596 15597 15598 15599#include <algorithm> // reverse 15600#include <array> // array 15601#include <map> // map 15602#include <cmath> // isnan, isinf 15603#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 15604#include <cstring> // memcpy 15605#include <limits> // numeric_limits 15606#include <string> // string 15607#include <utility> // move 15608#include <vector> // vector 15609 15610// #include <nlohmann/detail/input/binary_reader.hpp> 15611 15612// #include <nlohmann/detail/macro_scope.hpp> 15613 15614// #include <nlohmann/detail/output/output_adapters.hpp> 15615// __ _____ _____ _____ 15616// __| | __| | | | JSON for Modern C++ 15617// | | |__ | | | | | | version 3.12.0 15618// |_____|_____|_____|_|___| https://github.com/nlohmann/json 15619// 15620// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 15621// SPDX-License-Identifier: MIT 15622 15623 15624 15625#include <algorithm> // copy 15626#include <cstddef> // size_t 15627#include <iterator> // back_inserter 15628#include <memory> // shared_ptr, make_shared 15629#include <string> // basic_string 15630#include <vector> // vector 15631 15632#ifndef JSON_NO_IO 15633#include <ios> // streamsize 15634#include <ostream> // basic_ostream 15635#endif // JSON_NO_IO 15636 15637// #include <nlohmann/detail/macro_scope.hpp> 15638 15639 15640NLOHMANN_JSON_NAMESPACE_BEGIN 15641namespace detail 15642{ 15643 15644/// abstract output adapter interface 15645template < typename CharType > struct output_adapter_protocol 15646{ 15647virtual void write_character ( CharType c) = 0 ; 15648virtual void write_characters ( const CharType * s, std:: size_t length) = 0 ; 15649virtual ~output_adapter_protocol() = default ; 15650 15651output_adapter_protocol () = default ; 15652output_adapter_protocol ( const output_adapter_protocol & ) = default ; 15653output_adapter_protocol ( output_adapter_protocol && ) noexcept = default ; 15654output_adapter_protocol & operator = ( const output_adapter_protocol & ) = default ; 15655output_adapter_protocol & operator = ( output_adapter_protocol && ) noexcept = default ; 15656}; 15657 15658/// a type to simplify interfaces 15659template < typename CharType > 15660using output_adapter_t = std:: shared_ptr < output_adapter_protocol < CharType >> ; 15661 15662/// output adapter for byte vectors 15663template < typename CharType , typename AllocatorType = std:: allocator < CharType >> 15664class output_vector_adapter : public output_adapter_protocol < CharType > 15665{ 15666public : 15667explicit output_vector_adapter (std:: vector < CharType , AllocatorType >& vec) noexcept 15668: v (vec) 15669{} 15670 15671void write_character ( CharType c) override 15672{ 15673v. push_back (c); 15674} 15675 15676JSON_HEDLEY_NON_NULL ( 2 ) 15677void write_characters ( const CharType * s, std:: size_t length) override 15678{ 15679v. insert (v. end (), s, s + length); 15680} 15681 15682private : 15683std:: vector < CharType , AllocatorType >& v ; 15684}; 15685 15686#ifndef JSON_NO_IO 15687/// output adapter for output streams 15688template < typename CharType > 15689class output_stream_adapter : public output_adapter_protocol < CharType > 15690{ 15691public : 15692explicit output_stream_adapter (std:: basic_ostream < CharType >& s) noexcept 15693: stream (s) 15694{} 15695 15696void write_character ( CharType c) override 15697{ 15698stream. put (c); 15699} 15700 15701JSON_HEDLEY_NON_NULL ( 2 ) 15702void write_characters ( const CharType * s, std:: size_t length) override 15703{ 15704stream. write (s, static_cast < std:: streamsize > (length)); 15705} 15706 15707private : 15708std:: basic_ostream < CharType >& stream ; 15709}; 15710#endif // JSON_NO_IO 15711 15712/// output adapter for basic_string 15713template < typename CharType , typename StringType = std:: basic_string < CharType >> 15714class output_string_adapter : public output_adapter_protocol < CharType > 15715{ 15716public : 15717explicit output_string_adapter ( StringType & s) noexcept 15718: str (s) 15719{} 15720 15721void write_character ( CharType c) override 15722{ 15723str. push_back (c); 15724} 15725 15726JSON_HEDLEY_NON_NULL ( 2 ) 15727void write_characters ( const CharType * s, std:: size_t length) override 15728{ 15729str. append (s, length); 15730} 15731 15732private : 15733StringType & str ; 15734}; 15735 15736template < typename CharType , typename StringType = std:: basic_string < CharType >> 15737class output_adapter 15738{ 15739public : 15740template < typename AllocatorType = std:: allocator < CharType >> 15741output_adapter (std:: vector < CharType , AllocatorType >& vec) 15742: oa (std:: make_shared < output_vector_adapter < CharType , AllocatorType >> (vec)) {} 15743 15744#ifndef JSON_NO_IO 15745output_adapter (std:: basic_ostream < CharType >& s) 15746: oa (std:: make_shared < output_stream_adapter < CharType >> (s)) {} 15747#endif // JSON_NO_IO 15748 15749output_adapter ( StringType & s) 15750: oa (std:: make_shared < output_string_adapter < CharType , StringType >> (s)) {} 15751 15752operator output_adapter_t < CharType > () 15753{ 15754return oa; 15755} 15756 15757private : 15758output_adapter_t < CharType > oa = nullptr ; 15759}; 15760 15761} // namespace detail 15762NLOHMANN_JSON_NAMESPACE_END 15763 15764// #include <nlohmann/detail/string_concat.hpp> 15765 15766 15767NLOHMANN_JSON_NAMESPACE_BEGIN 15768namespace detail 15769{ 15770 15771/// how to encode BJData 15772enum class bjdata_version_t 15773{ 15774draft2, 15775draft3, 15776}; 15777 15778/////////////////// 15779// binary writer // 15780/////////////////// 15781 15782/*! 15783@brief serialization to CBOR and MessagePack values 15784*/ 15785template < typename BasicJsonType , typename CharType > 15786class binary_writer 15787{ 15788using string_t = typename BasicJsonType :: string_t ; 15789using binary_t = typename BasicJsonType :: binary_t ; 15790using number_float_t = typename BasicJsonType :: number_float_t ; 15791 15792public : 15793/*! 15794@brief create a binary writer 15795 15796@param[in] adapter output adapter to write to 15797*/ 15798explicit binary_writer ( output_adapter_t < CharType > adapter) : oa (std:: move (adapter)) 15799{ 15800JSON_ASSERT (oa); 15801} 15802 15803/*! 15804@param[in] j JSON value to serialize 15805@pre j.type() == value_t::object 15806*/ 15807void write_bson ( const BasicJsonType & j) 15808{ 15809switch (j. type ()) 15810{ 15811case value_t::object: 15812{ 15813write_bson_object ( * j. m_data . m_value . object ); 15814break ; 15815} 15816 15817case value_t::null: 15818case value_t::array: 15819case value_t::string: 15820case value_t::boolean: 15821case value_t::number_integer: 15822case value_t::number_unsigned: 15823case value_t::number_float: 15824case value_t::binary: 15825case value_t::discarded: 15826default : 15827{ 15828JSON_THROW (type_error:: create ( 317 , concat ( "to serialize to BSON, top-level type must be object, but is " , j. type_name ()), & j)); 15829} 15830} 15831} 15832 15833/*! 15834@param[in] j JSON value to serialize 15835*/ 15836void write_cbor ( const BasicJsonType & j) 15837{ 15838switch (j. type ()) 15839{ 15840case value_t::null: 15841{ 15842oa -> write_character ( to_char_type ( 0xF6 )); 15843break ; 15844} 15845 15846case value_t::boolean: 15847{ 15848oa -> write_character (j. m_data . m_value . boolean 15849? to_char_type ( 0xF5 ) 15850: to_char_type ( 0xF4 )); 15851break ; 15852} 15853 15854case value_t::number_integer: 15855{ 15856if (j. m_data . m_value . number_integer >= 0 ) 15857{ 15858// CBOR does not differentiate between positive signed 15859// integers and unsigned integers. Therefore, we used the 15860// code from the value_t::number_unsigned case here. 15861if (j. m_data . m_value . number_integer <= 0x17 ) 15862{ 15863write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_integer )); 15864} 15865else if (j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: uint8_t > ::max)()) 15866{ 15867oa -> write_character ( to_char_type ( 0x18 )); 15868write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_integer )); 15869} 15870else if (j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: uint16_t > ::max)()) 15871{ 15872oa -> write_character ( to_char_type ( 0x19 )); 15873write_number ( static_cast < std:: uint16_t > (j. m_data . m_value . number_integer )); 15874} 15875else if (j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: uint32_t > ::max)()) 15876{ 15877oa -> write_character ( to_char_type ( 0x1A )); 15878write_number ( static_cast < std:: uint32_t > (j. m_data . m_value . number_integer )); 15879} 15880else 15881{ 15882oa -> write_character ( to_char_type ( 0x1B )); 15883write_number ( static_cast < std:: uint64_t > (j. m_data . m_value . number_integer )); 15884} 15885} 15886else 15887{ 15888// The conversions below encode the sign in the first 15889// byte, and the value is converted to a positive number. 15890const auto positive_number = -1 - j. m_data . m_value . number_integer ; 15891if (j. m_data . m_value . number_integer >= -24 ) 15892{ 15893write_number ( static_cast < std:: uint8_t > ( 0x20 + positive_number)); 15894} 15895else if (positive_number <= (std:: numeric_limits < std:: uint8_t > ::max)()) 15896{ 15897oa -> write_character ( to_char_type ( 0x38 )); 15898write_number ( static_cast < std:: uint8_t > (positive_number)); 15899} 15900else if (positive_number <= (std:: numeric_limits < std:: uint16_t > ::max)()) 15901{ 15902oa -> write_character ( to_char_type ( 0x39 )); 15903write_number ( static_cast < std:: uint16_t > (positive_number)); 15904} 15905else if (positive_number <= (std:: numeric_limits < std:: uint32_t > ::max)()) 15906{ 15907oa -> write_character ( to_char_type ( 0x3A )); 15908write_number ( static_cast < std:: uint32_t > (positive_number)); 15909} 15910else 15911{ 15912oa -> write_character ( to_char_type ( 0x3B )); 15913write_number ( static_cast < std:: uint64_t > (positive_number)); 15914} 15915} 15916break ; 15917} 15918 15919case value_t::number_unsigned: 15920{ 15921if (j. m_data . m_value . number_unsigned <= 0x17 ) 15922{ 15923write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_unsigned )); 15924} 15925else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint8_t > ::max)()) 15926{ 15927oa -> write_character ( to_char_type ( 0x18 )); 15928write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_unsigned )); 15929} 15930else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint16_t > ::max)()) 15931{ 15932oa -> write_character ( to_char_type ( 0x19 )); 15933write_number ( static_cast < std:: uint16_t > (j. m_data . m_value . number_unsigned )); 15934} 15935else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint32_t > ::max)()) 15936{ 15937oa -> write_character ( to_char_type ( 0x1A )); 15938write_number ( static_cast < std:: uint32_t > (j. m_data . m_value . number_unsigned )); 15939} 15940else 15941{ 15942oa -> write_character ( to_char_type ( 0x1B )); 15943write_number ( static_cast < std:: uint64_t > (j. m_data . m_value . number_unsigned )); 15944} 15945break ; 15946} 15947 15948case value_t::number_float: 15949{ 15950if (std:: isnan (j. m_data . m_value . number_float )) 15951{ 15952// NaN is 0xf97e00 in CBOR 15953oa -> write_character ( to_char_type ( 0xF9 )); 15954oa -> write_character ( to_char_type ( 0x7E )); 15955oa -> write_character ( to_char_type ( 0x00 )); 15956} 15957else if (std:: isinf (j. m_data . m_value . number_float )) 15958{ 15959// Infinity is 0xf97c00, -Infinity is 0xf9fc00 15960oa -> write_character ( to_char_type ( 0xf9 )); 15961oa -> write_character (j. m_data . m_value . number_float > 0 ? to_char_type ( 0x7C ) : to_char_type ( 0xFC )); 15962oa -> write_character ( to_char_type ( 0x00 )); 15963} 15964else 15965{ 15966write_compact_float (j. m_data . m_value . number_float , detail::input_format_t::cbor); 15967} 15968break ; 15969} 15970 15971case value_t::string: 15972{ 15973// step 1: write control byte and the string length 15974const auto N = j. m_data . m_value . string -> size (); 15975if ( N <= 0x17 ) 15976{ 15977write_number ( static_cast < std:: uint8_t > ( 0x60 + N )); 15978} 15979else if ( N <= (std:: numeric_limits < std:: uint8_t > ::max)()) 15980{ 15981oa -> write_character ( to_char_type ( 0x78 )); 15982write_number ( static_cast < std:: uint8_t > ( N )); 15983} 15984else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 15985{ 15986oa -> write_character ( to_char_type ( 0x79 )); 15987write_number ( static_cast < std:: uint16_t > ( N )); 15988} 15989else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 15990{ 15991oa -> write_character ( to_char_type ( 0x7A )); 15992write_number ( static_cast < std:: uint32_t > ( N )); 15993} 15994// LCOV_EXCL_START 15995else if ( N <= (std:: numeric_limits < std:: uint64_t > ::max)()) 15996{ 15997oa -> write_character ( to_char_type ( 0x7B )); 15998write_number ( static_cast < std:: uint64_t > ( N )); 15999} 16000// LCOV_EXCL_STOP 16001 16002// step 2: write the string 16003oa -> write_characters ( 16004reinterpret_cast < const CharType *> (j. m_data . m_value . string -> c_str ()), 16005j. m_data . m_value . string -> size ()); 16006break ; 16007} 16008 16009case value_t::array: 16010{ 16011// step 1: write control byte and the array size 16012const auto N = j. m_data . m_value . array -> size (); 16013if ( N <= 0x17 ) 16014{ 16015write_number ( static_cast < std:: uint8_t > ( 0x80 + N )); 16016} 16017else if ( N <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16018{ 16019oa -> write_character ( to_char_type ( 0x98 )); 16020write_number ( static_cast < std:: uint8_t > ( N )); 16021} 16022else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16023{ 16024oa -> write_character ( to_char_type ( 0x99 )); 16025write_number ( static_cast < std:: uint16_t > ( N )); 16026} 16027else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16028{ 16029oa -> write_character ( to_char_type ( 0x9A )); 16030write_number ( static_cast < std:: uint32_t > ( N )); 16031} 16032// LCOV_EXCL_START 16033else if ( N <= (std:: numeric_limits < std:: uint64_t > ::max)()) 16034{ 16035oa -> write_character ( to_char_type ( 0x9B )); 16036write_number ( static_cast < std:: uint64_t > ( N )); 16037} 16038// LCOV_EXCL_STOP 16039 16040// step 2: write each element 16041for ( const auto & el : * j. m_data . m_value . array ) 16042{ 16043write_cbor (el); 16044} 16045break ; 16046} 16047 16048case value_t::binary: 16049{ 16050if (j. m_data . m_value . binary -> has_subtype ()) 16051{ 16052if (j. m_data . m_value . binary -> subtype () <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16053{ 16054write_number ( static_cast < std:: uint8_t > ( 0xd8 )); 16055write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . binary -> subtype ())); 16056} 16057else if (j. m_data . m_value . binary -> subtype () <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16058{ 16059write_number ( static_cast < std:: uint8_t > ( 0xd9 )); 16060write_number ( static_cast < std:: uint16_t > (j. m_data . m_value . binary -> subtype ())); 16061} 16062else if (j. m_data . m_value . binary -> subtype () <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16063{ 16064write_number ( static_cast < std:: uint8_t > ( 0xda )); 16065write_number ( static_cast < std:: uint32_t > (j. m_data . m_value . binary -> subtype ())); 16066} 16067else if (j. m_data . m_value . binary -> subtype () <= (std:: numeric_limits < std:: uint64_t > ::max)()) 16068{ 16069write_number ( static_cast < std:: uint8_t > ( 0xdb )); 16070write_number ( static_cast < std:: uint64_t > (j. m_data . m_value . binary -> subtype ())); 16071} 16072} 16073 16074// step 1: write control byte and the binary array size 16075const auto N = j. m_data . m_value . binary -> size (); 16076if ( N <= 0x17 ) 16077{ 16078write_number ( static_cast < std:: uint8_t > ( 0x40 + N )); 16079} 16080else if ( N <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16081{ 16082oa -> write_character ( to_char_type ( 0x58 )); 16083write_number ( static_cast < std:: uint8_t > ( N )); 16084} 16085else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16086{ 16087oa -> write_character ( to_char_type ( 0x59 )); 16088write_number ( static_cast < std:: uint16_t > ( N )); 16089} 16090else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16091{ 16092oa -> write_character ( to_char_type ( 0x5A )); 16093write_number ( static_cast < std:: uint32_t > ( N )); 16094} 16095// LCOV_EXCL_START 16096else if ( N <= (std:: numeric_limits < std:: uint64_t > ::max)()) 16097{ 16098oa -> write_character ( to_char_type ( 0x5B )); 16099write_number ( static_cast < std:: uint64_t > ( N )); 16100} 16101// LCOV_EXCL_STOP 16102 16103// step 2: write each element 16104oa -> write_characters ( 16105reinterpret_cast < const CharType *> (j. m_data . m_value . binary -> data ()), 16106N ); 16107 16108break ; 16109} 16110 16111case value_t::object: 16112{ 16113// step 1: write control byte and the object size 16114const auto N = j. m_data . m_value . object -> size (); 16115if ( N <= 0x17 ) 16116{ 16117write_number ( static_cast < std:: uint8_t > ( 0xA0 + N )); 16118} 16119else if ( N <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16120{ 16121oa -> write_character ( to_char_type ( 0xB8 )); 16122write_number ( static_cast < std:: uint8_t > ( N )); 16123} 16124else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16125{ 16126oa -> write_character ( to_char_type ( 0xB9 )); 16127write_number ( static_cast < std:: uint16_t > ( N )); 16128} 16129else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16130{ 16131oa -> write_character ( to_char_type ( 0xBA )); 16132write_number ( static_cast < std:: uint32_t > ( N )); 16133} 16134// LCOV_EXCL_START 16135else if ( N <= (std:: numeric_limits < std:: uint64_t > ::max)()) 16136{ 16137oa -> write_character ( to_char_type ( 0xBB )); 16138write_number ( static_cast < std:: uint64_t > ( N )); 16139} 16140// LCOV_EXCL_STOP 16141 16142// step 2: write each element 16143for ( const auto & el : * j. m_data . m_value . object ) 16144{ 16145write_cbor (el. first ); 16146write_cbor (el. second ); 16147} 16148break ; 16149} 16150 16151case value_t::discarded: 16152default : 16153break ; 16154} 16155} 16156 16157/*! 16158@param[in] j JSON value to serialize 16159*/ 16160void write_msgpack ( const BasicJsonType & j) 16161{ 16162switch (j. type ()) 16163{ 16164case value_t::null: // nil 16165{ 16166oa -> write_character ( to_char_type ( 0xC0 )); 16167break ; 16168} 16169 16170case value_t::boolean: // true and false 16171{ 16172oa -> write_character (j. m_data . m_value . boolean 16173? to_char_type ( 0xC3 ) 16174: to_char_type ( 0xC2 )); 16175break ; 16176} 16177 16178case value_t::number_integer: 16179{ 16180if (j. m_data . m_value . number_integer >= 0 ) 16181{ 16182// MessagePack does not differentiate between positive 16183// signed integers and unsigned integers. Therefore, we used 16184// the code from the value_t::number_unsigned case here. 16185if (j. m_data . m_value . number_unsigned < 128 ) 16186{ 16187// positive fixnum 16188write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_integer )); 16189} 16190else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16191{ 16192// uint 8 16193oa -> write_character ( to_char_type ( 0xCC )); 16194write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_integer )); 16195} 16196else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16197{ 16198// uint 16 16199oa -> write_character ( to_char_type ( 0xCD )); 16200write_number ( static_cast < std:: uint16_t > (j. m_data . m_value . number_integer )); 16201} 16202else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16203{ 16204// uint 32 16205oa -> write_character ( to_char_type ( 0xCE )); 16206write_number ( static_cast < std:: uint32_t > (j. m_data . m_value . number_integer )); 16207} 16208else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint64_t > ::max)()) 16209{ 16210// uint 64 16211oa -> write_character ( to_char_type ( 0xCF )); 16212write_number ( static_cast < std:: uint64_t > (j. m_data . m_value . number_integer )); 16213} 16214} 16215else 16216{ 16217if (j. m_data . m_value . number_integer >= -32 ) 16218{ 16219// negative fixnum 16220write_number ( static_cast < std:: int8_t > (j. m_data . m_value . number_integer )); 16221} 16222else if (j. m_data . m_value . number_integer >= (std:: numeric_limits < std:: int8_t > ::min)() && 16223j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int8_t > ::max)()) 16224{ 16225// int 8 16226oa -> write_character ( to_char_type ( 0xD0 )); 16227write_number ( static_cast < std:: int8_t > (j. m_data . m_value . number_integer )); 16228} 16229else if (j. m_data . m_value . number_integer >= (std:: numeric_limits < std:: int16_t > ::min)() && 16230j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int16_t > ::max)()) 16231{ 16232// int 16 16233oa -> write_character ( to_char_type ( 0xD1 )); 16234write_number ( static_cast < std:: int16_t > (j. m_data . m_value . number_integer )); 16235} 16236else if (j. m_data . m_value . number_integer >= (std:: numeric_limits < std:: int32_t > ::min)() && 16237j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int32_t > ::max)()) 16238{ 16239// int 32 16240oa -> write_character ( to_char_type ( 0xD2 )); 16241write_number ( static_cast < std:: int32_t > (j. m_data . m_value . number_integer )); 16242} 16243else if (j. m_data . m_value . number_integer >= (std:: numeric_limits < std:: int64_t > ::min)() && 16244j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int64_t > ::max)()) 16245{ 16246// int 64 16247oa -> write_character ( to_char_type ( 0xD3 )); 16248write_number ( static_cast < std:: int64_t > (j. m_data . m_value . number_integer )); 16249} 16250} 16251break ; 16252} 16253 16254case value_t::number_unsigned: 16255{ 16256if (j. m_data . m_value . number_unsigned < 128 ) 16257{ 16258// positive fixnum 16259write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_integer )); 16260} 16261else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16262{ 16263// uint 8 16264oa -> write_character ( to_char_type ( 0xCC )); 16265write_number ( static_cast < std:: uint8_t > (j. m_data . m_value . number_integer )); 16266} 16267else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16268{ 16269// uint 16 16270oa -> write_character ( to_char_type ( 0xCD )); 16271write_number ( static_cast < std:: uint16_t > (j. m_data . m_value . number_integer )); 16272} 16273else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16274{ 16275// uint 32 16276oa -> write_character ( to_char_type ( 0xCE )); 16277write_number ( static_cast < std:: uint32_t > (j. m_data . m_value . number_integer )); 16278} 16279else if (j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint64_t > ::max)()) 16280{ 16281// uint 64 16282oa -> write_character ( to_char_type ( 0xCF )); 16283write_number ( static_cast < std:: uint64_t > (j. m_data . m_value . number_integer )); 16284} 16285break ; 16286} 16287 16288case value_t::number_float: 16289{ 16290write_compact_float (j. m_data . m_value . number_float , detail::input_format_t::msgpack); 16291break ; 16292} 16293 16294case value_t::string: 16295{ 16296// step 1: write control byte and the string length 16297const auto N = j. m_data . m_value . string -> size (); 16298if ( N <= 31 ) 16299{ 16300// fixstr 16301write_number ( static_cast < std:: uint8_t > ( 0xA0 | N )); 16302} 16303else if ( N <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16304{ 16305// str 8 16306oa -> write_character ( to_char_type ( 0xD9 )); 16307write_number ( static_cast < std:: uint8_t > ( N )); 16308} 16309else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16310{ 16311// str 16 16312oa -> write_character ( to_char_type ( 0xDA )); 16313write_number ( static_cast < std:: uint16_t > ( N )); 16314} 16315else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16316{ 16317// str 32 16318oa -> write_character ( to_char_type ( 0xDB )); 16319write_number ( static_cast < std:: uint32_t > ( N )); 16320} 16321 16322// step 2: write the string 16323oa -> write_characters ( 16324reinterpret_cast < const CharType *> (j. m_data . m_value . string -> c_str ()), 16325j. m_data . m_value . string -> size ()); 16326break ; 16327} 16328 16329case value_t::array: 16330{ 16331// step 1: write control byte and the array size 16332const auto N = j. m_data . m_value . array -> size (); 16333if ( N <= 15 ) 16334{ 16335// fixarray 16336write_number ( static_cast < std:: uint8_t > ( 0x90 | N )); 16337} 16338else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16339{ 16340// array 16 16341oa -> write_character ( to_char_type ( 0xDC )); 16342write_number ( static_cast < std:: uint16_t > ( N )); 16343} 16344else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16345{ 16346// array 32 16347oa -> write_character ( to_char_type ( 0xDD )); 16348write_number ( static_cast < std:: uint32_t > ( N )); 16349} 16350 16351// step 2: write each element 16352for ( const auto & el : * j. m_data . m_value . array ) 16353{ 16354write_msgpack (el); 16355} 16356break ; 16357} 16358 16359case value_t::binary: 16360{ 16361// step 0: determine if the binary type has a set subtype to 16362// determine whether to use the ext or fixext types 16363const bool use_ext = j. m_data . m_value . binary -> has_subtype (); 16364 16365// step 1: write control byte and the byte string length 16366const auto N = j. m_data . m_value . binary -> size (); 16367if ( N <= (std:: numeric_limits < std:: uint8_t > ::max)()) 16368{ 16369std:: uint8_t output_type{}; 16370bool fixed = true; 16371if (use_ext) 16372{ 16373switch ( N ) 16374{ 16375case 1 : 16376output_type = 0xD4 ; // fixext 1 16377break ; 16378case 2 : 16379output_type = 0xD5 ; // fixext 2 16380break ; 16381case 4 : 16382output_type = 0xD6 ; // fixext 4 16383break ; 16384case 8 : 16385output_type = 0xD7 ; // fixext 8 16386break ; 16387case 16 : 16388output_type = 0xD8 ; // fixext 16 16389break ; 16390default : 16391output_type = 0xC7 ; // ext 8 16392fixed = false; 16393break ; 16394} 16395 16396} 16397else 16398{ 16399output_type = 0xC4 ; // bin 8 16400fixed = false; 16401} 16402 16403oa -> write_character ( to_char_type (output_type)); 16404if (!fixed) 16405{ 16406write_number ( static_cast < std:: uint8_t > ( N )); 16407} 16408} 16409else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16410{ 16411const std:: uint8_t output_type = use_ext 16412? 0xC8 // ext 16 16413: 0xC5 ; // bin 16 16414 16415oa -> write_character ( to_char_type (output_type)); 16416write_number ( static_cast < std:: uint16_t > ( N )); 16417} 16418else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16419{ 16420const std:: uint8_t output_type = use_ext 16421? 0xC9 // ext 32 16422: 0xC6 ; // bin 32 16423 16424oa -> write_character ( to_char_type (output_type)); 16425write_number ( static_cast < std:: uint32_t > ( N )); 16426} 16427 16428// step 1.5: if this is an ext type, write the subtype 16429if (use_ext) 16430{ 16431write_number ( static_cast < std:: int8_t > (j. m_data . m_value . binary -> subtype ())); 16432} 16433 16434// step 2: write the byte string 16435oa -> write_characters ( 16436reinterpret_cast < const CharType *> (j. m_data . m_value . binary -> data ()), 16437N ); 16438 16439break ; 16440} 16441 16442case value_t::object: 16443{ 16444// step 1: write control byte and the object size 16445const auto N = j. m_data . m_value . object -> size (); 16446if ( N <= 15 ) 16447{ 16448// fixmap 16449write_number ( static_cast < std:: uint8_t > ( 0x80 | ( N & 0xF ))); 16450} 16451else if ( N <= (std:: numeric_limits < std:: uint16_t > ::max)()) 16452{ 16453// map 16 16454oa -> write_character ( to_char_type ( 0xDE )); 16455write_number ( static_cast < std:: uint16_t > ( N )); 16456} 16457else if ( N <= (std:: numeric_limits < std:: uint32_t > ::max)()) 16458{ 16459// map 32 16460oa -> write_character ( to_char_type ( 0xDF )); 16461write_number ( static_cast < std:: uint32_t > ( N )); 16462} 16463 16464// step 2: write each element 16465for ( const auto & el : * j. m_data . m_value . object ) 16466{ 16467write_msgpack (el. first ); 16468write_msgpack (el. second ); 16469} 16470break ; 16471} 16472 16473case value_t::discarded: 16474default : 16475break ; 16476} 16477} 16478 16479/*! 16480@param[in] j JSON value to serialize 16481@param[in] use_count whether to use '#' prefixes (optimized format) 16482@param[in] use_type whether to use '$' prefixes (optimized format) 16483@param[in] add_prefix whether prefixes need to be used for this value 16484@param[in] use_bjdata whether write in BJData format, default is false 16485@param[in] bjdata_version which BJData version to use, default is draft2 16486*/ 16487void write_ubjson ( const BasicJsonType & j, const bool use_count, 16488const bool use_type, const bool add_prefix = true, 16489const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2) 16490{ 16491const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3; 16492 16493switch (j. type ()) 16494{ 16495case value_t::null: 16496{ 16497if (add_prefix) 16498{ 16499oa -> write_character ( to_char_type ( 'Z' )); 16500} 16501break ; 16502} 16503 16504case value_t::boolean: 16505{ 16506if (add_prefix) 16507{ 16508oa -> write_character (j. m_data . m_value . boolean 16509? to_char_type ( 'T' ) 16510: to_char_type ( 'F' )); 16511} 16512break ; 16513} 16514 16515case value_t::number_integer: 16516{ 16517write_number_with_ubjson_prefix (j. m_data . m_value . number_integer , add_prefix, use_bjdata); 16518break ; 16519} 16520 16521case value_t::number_unsigned: 16522{ 16523write_number_with_ubjson_prefix (j. m_data . m_value . number_unsigned , add_prefix, use_bjdata); 16524break ; 16525} 16526 16527case value_t::number_float: 16528{ 16529write_number_with_ubjson_prefix (j. m_data . m_value . number_float , add_prefix, use_bjdata); 16530break ; 16531} 16532 16533case value_t::string: 16534{ 16535if (add_prefix) 16536{ 16537oa -> write_character ( to_char_type ( 'S' )); 16538} 16539write_number_with_ubjson_prefix (j. m_data . m_value . string -> size (), true, use_bjdata); 16540oa -> write_characters ( 16541reinterpret_cast < const CharType *> (j. m_data . m_value . string -> c_str ()), 16542j. m_data . m_value . string -> size ()); 16543break ; 16544} 16545 16546case value_t::array: 16547{ 16548if (add_prefix) 16549{ 16550oa -> write_character ( to_char_type ( '[' )); 16551} 16552 16553bool prefix_required = true; 16554if (use_type && !j. m_data . m_value . array -> empty ()) 16555{ 16556JSON_ASSERT (use_count); 16557const CharType first_prefix = ubjson_prefix (j. front (), use_bjdata); 16558const bool same_prefix = std:: all_of (j. begin () + 1 , j. end (), 16559[this, first_prefix, use_bjdata]( const BasicJsonType & v) 16560{ 16561return ubjson_prefix (v, use_bjdata) == first_prefix; 16562}); 16563 16564std:: vector < CharType > bjdx = { '[' , '{' , 'S' , 'H' , 'T' , 'F' , 'N' , 'Z' }; // excluded markers in bjdata optimized type 16565 16566if (same_prefix && !(use_bjdata && std:: find (bjdx. begin (), bjdx. end (), first_prefix) != bjdx. end ())) 16567{ 16568prefix_required = false; 16569oa -> write_character ( to_char_type ( '$' )); 16570oa -> write_character (first_prefix); 16571} 16572} 16573 16574if (use_count) 16575{ 16576oa -> write_character ( to_char_type ( '#' )); 16577write_number_with_ubjson_prefix (j. m_data . m_value . array -> size (), true, use_bjdata); 16578} 16579 16580for ( const auto & el : * j. m_data . m_value . array ) 16581{ 16582write_ubjson (el, use_count, use_type, prefix_required, use_bjdata, bjdata_version); 16583} 16584 16585if (!use_count) 16586{ 16587oa -> write_character ( to_char_type ( ']' )); 16588} 16589 16590break ; 16591} 16592 16593case value_t::binary: 16594{ 16595if (add_prefix) 16596{ 16597oa -> write_character ( to_char_type ( '[' )); 16598} 16599 16600if (use_type && (bjdata_draft3 || !j. m_data . m_value . binary -> empty ())) 16601{ 16602JSON_ASSERT (use_count); 16603oa -> write_character ( to_char_type ( '$' )); 16604oa -> write_character (bjdata_draft3 ? 'B' : 'U' ); 16605} 16606 16607if (use_count) 16608{ 16609oa -> write_character ( to_char_type ( '#' )); 16610write_number_with_ubjson_prefix (j. m_data . m_value . binary -> size (), true, use_bjdata); 16611} 16612 16613if (use_type) 16614{ 16615oa -> write_characters ( 16616reinterpret_cast < const CharType *> (j. m_data . m_value . binary -> data ()), 16617j. m_data . m_value . binary -> size ()); 16618} 16619else 16620{ 16621for ( size_t i = 0 ; i < j. m_data . m_value . binary -> size (); ++ i) 16622{ 16623oa -> write_character ( to_char_type (bjdata_draft3 ? 'B' : 'U' )); 16624oa -> write_character (j. m_data . m_value . binary -> data ()[i]); 16625} 16626} 16627 16628if (!use_count) 16629{ 16630oa -> write_character ( to_char_type ( ']' )); 16631} 16632 16633break ; 16634} 16635 16636case value_t::object: 16637{ 16638if (use_bjdata && j. m_data . m_value . object -> size () == 3 && j. m_data . m_value . object -> find ( "_ArrayType_" ) != j. m_data . m_value . object -> end () && j. m_data . m_value . object -> find ( "_ArraySize_" ) != j. m_data . m_value . object -> end () && j. m_data . m_value . object -> find ( "_ArrayData_" ) != j. m_data . m_value . object -> end ()) 16639{ 16640if (! write_bjdata_ndarray ( * j. m_data . m_value . object , use_count, use_type, bjdata_version)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) 16641{ 16642break ; 16643} 16644} 16645 16646if (add_prefix) 16647{ 16648oa -> write_character ( to_char_type ( '{' )); 16649} 16650 16651bool prefix_required = true; 16652if (use_type && !j. m_data . m_value . object -> empty ()) 16653{ 16654JSON_ASSERT (use_count); 16655const CharType first_prefix = ubjson_prefix (j. front (), use_bjdata); 16656const bool same_prefix = std:: all_of (j. begin (), j. end (), 16657[this, first_prefix, use_bjdata]( const BasicJsonType & v) 16658{ 16659return ubjson_prefix (v, use_bjdata) == first_prefix; 16660}); 16661 16662std:: vector < CharType > bjdx = { '[' , '{' , 'S' , 'H' , 'T' , 'F' , 'N' , 'Z' }; // excluded markers in bjdata optimized type 16663 16664if (same_prefix && !(use_bjdata && std:: find (bjdx. begin (), bjdx. end (), first_prefix) != bjdx. end ())) 16665{ 16666prefix_required = false; 16667oa -> write_character ( to_char_type ( '$' )); 16668oa -> write_character (first_prefix); 16669} 16670} 16671 16672if (use_count) 16673{ 16674oa -> write_character ( to_char_type ( '#' )); 16675write_number_with_ubjson_prefix (j. m_data . m_value . object -> size (), true, use_bjdata); 16676} 16677 16678for ( const auto & el : * j. m_data . m_value . object ) 16679{ 16680write_number_with_ubjson_prefix (el. first . size (), true, use_bjdata); 16681oa -> write_characters ( 16682reinterpret_cast < const CharType *> (el. first . c_str ()), 16683el. first . size ()); 16684write_ubjson (el. second , use_count, use_type, prefix_required, use_bjdata, bjdata_version); 16685} 16686 16687if (!use_count) 16688{ 16689oa -> write_character ( to_char_type ( '}' )); 16690} 16691 16692break ; 16693} 16694 16695case value_t::discarded: 16696default : 16697break ; 16698} 16699} 16700 16701private : 16702////////// 16703// BSON // 16704////////// 16705 16706/*! 16707@return The size of a BSON document entry header, including the id marker 16708and the entry name size (and its null-terminator). 16709*/ 16710static std:: size_t calc_bson_entry_header_size ( const string_t & name, const BasicJsonType & j) 16711{ 16712const auto it = name. find ( static_cast < typename string_t:: value_type > ( 0 )); 16713if ( JSON_HEDLEY_UNLIKELY (it != BasicJsonType ::string_t::npos)) 16714{ 16715JSON_THROW (out_of_range:: create ( 409 , concat ( "BSON key cannot contain code point U+0000 (at byte " , std:: to_string (it), ")" ), & j)); 16716static_cast < void > (j); 16717} 16718 16719return /*id*/ 1ul + name. size () + /*zero-terminator*/ 1u ; 16720} 16721 16722/*! 16723@brief Writes the given @a element_type and @a name to the output adapter 16724*/ 16725void write_bson_entry_header ( const string_t & name, 16726const std:: uint8_t element_type) 16727{ 16728oa -> write_character ( to_char_type (element_type)); // boolean 16729oa -> write_characters ( 16730reinterpret_cast < const CharType *> (name. c_str ()), 16731name. size () + 1u ); 16732} 16733 16734/*! 16735@brief Writes a BSON element with key @a name and boolean value @a value 16736*/ 16737void write_bson_boolean ( const string_t & name, 16738const bool value) 16739{ 16740write_bson_entry_header (name, 0x08 ); 16741oa -> write_character (value ? to_char_type ( 0x01 ) : to_char_type ( 0x00 )); 16742} 16743 16744/*! 16745@brief Writes a BSON element with key @a name and double value @a value 16746*/ 16747void write_bson_double ( const string_t & name, 16748const double value) 16749{ 16750write_bson_entry_header (name, 0x01 ); 16751write_number < double > (value, true); 16752} 16753 16754/*! 16755@return The size of the BSON-encoded string in @a value 16756*/ 16757static std:: size_t calc_bson_string_size ( const string_t & value) 16758{ 16759return sizeof (std:: int32_t ) + value. size () + 1ul ; 16760} 16761 16762/*! 16763@brief Writes a BSON element with key @a name and string value @a value 16764*/ 16765void write_bson_string ( const string_t & name, 16766const string_t & value) 16767{ 16768write_bson_entry_header (name, 0x02 ); 16769 16770write_number < std:: int32_t > ( static_cast < std:: int32_t > (value. size () + 1ul ), true); 16771oa -> write_characters ( 16772reinterpret_cast < const CharType *> (value. c_str ()), 16773value. size () + 1 ); 16774} 16775 16776/*! 16777@brief Writes a BSON element with key @a name and null value 16778*/ 16779void write_bson_null ( const string_t & name) 16780{ 16781write_bson_entry_header (name, 0x0A ); 16782} 16783 16784/*! 16785@return The size of the BSON-encoded integer @a value 16786*/ 16787static std:: size_t calc_bson_integer_size ( const std:: int64_t value) 16788{ 16789return (std:: numeric_limits < std:: int32_t > ::min)() <= value && value <= (std:: numeric_limits < std:: int32_t > ::max)() 16790? sizeof (std:: int32_t ) 16791: sizeof (std:: int64_t ); 16792} 16793 16794/*! 16795@brief Writes a BSON element with key @a name and integer @a value 16796*/ 16797void write_bson_integer ( const string_t & name, 16798const std:: int64_t value) 16799{ 16800if ((std:: numeric_limits < std:: int32_t > ::min)() <= value && value <= (std:: numeric_limits < std:: int32_t > ::max)()) 16801{ 16802write_bson_entry_header (name, 0x10 ); // int32 16803write_number < std:: int32_t > ( static_cast < std:: int32_t > (value), true); 16804} 16805else 16806{ 16807write_bson_entry_header (name, 0x12 ); // int64 16808write_number < std:: int64_t > ( static_cast < std:: int64_t > (value), true); 16809} 16810} 16811 16812/*! 16813@return The size of the BSON-encoded unsigned integer in @a j 16814*/ 16815static constexpr std:: size_t calc_bson_unsigned_size ( const std:: uint64_t value) noexcept 16816{ 16817return (value <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int32_t > ::max)())) 16818? sizeof (std:: int32_t ) 16819: sizeof (std:: int64_t ); 16820} 16821 16822/*! 16823@brief Writes a BSON element with key @a name and unsigned @a value 16824*/ 16825void write_bson_unsigned ( const string_t & name, 16826const BasicJsonType & j) 16827{ 16828if (j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int32_t > ::max)())) 16829{ 16830write_bson_entry_header (name, 0x10 /* int32 */ ); 16831write_number < std:: int32_t > ( static_cast < std:: int32_t > (j. m_data . m_value . number_unsigned ), true); 16832} 16833else if (j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int64_t > ::max)())) 16834{ 16835write_bson_entry_header (name, 0x12 /* int64 */ ); 16836write_number < std:: int64_t > ( static_cast < std:: int64_t > (j. m_data . m_value . number_unsigned ), true); 16837} 16838else 16839{ 16840write_bson_entry_header (name, 0x11 /* uint64 */ ); 16841write_number < std:: uint64_t > ( static_cast < std:: uint64_t > (j. m_data . m_value . number_unsigned ), true); 16842} 16843} 16844 16845/*! 16846@brief Writes a BSON element with key @a name and object @a value 16847*/ 16848void write_bson_object_entry ( const string_t & name, 16849const typename BasicJsonType :: object_t & value) 16850{ 16851write_bson_entry_header (name, 0x03 ); // object 16852write_bson_object (value); 16853} 16854 16855/*! 16856@return The size of the BSON-encoded array @a value 16857*/ 16858static std:: size_t calc_bson_array_size ( const typename BasicJsonType :: array_t & value) 16859{ 16860std:: size_t array_index = 0ul ; 16861 16862const std:: size_t embedded_document_size = std:: accumulate (std:: begin (value), std:: end (value), static_cast < std:: size_t > ( 0 ), [ & array_index](std:: size_t result, const typename BasicJsonType ::array_t:: value_type & el) 16863{ 16864return result + calc_bson_element_size (std:: to_string (array_index ++ ), el); 16865}); 16866 16867return sizeof (std:: int32_t ) + embedded_document_size + 1ul ; 16868} 16869 16870/*! 16871@return The size of the BSON-encoded binary array @a value 16872*/ 16873static std:: size_t calc_bson_binary_size ( const typename BasicJsonType :: binary_t & value) 16874{ 16875return sizeof (std:: int32_t ) + value. size () + 1ul ; 16876} 16877 16878/*! 16879@brief Writes a BSON element with key @a name and array @a value 16880*/ 16881void write_bson_array ( const string_t & name, 16882const typename BasicJsonType :: array_t & value) 16883{ 16884write_bson_entry_header (name, 0x04 ); // array 16885write_number < std:: int32_t > ( static_cast < std:: int32_t > ( calc_bson_array_size (value)), true); 16886 16887std:: size_t array_index = 0ul ; 16888 16889for ( const auto & el : value) 16890{ 16891write_bson_element (std:: to_string (array_index ++ ), el); 16892} 16893 16894oa -> write_character ( to_char_type ( 0x00 )); 16895} 16896 16897/*! 16898@brief Writes a BSON element with key @a name and binary value @a value 16899*/ 16900void write_bson_binary ( const string_t & name, 16901const binary_t & value) 16902{ 16903write_bson_entry_header (name, 0x05 ); 16904 16905write_number < std:: int32_t > ( static_cast < std:: int32_t > (value. size ()), true); 16906write_number (value. has_subtype () ? static_cast < std:: uint8_t > (value. subtype ()) : static_cast < std:: uint8_t > ( 0x00 )); 16907 16908oa -> write_characters ( reinterpret_cast < const CharType *> (value. data ()), value. size ()); 16909} 16910 16911/*! 16912@brief Calculates the size necessary to serialize the JSON value @a j with its @a name 16913@return The calculated size for the BSON document entry for @a j with the given @a name. 16914*/ 16915static std:: size_t calc_bson_element_size ( const string_t & name, 16916const BasicJsonType & j) 16917{ 16918const auto header_size = calc_bson_entry_header_size (name, j); 16919switch (j. type ()) 16920{ 16921case value_t::object: 16922return header_size + calc_bson_object_size ( * j. m_data . m_value . object ); 16923 16924case value_t::array: 16925return header_size + calc_bson_array_size ( * j. m_data . m_value . array ); 16926 16927case value_t::binary: 16928return header_size + calc_bson_binary_size ( * j. m_data . m_value . binary ); 16929 16930case value_t::boolean: 16931return header_size + 1ul ; 16932 16933case value_t::number_float: 16934return header_size + 8ul ; 16935 16936case value_t::number_integer: 16937return header_size + calc_bson_integer_size (j. m_data . m_value . number_integer ); 16938 16939case value_t::number_unsigned: 16940return header_size + calc_bson_unsigned_size (j. m_data . m_value . number_unsigned ); 16941 16942case value_t::string: 16943return header_size + calc_bson_string_size ( * j. m_data . m_value . string ); 16944 16945case value_t::null: 16946return header_size + 0ul ; 16947 16948// LCOV_EXCL_START 16949case value_t::discarded: 16950default : 16951JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16952return 0ul ; 16953// LCOV_EXCL_STOP 16954} 16955} 16956 16957/*! 16958@brief Serializes the JSON value @a j to BSON and associates it with the 16959key @a name. 16960@param name The name to associate with the JSON entity @a j within the 16961current BSON document 16962*/ 16963void write_bson_element ( const string_t & name, 16964const BasicJsonType & j) 16965{ 16966switch (j. type ()) 16967{ 16968case value_t::object: 16969return write_bson_object_entry (name, * j. m_data . m_value . object ); 16970 16971case value_t::array: 16972return write_bson_array (name, * j. m_data . m_value . array ); 16973 16974case value_t::binary: 16975return write_bson_binary (name, * j. m_data . m_value . binary ); 16976 16977case value_t::boolean: 16978return write_bson_boolean (name, j. m_data . m_value . boolean ); 16979 16980case value_t::number_float: 16981return write_bson_double (name, j. m_data . m_value . number_float ); 16982 16983case value_t::number_integer: 16984return write_bson_integer (name, j. m_data . m_value . number_integer ); 16985 16986case value_t::number_unsigned: 16987return write_bson_unsigned (name, j); 16988 16989case value_t::string: 16990return write_bson_string (name, * j. m_data . m_value . string ); 16991 16992case value_t::null: 16993return write_bson_null (name); 16994 16995// LCOV_EXCL_START 16996case value_t::discarded: 16997default : 16998JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16999return ; 17000// LCOV_EXCL_STOP 17001} 17002} 17003 17004/*! 17005@brief Calculates the size of the BSON serialization of the given 17006JSON-object @a j. 17007@param[in] value JSON value to serialize 17008@pre value.type() == value_t::object 17009*/ 17010static std:: size_t calc_bson_object_size ( const typename BasicJsonType :: object_t & value) 17011{ 17012const std:: size_t document_size = std:: accumulate (value. begin (), value. end (), static_cast < std:: size_t > ( 0 ), 17013[]( size_t result, const typename BasicJsonType ::object_t:: value_type & el) 17014{ 17015return result += calc_bson_element_size (el. first , el. second ); 17016}); 17017 17018return sizeof (std:: int32_t ) + document_size + 1ul ; 17019} 17020 17021/*! 17022@param[in] value JSON value to serialize 17023@pre value.type() == value_t::object 17024*/ 17025void write_bson_object ( const typename BasicJsonType :: object_t & value) 17026{ 17027write_number < std:: int32_t > ( static_cast < std:: int32_t > ( calc_bson_object_size (value)), true); 17028 17029for ( const auto & el : value) 17030{ 17031write_bson_element (el. first , el. second ); 17032} 17033 17034oa -> write_character ( to_char_type ( 0x00 )); 17035} 17036 17037////////// 17038// CBOR // 17039////////// 17040 17041static constexpr CharType get_cbor_float_prefix ( float /*unused*/ ) 17042{ 17043return to_char_type ( 0xFA ); // Single-Precision Float 17044} 17045 17046static constexpr CharType get_cbor_float_prefix ( double /*unused*/ ) 17047{ 17048return to_char_type ( 0xFB ); // Double-Precision Float 17049} 17050 17051///////////// 17052// MsgPack // 17053///////////// 17054 17055static constexpr CharType get_msgpack_float_prefix ( float /*unused*/ ) 17056{ 17057return to_char_type ( 0xCA ); // float 32 17058} 17059 17060static constexpr CharType get_msgpack_float_prefix ( double /*unused*/ ) 17061{ 17062return to_char_type ( 0xCB ); // float 64 17063} 17064 17065//////////// 17066// UBJSON // 17067//////////// 17068 17069// UBJSON: write number (floating point) 17070template < typename NumberType , typename std:: enable_if < 17071std:: is_floating_point < NumberType > :: value , int > :: type = 0 > 17072void write_number_with_ubjson_prefix ( const NumberType n, 17073const bool add_prefix, 17074const bool use_bjdata) 17075{ 17076if (add_prefix) 17077{ 17078oa -> write_character ( get_ubjson_float_prefix (n)); 17079} 17080write_number (n, use_bjdata); 17081} 17082 17083// UBJSON: write number (unsigned integer) 17084template < typename NumberType , typename std:: enable_if < 17085std:: is_unsigned < NumberType > :: value , int > :: type = 0 > 17086void write_number_with_ubjson_prefix ( const NumberType n, 17087const bool add_prefix, 17088const bool use_bjdata) 17089{ 17090if (n <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int8_t > ::max)())) 17091{ 17092if (add_prefix) 17093{ 17094oa -> write_character ( to_char_type ( 'i' )); // int8 17095} 17096write_number ( static_cast < std:: uint8_t > (n), use_bjdata); 17097} 17098else if (n <= (std:: numeric_limits < std:: uint8_t > ::max)()) 17099{ 17100if (add_prefix) 17101{ 17102oa -> write_character ( to_char_type ( 'U' )); // uint8 17103} 17104write_number ( static_cast < std:: uint8_t > (n), use_bjdata); 17105} 17106else if (n <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int16_t > ::max)())) 17107{ 17108if (add_prefix) 17109{ 17110oa -> write_character ( to_char_type ( 'I' )); // int16 17111} 17112write_number ( static_cast < std:: int16_t > (n), use_bjdata); 17113} 17114else if (use_bjdata && n <= static_cast < uint64_t > ((std:: numeric_limits < uint16_t > ::max)())) 17115{ 17116if (add_prefix) 17117{ 17118oa -> write_character ( to_char_type ( 'u' )); // uint16 - bjdata only 17119} 17120write_number ( static_cast < std:: uint16_t > (n), use_bjdata); 17121} 17122else if (n <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int32_t > ::max)())) 17123{ 17124if (add_prefix) 17125{ 17126oa -> write_character ( to_char_type ( 'l' )); // int32 17127} 17128write_number ( static_cast < std:: int32_t > (n), use_bjdata); 17129} 17130else if (use_bjdata && n <= static_cast < uint64_t > ((std:: numeric_limits < uint32_t > ::max)())) 17131{ 17132if (add_prefix) 17133{ 17134oa -> write_character ( to_char_type ( 'm' )); // uint32 - bjdata only 17135} 17136write_number ( static_cast < std:: uint32_t > (n), use_bjdata); 17137} 17138else if (n <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int64_t > ::max)())) 17139{ 17140if (add_prefix) 17141{ 17142oa -> write_character ( to_char_type ( 'L' )); // int64 17143} 17144write_number ( static_cast < std:: int64_t > (n), use_bjdata); 17145} 17146else if (use_bjdata && n <= (std:: numeric_limits < uint64_t > ::max)()) 17147{ 17148if (add_prefix) 17149{ 17150oa -> write_character ( to_char_type ( 'M' )); // uint64 - bjdata only 17151} 17152write_number ( static_cast < std:: uint64_t > (n), use_bjdata); 17153} 17154else 17155{ 17156if (add_prefix) 17157{ 17158oa -> write_character ( to_char_type ( 'H' )); // high-precision number 17159} 17160 17161const auto number = BasicJsonType (n). dump (); 17162write_number_with_ubjson_prefix (number. size (), true, use_bjdata); 17163for (std:: size_t i = 0 ; i < number. size (); ++ i) 17164{ 17165oa -> write_character ( to_char_type ( static_cast < std:: uint8_t > (number[i]))); 17166} 17167} 17168} 17169 17170// UBJSON: write number (signed integer) 17171template < typename NumberType , typename std:: enable_if < 17172std:: is_signed < NumberType > ::value && 17173!std:: is_floating_point < NumberType > ::value, int > :: type = 0 > 17174void write_number_with_ubjson_prefix ( const NumberType n, 17175const bool add_prefix, 17176const bool use_bjdata) 17177{ 17178if ((std:: numeric_limits < std:: int8_t > ::min)() <= n && n <= (std:: numeric_limits < std:: int8_t > ::max)()) 17179{ 17180if (add_prefix) 17181{ 17182oa -> write_character ( to_char_type ( 'i' )); // int8 17183} 17184write_number ( static_cast < std:: int8_t > (n), use_bjdata); 17185} 17186else if ( static_cast < std:: int64_t > ((std:: numeric_limits < std:: uint8_t > ::min)()) <= n && n <= static_cast < std:: int64_t > ((std:: numeric_limits < std:: uint8_t > ::max)())) 17187{ 17188if (add_prefix) 17189{ 17190oa -> write_character ( to_char_type ( 'U' )); // uint8 17191} 17192write_number ( static_cast < std:: uint8_t > (n), use_bjdata); 17193} 17194else if ((std:: numeric_limits < std:: int16_t > ::min)() <= n && n <= (std:: numeric_limits < std:: int16_t > ::max)()) 17195{ 17196if (add_prefix) 17197{ 17198oa -> write_character ( to_char_type ( 'I' )); // int16 17199} 17200write_number ( static_cast < std:: int16_t > (n), use_bjdata); 17201} 17202else if (use_bjdata && ( static_cast < std:: int64_t > ((std:: numeric_limits < std:: uint16_t > ::min)()) <= n && n <= static_cast < std:: int64_t > ((std:: numeric_limits < std:: uint16_t > ::max)()))) 17203{ 17204if (add_prefix) 17205{ 17206oa -> write_character ( to_char_type ( 'u' )); // uint16 - bjdata only 17207} 17208write_number ( static_cast < uint16_t > (n), use_bjdata); 17209} 17210else if ((std:: numeric_limits < std:: int32_t > ::min)() <= n && n <= (std:: numeric_limits < std:: int32_t > ::max)()) 17211{ 17212if (add_prefix) 17213{ 17214oa -> write_character ( to_char_type ( 'l' )); // int32 17215} 17216write_number ( static_cast < std:: int32_t > (n), use_bjdata); 17217} 17218else if (use_bjdata && ( static_cast < std:: int64_t > ((std:: numeric_limits < std:: uint32_t > ::min)()) <= n && n <= static_cast < std:: int64_t > ((std:: numeric_limits < std:: uint32_t > ::max)()))) 17219{ 17220if (add_prefix) 17221{ 17222oa -> write_character ( to_char_type ( 'm' )); // uint32 - bjdata only 17223} 17224write_number ( static_cast < uint32_t > (n), use_bjdata); 17225} 17226else if ((std:: numeric_limits < std:: int64_t > ::min)() <= n && n <= (std:: numeric_limits < std:: int64_t > ::max)()) 17227{ 17228if (add_prefix) 17229{ 17230oa -> write_character ( to_char_type ( 'L' )); // int64 17231} 17232write_number ( static_cast < std:: int64_t > (n), use_bjdata); 17233} 17234// LCOV_EXCL_START 17235else 17236{ 17237if (add_prefix) 17238{ 17239oa -> write_character ( to_char_type ( 'H' )); // high-precision number 17240} 17241 17242const auto number = BasicJsonType (n). dump (); 17243write_number_with_ubjson_prefix (number. size (), true, use_bjdata); 17244for (std:: size_t i = 0 ; i < number. size (); ++ i) 17245{ 17246oa -> write_character ( to_char_type ( static_cast < std:: uint8_t > (number[i]))); 17247} 17248} 17249// LCOV_EXCL_STOP 17250} 17251 17252/*! 17253@brief determine the type prefix of container values 17254*/ 17255CharType ubjson_prefix ( const BasicJsonType & j, const bool use_bjdata) const noexcept 17256{ 17257switch (j. type ()) 17258{ 17259case value_t::null: 17260return 'Z' ; 17261 17262case value_t::boolean: 17263return j. m_data . m_value . boolean ? 'T' : 'F' ; 17264 17265case value_t::number_integer: 17266{ 17267if ((std:: numeric_limits < std:: int8_t > ::min)() <= j. m_data . m_value . number_integer && j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int8_t > ::max)()) 17268{ 17269return 'i' ; 17270} 17271if ((std:: numeric_limits < std:: uint8_t > ::min)() <= j. m_data . m_value . number_integer && j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: uint8_t > ::max)()) 17272{ 17273return 'U' ; 17274} 17275if ((std:: numeric_limits < std:: int16_t > ::min)() <= j. m_data . m_value . number_integer && j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int16_t > ::max)()) 17276{ 17277return 'I' ; 17278} 17279if (use_bjdata && ((std:: numeric_limits < std:: uint16_t > ::min)() <= j. m_data . m_value . number_integer && j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: uint16_t > ::max)())) 17280{ 17281return 'u' ; 17282} 17283if ((std:: numeric_limits < std:: int32_t > ::min)() <= j. m_data . m_value . number_integer && j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int32_t > ::max)()) 17284{ 17285return 'l' ; 17286} 17287if (use_bjdata && ((std:: numeric_limits < std:: uint32_t > ::min)() <= j. m_data . m_value . number_integer && j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: uint32_t > ::max)())) 17288{ 17289return 'm' ; 17290} 17291if ((std:: numeric_limits < std:: int64_t > ::min)() <= j. m_data . m_value . number_integer && j. m_data . m_value . number_integer <= (std:: numeric_limits < std:: int64_t > ::max)()) 17292{ 17293return 'L' ; 17294} 17295// anything else is treated as high-precision number 17296return 'H' ; // LCOV_EXCL_LINE 17297} 17298 17299case value_t::number_unsigned: 17300{ 17301if (j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int8_t > ::max)())) 17302{ 17303return 'i' ; 17304} 17305if (j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: uint8_t > ::max)())) 17306{ 17307return 'U' ; 17308} 17309if (j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int16_t > ::max)())) 17310{ 17311return 'I' ; 17312} 17313if (use_bjdata && j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: uint16_t > ::max)())) 17314{ 17315return 'u' ; 17316} 17317if (j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int32_t > ::max)())) 17318{ 17319return 'l' ; 17320} 17321if (use_bjdata && j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: uint32_t > ::max)())) 17322{ 17323return 'm' ; 17324} 17325if (j. m_data . m_value . number_unsigned <= static_cast < std:: uint64_t > ((std:: numeric_limits < std:: int64_t > ::max)())) 17326{ 17327return 'L' ; 17328} 17329if (use_bjdata && j. m_data . m_value . number_unsigned <= (std:: numeric_limits < std:: uint64_t > ::max)()) 17330{ 17331return 'M' ; 17332} 17333// anything else is treated as high-precision number 17334return 'H' ; // LCOV_EXCL_LINE 17335} 17336 17337case value_t::number_float: 17338return get_ubjson_float_prefix (j. m_data . m_value . number_float ); 17339 17340case value_t::string: 17341return 'S' ; 17342 17343case value_t::array: // fallthrough 17344case value_t::binary: 17345return '[' ; 17346 17347case value_t::object: 17348return '{' ; 17349 17350case value_t::discarded: 17351default : // discarded values 17352return 'N' ; 17353} 17354} 17355 17356static constexpr CharType get_ubjson_float_prefix ( float /*unused*/ ) 17357{ 17358return 'd' ; // float 32 17359} 17360 17361static constexpr CharType get_ubjson_float_prefix ( double /*unused*/ ) 17362{ 17363return 'D' ; // float 64 17364} 17365 17366/*! 17367@return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid 17368*/ 17369bool write_bjdata_ndarray ( const typename BasicJsonType :: object_t & value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version) 17370{ 17371std:: map < string_t , CharType > bjdtype = {{ "uint8" , 'U' }, { "int8" , 'i' }, { "uint16" , 'u' }, { "int16" , 'I' }, 17372{ "uint32" , 'm' }, { "int32" , 'l' }, { "uint64" , 'M' }, { "int64" , 'L' }, { "single" , 'd' }, { "double" , 'D' }, 17373{ "char" , 'C' }, { "byte" , 'B' } 17374}; 17375 17376string_t key = "_ArrayType_" ; 17377auto it = bjdtype. find ( static_cast < string_t > (value. at (key))); 17378if (it == bjdtype. end ()) 17379{ 17380return true; 17381} 17382CharType dtype = it -> second ; 17383 17384key = "_ArraySize_" ; 17385std:: size_t len = (value. at (key). empty () ? 0 : 1 ); 17386for ( const auto & el : value. at (key)) 17387{ 17388len *= static_cast < std:: size_t > (el. m_data . m_value . number_unsigned ); 17389} 17390 17391key = "_ArrayData_" ; 17392if (value. at (key). size () != len) 17393{ 17394return true; 17395} 17396 17397oa -> write_character ( '[' ); 17398oa -> write_character ( '$' ); 17399oa -> write_character (dtype); 17400oa -> write_character ( '#' ); 17401 17402key = "_ArraySize_" ; 17403write_ubjson (value. at (key), use_count, use_type, true, true, bjdata_version); 17404 17405key = "_ArrayData_" ; 17406if (dtype == 'U' || dtype == 'C' || dtype == 'B' ) 17407{ 17408for ( const auto & el : value. at (key)) 17409{ 17410write_number ( static_cast < std:: uint8_t > (el. m_data . m_value . number_unsigned ), true); 17411} 17412} 17413else if (dtype == 'i' ) 17414{ 17415for ( const auto & el : value. at (key)) 17416{ 17417write_number ( static_cast < std:: int8_t > (el. m_data . m_value . number_integer ), true); 17418} 17419} 17420else if (dtype == 'u' ) 17421{ 17422for ( const auto & el : value. at (key)) 17423{ 17424write_number ( static_cast < std:: uint16_t > (el. m_data . m_value . number_unsigned ), true); 17425} 17426} 17427else if (dtype == 'I' ) 17428{ 17429for ( const auto & el : value. at (key)) 17430{ 17431write_number ( static_cast < std:: int16_t > (el. m_data . m_value . number_integer ), true); 17432} 17433} 17434else if (dtype == 'm' ) 17435{ 17436for ( const auto & el : value. at (key)) 17437{ 17438write_number ( static_cast < std:: uint32_t > (el. m_data . m_value . number_unsigned ), true); 17439} 17440} 17441else if (dtype == 'l' ) 17442{ 17443for ( const auto & el : value. at (key)) 17444{ 17445write_number ( static_cast < std:: int32_t > (el. m_data . m_value . number_integer ), true); 17446} 17447} 17448else if (dtype == 'M' ) 17449{ 17450for ( const auto & el : value. at (key)) 17451{ 17452write_number ( static_cast < std:: uint64_t > (el. m_data . m_value . number_unsigned ), true); 17453} 17454} 17455else if (dtype == 'L' ) 17456{ 17457for ( const auto & el : value. at (key)) 17458{ 17459write_number ( static_cast < std:: int64_t > (el. m_data . m_value . number_integer ), true); 17460} 17461} 17462else if (dtype == 'd' ) 17463{ 17464for ( const auto & el : value. at (key)) 17465{ 17466write_number ( static_cast < float > (el. m_data . m_value . number_float ), true); 17467} 17468} 17469else if (dtype == 'D' ) 17470{ 17471for ( const auto & el : value. at (key)) 17472{ 17473write_number ( static_cast < double > (el. m_data . m_value . number_float ), true); 17474} 17475} 17476return false; 17477} 17478 17479/////////////////////// 17480// Utility functions // 17481/////////////////////// 17482 17483/* 17484@brief write a number to output input 17485@param[in] n number of type @a NumberType 17486@param[in] OutputIsLittleEndian Set to true if output data is 17487required to be little endian 17488@tparam NumberType the type of the number 17489 17490@note This function needs to respect the system's endianness, because bytes 17491in CBOR, MessagePack, and UBJSON are stored in network order (big 17492endian) and therefore need reordering on little endian systems. 17493On the other hand, BSON and BJData use little endian and should reorder 17494on big endian systems. 17495*/ 17496template < typename NumberType > 17497void write_number ( const NumberType n, const bool OutputIsLittleEndian = false) 17498{ 17499// step 1: write number to array of length NumberType 17500std:: array < CharType , sizeof (NumberType) > vec{}; 17501std:: memcpy (vec. data (), & n, sizeof (NumberType)); 17502 17503// step 2: write array to output (with possible reordering) 17504if (is_little_endian != OutputIsLittleEndian) 17505{ 17506// reverse byte order prior to conversion if necessary 17507std:: reverse (vec. begin (), vec. end ()); 17508} 17509 17510oa -> write_characters (vec. data (), sizeof (NumberType)); 17511} 17512 17513void write_compact_float ( const number_float_t n, detail:: input_format_t format) 17514{ 17515#ifdef __GNUC__ 17516#pragma GCC diagnostic push 17517#pragma GCC diagnostic ignored "-Wfloat-equal" 17518#endif 17519if ( static_cast < double > (n) >= static_cast < double > (std:: numeric_limits < float > ::lowest()) && 17520static_cast < double > (n) <= static_cast < double > ((std:: numeric_limits < float > ::max)()) && 17521static_cast < double > ( static_cast < float > (n)) == static_cast < double > (n)) 17522{ 17523oa -> write_character (format == detail::input_format_t::cbor 17524? get_cbor_float_prefix ( static_cast < float > (n)) 17525: get_msgpack_float_prefix ( static_cast < float > (n))); 17526write_number ( static_cast < float > (n)); 17527} 17528else 17529{ 17530oa -> write_character (format == detail::input_format_t::cbor 17531? get_cbor_float_prefix (n) 17532: get_msgpack_float_prefix (n)); 17533write_number (n); 17534} 17535#ifdef __GNUC__ 17536#pragma GCC diagnostic pop 17537#endif 17538} 17539 17540public : 17541// The following to_char_type functions are implement the conversion 17542// between uint8_t and CharType. In case CharType is not unsigned, 17543// such a conversion is required to allow values greater than 128. 17544// See <https://github.com/nlohmann/json/issues/1286> for a discussion. 17545template < typename C = CharType , 17546enable_if_t < std:: is_signed < C > ::value && std:: is_signed < char > ::value > * = nullptr > 17547static constexpr CharType to_char_type (std:: uint8_t x) noexcept 17548{ 17549return * reinterpret_cast < char *> ( & x); 17550} 17551 17552template < typename C = CharType , 17553enable_if_t < std:: is_signed < C > ::value && std:: is_unsigned < char > ::value > * = nullptr > 17554static CharType to_char_type (std:: uint8_t x) noexcept 17555{ 17556static_assert( sizeof (std:: uint8_t ) == sizeof (CharType), "size of CharType must be equal to std::uint8_t" ); 17557static_assert(std:: is_trivial < CharType > ::value, "CharType must be trivial" ); 17558CharType result; 17559std:: memcpy ( & result, & x, sizeof (x)); 17560return result; 17561} 17562 17563template < typename C = CharType , 17564enable_if_t < std:: is_unsigned < C > :: value >* = nullptr > 17565static constexpr CharType to_char_type (std:: uint8_t x) noexcept 17566{ 17567return x; 17568} 17569 17570template < typename InputCharType , typename C = CharType , 17571enable_if_t < 17572std:: is_signed < C > ::value && 17573std:: is_signed < char > ::value && 17574std:: is_same < char , typename std:: remove_cv < InputCharType > :: type > ::value 17575> * = nullptr > 17576static constexpr CharType to_char_type ( InputCharType x) noexcept 17577{ 17578return x; 17579} 17580 17581private : 17582/// whether we can assume little endianness 17583const bool is_little_endian = little_endianness (); 17584 17585/// the output 17586output_adapter_t < CharType > oa = nullptr ; 17587}; 17588 17589} // namespace detail 17590NLOHMANN_JSON_NAMESPACE_END 17591 17592// #include <nlohmann/detail/output/output_adapters.hpp> 17593 17594// #include <nlohmann/detail/output/serializer.hpp> 17595// __ _____ _____ _____ 17596// __| | __| | | | JSON for Modern C++ 17597// | | |__ | | | | | | version 3.12.0 17598// |_____|_____|_____|_|___| https://github.com/nlohmann/json 17599// 17600// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de> 17601// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 17602// SPDX-License-Identifier: MIT 17603 17604 17605 17606#include <algorithm> // reverse, remove, fill, find, none_of 17607#include <array> // array 17608#include <clocale> // localeconv, lconv 17609#include <cmath> // labs, isfinite, isnan, signbit 17610#include <cstddef> // size_t, ptrdiff_t 17611#include <cstdint> // uint8_t 17612#include <cstdio> // snprintf 17613#include <limits> // numeric_limits 17614#include <string> // string, char_traits 17615#include <iomanip> // setfill, setw 17616#include <type_traits> // is_same 17617#include <utility> // move 17618 17619// #include <nlohmann/detail/conversions/to_chars.hpp> 17620// __ _____ _____ _____ 17621// __| | __| | | | JSON for Modern C++ 17622// | | |__ | | | | | | version 3.12.0 17623// |_____|_____|_____|_|___| https://github.com/nlohmann/json 17624// 17625// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/> 17626// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 17627// SPDX-License-Identifier: MIT 17628 17629 17630 17631#include <array> // array 17632#include <cmath> // signbit, isfinite 17633#include <cstdint> // intN_t, uintN_t 17634#include <cstring> // memcpy, memmove 17635#include <limits> // numeric_limits 17636#include <type_traits> // conditional 17637 17638// #include <nlohmann/detail/macro_scope.hpp> 17639 17640 17641NLOHMANN_JSON_NAMESPACE_BEGIN 17642namespace detail 17643{ 17644 17645/*! 17646@brief implements the Grisu2 algorithm for binary to decimal floating-point 17647conversion. 17648 17649This implementation is a slightly modified version of the reference 17650implementation which may be obtained from 17651http://florian.loitsch.com/publications (bench.tar.gz). 17652 17653The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. 17654 17655For a detailed description of the algorithm see: 17656 17657[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with 17658Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming 17659Language Design and Implementation, PLDI 2010 17660[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", 17661Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language 17662Design and Implementation, PLDI 1996 17663*/ 17664namespace dtoa_impl 17665{ 17666 17667template < typename Target , typename Source > 17668Target reinterpret_bits ( const Source source) 17669{ 17670static_assert( sizeof (Target) == sizeof (Source), "size mismatch" ); 17671 17672Target target; 17673std:: memcpy ( & target, & source, sizeof (Source)); 17674return target; 17675} 17676 17677struct diyfp // f * 2^e 17678{ 17679static constexpr int kPrecision = 64 ; // = q 17680 17681std:: uint64_t f = 0 ; 17682int e = 0 ; 17683 17684constexpr diyfp (std:: uint64_t f_, int e_) noexcept : f (f_), e (e_) {} 17685 17686/*! 17687@brief returns x - y 17688@pre x.e == y.e and x.f >= y.f 17689*/ 17690static diyfp sub ( const diyfp & x, const diyfp & y) noexcept 17691{ 17692JSON_ASSERT (x. e == y. e ); 17693JSON_ASSERT (x. f >= y. f ); 17694 17695return {x. f - y. f , x. e }; 17696} 17697 17698/*! 17699@brief returns x * y 17700@note The result is rounded. (Only the upper q bits are returned.) 17701*/ 17702static diyfp mul ( const diyfp & x, const diyfp & y) noexcept 17703{ 17704static_assert(kPrecision == 64 , "internal error" ); 17705 17706// Computes: 17707// f = round((x.f * y.f) / 2^q) 17708// e = x.e + y.e + q 17709 17710// Emulate the 64-bit * 64-bit multiplication: 17711// 17712// p = u * v 17713// = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) 17714// = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) 17715// = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) 17716// = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) 17717// = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) 17718// = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) 17719// = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) 17720// 17721// (Since Q might be larger than 2^32 - 1) 17722// 17723// = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) 17724// 17725// (Q_hi + H does not overflow a 64-bit int) 17726// 17727// = p_lo + 2^64 p_hi 17728 17729const std:: uint64_t u_lo = x. f & 0xFFFFFFFFu ; 17730const std:: uint64_t u_hi = x. f >> 32u ; 17731const std:: uint64_t v_lo = y. f & 0xFFFFFFFFu ; 17732const std:: uint64_t v_hi = y. f >> 32u ; 17733 17734const std:: uint64_t p0 = u_lo * v_lo; 17735const std:: uint64_t p1 = u_lo * v_hi; 17736const std:: uint64_t p2 = u_hi * v_lo; 17737const std:: uint64_t p3 = u_hi * v_hi; 17738 17739const std:: uint64_t p0_hi = p0 >> 32u ; 17740const std:: uint64_t p1_lo = p1 & 0xFFFFFFFFu ; 17741const std:: uint64_t p1_hi = p1 >> 32u ; 17742const std:: uint64_t p2_lo = p2 & 0xFFFFFFFFu ; 17743const std:: uint64_t p2_hi = p2 >> 32u ; 17744 17745std:: uint64_t Q = p0_hi + p1_lo + p2_lo; 17746 17747// The full product might now be computed as 17748// 17749// p_hi = p3 + p2_hi + p1_hi + (Q >> 32) 17750// p_lo = p0_lo + (Q << 32) 17751// 17752// But in this particular case here, the full p_lo is not required. 17753// Effectively we only need to add the highest bit in p_lo to p_hi (and 17754// Q_hi + 1 does not overflow). 17755 17756Q += std:: uint64_t { 1 } << ( 64u - 32u - 1u ); // round, ties up 17757 17758const std:: uint64_t h = p3 + p2_hi + p1_hi + ( Q >> 32u ); 17759 17760return {h, x. e + y. e + 64 }; 17761} 17762 17763/*! 17764@brief normalize x such that the significand is >= 2^(q-1) 17765@pre x.f != 0 17766*/ 17767static diyfp normalize ( diyfp x) noexcept 17768{ 17769JSON_ASSERT (x. f != 0 ); 17770 17771while ((x. f >> 63u ) == 0 ) 17772{ 17773x. f <<= 1u ; 17774x. e -- ; 17775} 17776 17777return x; 17778} 17779 17780/*! 17781@brief normalize x such that the result has the exponent E 17782@pre e >= x.e and the upper e - x.e bits of x.f must be zero. 17783*/ 17784static diyfp normalize_to ( const diyfp & x, const int target_exponent) noexcept 17785{ 17786const int delta = x. e - target_exponent; 17787 17788JSON_ASSERT (delta >= 0 ); 17789JSON_ASSERT (((x. f << delta) >> delta) == x. f ); 17790 17791return {x. f << delta, target_exponent}; 17792} 17793}; 17794 17795struct boundaries 17796{ 17797diyfp w ; 17798diyfp minus ; 17799diyfp plus ; 17800}; 17801 17802/*! 17803Compute the (normalized) diyfp representing the input number 'value' and its 17804boundaries. 17805 17806@pre value must be finite and positive 17807*/ 17808template < typename FloatType > 17809boundaries compute_boundaries ( FloatType value) 17810{ 17811JSON_ASSERT (std:: isfinite (value)); 17812JSON_ASSERT (value > 0 ); 17813 17814// Convert the IEEE representation into a diyfp. 17815// 17816// If v is denormal: 17817// value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) 17818// If v is normalized: 17819// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) 17820 17821static_assert(std:: numeric_limits < FloatType > ::is_iec559, 17822"internal error: dtoa_short requires an IEEE-754 floating-point implementation" ); 17823 17824constexpr int kPrecision = std:: numeric_limits < FloatType > ::digits; // = p (includes the hidden bit) 17825constexpr int kBias = std:: numeric_limits < FloatType > ::max_exponent - 1 + (kPrecision - 1 ); 17826constexpr int kMinExp = 1 - kBias; 17827constexpr std:: uint64_t kHiddenBit = std:: uint64_t { 1 } << (kPrecision - 1 ); // = 2^(p-1) 17828 17829using bits_type = typename std:: conditional < kPrecision == 24 , std:: uint32_t , std:: uint64_t > :: type ; 17830 17831const auto bits = static_cast < std:: uint64_t > ( reinterpret_bits < bits_type > (value)); 17832const std:: uint64_t E = bits >> (kPrecision - 1 ); 17833const std:: uint64_t F = bits & (kHiddenBit - 1 ); 17834 17835const bool is_denormal = E == 0 ; 17836const diyfp v = is_denormal 17837? diyfp ( F , kMinExp) 17838: diyfp ( F + kHiddenBit, static_cast < int > ( E ) - kBias); 17839 17840// Compute the boundaries m- and m+ of the floating-point value 17841// v = f * 2^e. 17842// 17843// Determine v- and v+, the floating-point predecessor and successor if v, 17844// respectively. 17845// 17846// v- = v - 2^e if f != 2^(p-1) or e == e_min (A) 17847// = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) 17848// 17849// v+ = v + 2^e 17850// 17851// Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ 17852// between m- and m+ round to v, regardless of how the input rounding 17853// algorithm breaks ties. 17854// 17855// ---+-------------+-------------+-------------+-------------+--- (A) 17856// v- m- v m+ v+ 17857// 17858// -----------------+------+------+-------------+-------------+--- (B) 17859// v- m- v m+ v+ 17860 17861const bool lower_boundary_is_closer = F == 0 && E > 1 ; 17862const diyfp m_plus = diyfp (( 2 * v. f ) + 1 , v. e - 1 ); 17863const diyfp m_minus = lower_boundary_is_closer 17864? diyfp (( 4 * v. f ) - 1 , v. e - 2 ) // (B) 17865: diyfp (( 2 * v. f ) - 1 , v. e - 1 ); // (A) 17866 17867// Determine the normalized w+ = m+. 17868const diyfp w_plus = diyfp:: normalize (m_plus); 17869 17870// Determine w- = m- such that e_(w-) = e_(w+). 17871const diyfp w_minus = diyfp:: normalize_to (m_minus, w_plus. e ); 17872 17873return {diyfp:: normalize (v), w_minus, w_plus}; 17874} 17875 17876// Given normalized diyfp w, Grisu needs to find a (normalized) cached 17877// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies 17878// within a certain range [alpha, gamma] (Definition 3.2 from [1]) 17879// 17880// alpha <= e = e_c + e_w + q <= gamma 17881// 17882// or 17883// 17884// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q 17885// <= f_c * f_w * 2^gamma 17886// 17887// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies 17888// 17889// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma 17890// 17891// or 17892// 17893// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) 17894// 17895// The choice of (alpha,gamma) determines the size of the table and the form of 17896// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well 17897// in practice: 17898// 17899// The idea is to cut the number c * w = f * 2^e into two parts, which can be 17900// processed independently: An integral part p1, and a fractional part p2: 17901// 17902// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e 17903// = (f div 2^-e) + (f mod 2^-e) * 2^e 17904// = p1 + p2 * 2^e 17905// 17906// The conversion of p1 into decimal form requires a series of divisions and 17907// modulos by (a power of) 10. These operations are faster for 32-bit than for 17908// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be 17909// achieved by choosing 17910// 17911// -e >= 32 or e <= -32 := gamma 17912// 17913// In order to convert the fractional part 17914// 17915// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... 17916// 17917// into decimal form, the fraction is repeatedly multiplied by 10 and the digits 17918// d[-i] are extracted in order: 17919// 17920// (10 * p2) div 2^-e = d[-1] 17921// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... 17922// 17923// The multiplication by 10 must not overflow. It is sufficient to choose 17924// 17925// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. 17926// 17927// Since p2 = f mod 2^-e < 2^-e, 17928// 17929// -e <= 60 or e >= -60 := alpha 17930 17931constexpr int kAlpha = -60 ; 17932constexpr int kGamma = -32 ; 17933 17934struct cached_power // c = f * 2^e ~= 10^k 17935{ 17936std:: uint64_t f ; 17937int e ; 17938int k ; 17939}; 17940 17941/*! 17942For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached 17943power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c 17944satisfies (Definition 3.2 from [1]) 17945 17946alpha <= e_c + e + q <= gamma. 17947*/ 17948inline cached_power get_cached_power_for_binary_exponent ( int e) 17949{ 17950// Now 17951// 17952// alpha <= e_c + e + q <= gamma (1) 17953// ==> f_c * 2^alpha <= c * 2^e * 2^q 17954// 17955// and since the c's are normalized, 2^(q-1) <= f_c, 17956// 17957// ==> 2^(q - 1 + alpha) <= c * 2^(e + q) 17958// ==> 2^(alpha - e - 1) <= c 17959// 17960// If c were an exact power of ten, i.e. c = 10^k, one may determine k as 17961// 17962// k = ceil( log_10( 2^(alpha - e - 1) ) ) 17963// = ceil( (alpha - e - 1) * log_10(2) ) 17964// 17965// From the paper: 17966// "In theory the result of the procedure could be wrong since c is rounded, 17967// and the computation itself is approximated [...]. In practice, however, 17968// this simple function is sufficient." 17969// 17970// For IEEE double precision floating-point numbers converted into 17971// normalized diyfp's w = f * 2^e, with q = 64, 17972// 17973// e >= -1022 (min IEEE exponent) 17974// -52 (p - 1) 17975// -52 (p - 1, possibly normalize denormal IEEE numbers) 17976// -11 (normalize the diyfp) 17977// = -1137 17978// 17979// and 17980// 17981// e <= +1023 (max IEEE exponent) 17982// -52 (p - 1) 17983// -11 (normalize the diyfp) 17984// = 960 17985// 17986// This binary exponent range [-1137,960] results in a decimal exponent 17987// range [-307,324]. One does not need to store a cached power for each 17988// k in this range. For each such k it suffices to find a cached power 17989// such that the exponent of the product lies in [alpha,gamma]. 17990// This implies that the difference of the decimal exponents of adjacent 17991// table entries must be less than or equal to 17992// 17993// floor( (gamma - alpha) * log_10(2) ) = 8. 17994// 17995// (A smaller distance gamma-alpha would require a larger table.) 17996 17997// NB: 17998// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. 17999 18000constexpr int kCachedPowersMinDecExp = -300 ; 18001constexpr int kCachedPowersDecStep = 8 ; 18002 18003static constexpr std:: array < cached_power , 79 > kCachedPowers = 18004{ 18005{ 18006{ 0xAB70FE17C79AC6CA , -1060 , -300 }, 18007{ 0xFF77B1FCBEBCDC4F , -1034 , -292 }, 18008{ 0xBE5691EF416BD60C , -1007 , -284 }, 18009{ 0x8DD01FAD907FFC3C , -980 , -276 }, 18010{ 0xD3515C2831559A83 , -954 , -268 }, 18011{ 0x9D71AC8FADA6C9B5 , -927 , -260 }, 18012{ 0xEA9C227723EE8BCB , -901 , -252 }, 18013{ 0xAECC49914078536D , -874 , -244 }, 18014{ 0x823C12795DB6CE57 , -847 , -236 }, 18015{ 0xC21094364DFB5637 , -821 , -228 }, 18016{ 0x9096EA6F3848984F , -794 , -220 }, 18017{ 0xD77485CB25823AC7 , -768 , -212 }, 18018{ 0xA086CFCD97BF97F4 , -741 , -204 }, 18019{ 0xEF340A98172AACE5 , -715 , -196 }, 18020{ 0xB23867FB2A35B28E , -688 , -188 }, 18021{ 0x84C8D4DFD2C63F3B , -661 , -180 }, 18022{ 0xC5DD44271AD3CDBA , -635 , -172 }, 18023{ 0x936B9FCEBB25C996 , -608 , -164 }, 18024{ 0xDBAC6C247D62A584 , -582 , -156 }, 18025{ 0xA3AB66580D5FDAF6 , -555 , -148 }, 18026{ 0xF3E2F893DEC3F126 , -529 , -140 }, 18027{ 0xB5B5ADA8AAFF80B8 , -502 , -132 }, 18028{ 0x87625F056C7C4A8B , -475 , -124 }, 18029{ 0xC9BCFF6034C13053 , -449 , -116 }, 18030{ 0x964E858C91BA2655 , -422 , -108 }, 18031{ 0xDFF9772470297EBD , -396 , -100 }, 18032{ 0xA6DFBD9FB8E5B88F , -369 , -92 }, 18033{ 0xF8A95FCF88747D94 , -343 , -84 }, 18034{ 0xB94470938FA89BCF , -316 , -76 }, 18035{ 0x8A08F0F8BF0F156B , -289 , -68 }, 18036{ 0xCDB02555653131B6 , -263 , -60 }, 18037{ 0x993FE2C6D07B7FAC , -236 , -52 }, 18038{ 0xE45C10C42A2B3B06 , -210 , -44 }, 18039{ 0xAA242499697392D3 , -183 , -36 }, 18040{ 0xFD87B5F28300CA0E , -157 , -28 }, 18041{ 0xBCE5086492111AEB , -130 , -20 }, 18042{ 0x8CBCCC096F5088CC , -103 , -12 }, 18043{ 0xD1B71758E219652C , -77 , -4 }, 18044{ 0x9C40000000000000 , -50 , 4 }, 18045{ 0xE8D4A51000000000 , -24 , 12 }, 18046{ 0xAD78EBC5AC620000 , 3 , 20 }, 18047{ 0x813F3978F8940984 , 30 , 28 }, 18048{ 0xC097CE7BC90715B3 , 56 , 36 }, 18049{ 0x8F7E32CE7BEA5C70 , 83 , 44 }, 18050{ 0xD5D238A4ABE98068 , 109 , 52 }, 18051{ 0x9F4F2726179A2245 , 136 , 60 }, 18052{ 0xED63A231D4C4FB27 , 162 , 68 }, 18053{ 0xB0DE65388CC8ADA8 , 189 , 76 }, 18054{ 0x83C7088E1AAB65DB , 216 , 84 }, 18055{ 0xC45D1DF942711D9A , 242 , 92 }, 18056{ 0x924D692CA61BE758 , 269 , 100 }, 18057{ 0xDA01EE641A708DEA , 295 , 108 }, 18058{ 0xA26DA3999AEF774A , 322 , 116 }, 18059{ 0xF209787BB47D6B85 , 348 , 124 }, 18060{ 0xB454E4A179DD1877 , 375 , 132 }, 18061{ 0x865B86925B9BC5C2 , 402 , 140 }, 18062{ 0xC83553C5C8965D3D , 428 , 148 }, 18063{ 0x952AB45CFA97A0B3 , 455 , 156 }, 18064{ 0xDE469FBD99A05FE3 , 481 , 164 }, 18065{ 0xA59BC234DB398C25 , 508 , 172 }, 18066{ 0xF6C69A72A3989F5C , 534 , 180 }, 18067{ 0xB7DCBF5354E9BECE , 561 , 188 }, 18068{ 0x88FCF317F22241E2 , 588 , 196 }, 18069{ 0xCC20CE9BD35C78A5 , 614 , 204 }, 18070{ 0x98165AF37B2153DF , 641 , 212 }, 18071{ 0xE2A0B5DC971F303A , 667 , 220 }, 18072{ 0xA8D9D1535CE3B396 , 694 , 228 }, 18073{ 0xFB9B7CD9A4A7443C , 720 , 236 }, 18074{ 0xBB764C4CA7A44410 , 747 , 244 }, 18075{ 0x8BAB8EEFB6409C1A , 774 , 252 }, 18076{ 0xD01FEF10A657842C , 800 , 260 }, 18077{ 0x9B10A4E5E9913129 , 827 , 268 }, 18078{ 0xE7109BFBA19C0C9D , 853 , 276 }, 18079{ 0xAC2820D9623BF429 , 880 , 284 }, 18080{ 0x80444B5E7AA7CF85 , 907 , 292 }, 18081{ 0xBF21E44003ACDD2D , 933 , 300 }, 18082{ 0x8E679C2F5E44FF8F , 960 , 308 }, 18083{ 0xD433179D9C8CB841 , 986 , 316 }, 18084{ 0x9E19DB92B4E31BA9 , 1013 , 324 }, 18085} 18086}; 18087 18088// This computation gives exactly the same results for k as 18089// k = ceil((kAlpha - e - 1) * 0.30102999566398114) 18090// for |e| <= 1500, but doesn't require floating-point operations. 18091// NB: log_10(2) ~= 78913 / 2^18 18092JSON_ASSERT (e >= -1500 ); 18093JSON_ASSERT (e <= 1500 ); 18094const int f = kAlpha - e - 1 ; 18095const int k = ((f * 78913 ) / ( 1 << 18 )) + static_cast < int > (f > 0 ); 18096 18097const int index = ( - kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1 )) / kCachedPowersDecStep; 18098JSON_ASSERT (index >= 0 ); 18099JSON_ASSERT ( static_cast < std:: size_t > (index) < kCachedPowers. size ()); 18100 18101const cached_power cached = kCachedPowers[ static_cast < std:: size_t > (index)]; 18102JSON_ASSERT (kAlpha <= cached. e + e + 64 ); 18103JSON_ASSERT (kGamma >= cached. e + e + 64 ); 18104 18105return cached; 18106} 18107 18108/*! 18109For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. 18110For n == 0, returns 1 and sets pow10 := 1. 18111*/ 18112inline int find_largest_pow10 ( const std:: uint32_t n, std:: uint32_t & pow10) 18113{ 18114// LCOV_EXCL_START 18115if (n >= 1000000000 ) 18116{ 18117pow10 = 1000000000 ; 18118return 10 ; 18119} 18120// LCOV_EXCL_STOP 18121if (n >= 100000000 ) 18122{ 18123pow10 = 100000000 ; 18124return 9 ; 18125} 18126if (n >= 10000000 ) 18127{ 18128pow10 = 10000000 ; 18129return 8 ; 18130} 18131if (n >= 1000000 ) 18132{ 18133pow10 = 1000000 ; 18134return 7 ; 18135} 18136if (n >= 100000 ) 18137{ 18138pow10 = 100000 ; 18139return 6 ; 18140} 18141if (n >= 10000 ) 18142{ 18143pow10 = 10000 ; 18144return 5 ; 18145} 18146if (n >= 1000 ) 18147{ 18148pow10 = 1000 ; 18149return 4 ; 18150} 18151if (n >= 100 ) 18152{ 18153pow10 = 100 ; 18154return 3 ; 18155} 18156if (n >= 10 ) 18157{ 18158pow10 = 10 ; 18159return 2 ; 18160} 18161 18162pow10 = 1 ; 18163return 1 ; 18164} 18165 18166inline void grisu2_round ( char * buf, int len, std:: uint64_t dist, std:: uint64_t delta, 18167std:: uint64_t rest, std:: uint64_t ten_k) 18168{ 18169JSON_ASSERT (len >= 1 ); 18170JSON_ASSERT (dist <= delta); 18171JSON_ASSERT (rest <= delta); 18172JSON_ASSERT (ten_k > 0 ); 18173 18174// <--------------------------- delta ----> 18175// <---- dist ---------> 18176// --------------[------------------+-------------------]-------------- 18177// M- w M+ 18178// 18179// ten_k 18180// <------> 18181// <---- rest ----> 18182// --------------[------------------+----+--------------]-------------- 18183// w V 18184// = buf * 10^k 18185// 18186// ten_k represents a unit-in-the-last-place in the decimal representation 18187// stored in buf. 18188// Decrement buf by ten_k while this takes buf closer to w. 18189 18190// The tests are written in this order to avoid overflow in unsigned 18191// integer arithmetic. 18192 18193while (rest < dist 18194&& delta - rest >= ten_k 18195&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) 18196{ 18197JSON_ASSERT (buf[len - 1 ] != '0' ); 18198buf[len - 1 ] -- ; 18199rest += ten_k; 18200} 18201} 18202 18203/*! 18204Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. 18205M- and M+ must be normalized and share the same exponent -60 <= e <= -32. 18206*/ 18207inline void grisu2_digit_gen ( char * buffer, int & length, int & decimal_exponent, 18208diyfp M_minus, diyfp w, diyfp M_plus) 18209{ 18210static_assert(kAlpha >= -60 , "internal error" ); 18211static_assert(kGamma <= -32 , "internal error" ); 18212 18213// Generates the digits (and the exponent) of a decimal floating-point 18214// number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's 18215// w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. 18216// 18217// <--------------------------- delta ----> 18218// <---- dist ---------> 18219// --------------[------------------+-------------------]-------------- 18220// M- w M+ 18221// 18222// Grisu2 generates the digits of M+ from left to right and stops as soon as 18223// V is in [M-,M+]. 18224 18225JSON_ASSERT (M_plus. e >= kAlpha); 18226JSON_ASSERT (M_plus. e <= kGamma); 18227 18228std:: uint64_t delta = diyfp:: sub (M_plus, M_minus). f ; // (significand of (M+ - M-), implicit exponent is e) 18229std:: uint64_t dist = diyfp:: sub (M_plus, w ). f ; // (significand of (M+ - w ), implicit exponent is e) 18230 18231// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): 18232// 18233// M+ = f * 2^e 18234// = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e 18235// = ((p1 ) * 2^-e + (p2 )) * 2^e 18236// = p1 + p2 * 2^e 18237 18238const diyfp one(std:: uint64_t { 1 } << - M_plus. e , M_plus. e ); 18239 18240auto p1 = static_cast < std:: uint32_t > (M_plus. f >> - one. e ); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) 18241std:: uint64_t p2 = M_plus. f & (one. f - 1 ); // p2 = f mod 2^-e 18242 18243// 1) 18244// 18245// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] 18246 18247JSON_ASSERT (p1 > 0 ); 18248 18249std:: uint32_t pow10{}; 18250const int k = find_largest_pow10 (p1, pow10); 18251 18252// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) 18253// 18254// p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) 18255// = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) 18256// 18257// M+ = p1 + p2 * 2^e 18258// = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e 18259// = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e 18260// = d[k-1] * 10^(k-1) + ( rest) * 2^e 18261// 18262// Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) 18263// 18264// p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] 18265// 18266// but stop as soon as 18267// 18268// rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e 18269 18270int n = k; 18271while (n > 0 ) 18272{ 18273// Invariants: 18274// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) 18275// pow10 = 10^(n-1) <= p1 < 10^n 18276// 18277const std:: uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) 18278const std:: uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) 18279// 18280// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e 18281// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) 18282// 18283JSON_ASSERT (d <= 9 ); 18284buffer[length ++ ] = static_cast < char > ( '0' + d); // buffer := buffer * 10 + d 18285// 18286// M+ = buffer * 10^(n-1) + (r + p2 * 2^e) 18287// 18288p1 = r; 18289n -- ; 18290// 18291// M+ = buffer * 10^n + (p1 + p2 * 2^e) 18292// pow10 = 10^n 18293// 18294 18295// Now check if enough digits have been generated. 18296// Compute 18297// 18298// p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e 18299// 18300// Note: 18301// Since rest and delta share the same exponent e, it suffices to 18302// compare the significands. 18303const std:: uint64_t rest = (std:: uint64_t {p1} << - one. e ) + p2; 18304if (rest <= delta) 18305{ 18306// V = buffer * 10^n, with M- <= V <= M+. 18307 18308decimal_exponent += n; 18309 18310// We may now just stop. But instead look if the buffer could be 18311// decremented to bring V closer to w. 18312// 18313// pow10 = 10^n is now 1 ulp in the decimal representation V. 18314// The rounding procedure works with diyfp's with an implicit 18315// exponent of e. 18316// 18317// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e 18318// 18319const std:: uint64_t ten_n = std:: uint64_t {pow10} << - one. e ; 18320grisu2_round (buffer, length, dist, delta, rest, ten_n); 18321 18322return ; 18323} 18324 18325pow10 /= 10 ; 18326// 18327// pow10 = 10^(n-1) <= p1 < 10^n 18328// Invariants restored. 18329} 18330 18331// 2) 18332// 18333// The digits of the integral part have been generated: 18334// 18335// M+ = d[k-1]...d[1]d[0] + p2 * 2^e 18336// = buffer + p2 * 2^e 18337// 18338// Now generate the digits of the fractional part p2 * 2^e. 18339// 18340// Note: 18341// No decimal point is generated: the exponent is adjusted instead. 18342// 18343// p2 actually represents the fraction 18344// 18345// p2 * 2^e 18346// = p2 / 2^-e 18347// = d[-1] / 10^1 + d[-2] / 10^2 + ... 18348// 18349// Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) 18350// 18351// p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m 18352// + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) 18353// 18354// using 18355// 18356// 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) 18357// = ( d) * 2^-e + ( r) 18358// 18359// or 18360// 10^m * p2 * 2^e = d + r * 2^e 18361// 18362// i.e. 18363// 18364// M+ = buffer + p2 * 2^e 18365// = buffer + 10^-m * (d + r * 2^e) 18366// = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e 18367// 18368// and stop as soon as 10^-m * r * 2^e <= delta * 2^e 18369 18370JSON_ASSERT (p2 > delta); 18371 18372int m = 0 ; 18373for (;;) 18374{ 18375// Invariant: 18376// M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e 18377// = buffer * 10^-m + 10^-m * (p2 ) * 2^e 18378// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e 18379// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e 18380// 18381JSON_ASSERT (p2 <= (std:: numeric_limits < std:: uint64_t > ::max)() / 10 ); 18382p2 *= 10 ; 18383const std:: uint64_t d = p2 >> - one. e ; // d = (10 * p2) div 2^-e 18384const std:: uint64_t r = p2 & (one. f - 1 ); // r = (10 * p2) mod 2^-e 18385// 18386// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e 18387// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) 18388// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e 18389// 18390JSON_ASSERT (d <= 9 ); 18391buffer[length ++ ] = static_cast < char > ( '0' + d); // buffer := buffer * 10 + d 18392// 18393// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e 18394// 18395p2 = r; 18396m ++ ; 18397// 18398// M+ = buffer * 10^-m + 10^-m * p2 * 2^e 18399// Invariant restored. 18400 18401// Check if enough digits have been generated. 18402// 18403// 10^-m * p2 * 2^e <= delta * 2^e 18404// p2 * 2^e <= 10^m * delta * 2^e 18405// p2 <= 10^m * delta 18406delta *= 10 ; 18407dist *= 10 ; 18408if (p2 <= delta) 18409{ 18410break ; 18411} 18412} 18413 18414// V = buffer * 10^-m, with M- <= V <= M+. 18415 18416decimal_exponent -= m; 18417 18418// 1 ulp in the decimal representation is now 10^-m. 18419// Since delta and dist are now scaled by 10^m, we need to do the 18420// same with ulp in order to keep the units in sync. 18421// 18422// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e 18423// 18424const std:: uint64_t ten_m = one. f ; 18425grisu2_round (buffer, length, dist, delta, p2, ten_m); 18426 18427// By construction this algorithm generates the shortest possible decimal 18428// number (Loitsch, Theorem 6.2) which rounds back to w. 18429// For an input number of precision p, at least 18430// 18431// N = 1 + ceil(p * log_10(2)) 18432// 18433// decimal digits are sufficient to identify all binary floating-point 18434// numbers (Matula, "In-and-Out conversions"). 18435// This implies that the algorithm does not produce more than N decimal 18436// digits. 18437// 18438// N = 17 for p = 53 (IEEE double precision) 18439// N = 9 for p = 24 (IEEE single precision) 18440} 18441 18442/*! 18443v = buf * 10^decimal_exponent 18444len is the length of the buffer (number of decimal digits) 18445The buffer must be large enough, i.e. >= max_digits10. 18446*/ 18447JSON_HEDLEY_NON_NULL ( 1 ) 18448inline void grisu2 ( char * buf, int & len, int & decimal_exponent, 18449diyfp m_minus, diyfp v, diyfp m_plus) 18450{ 18451JSON_ASSERT (m_plus. e == m_minus. e ); 18452JSON_ASSERT (m_plus. e == v. e ); 18453 18454// --------(-----------------------+-----------------------)-------- (A) 18455// m- v m+ 18456// 18457// --------------------(-----------+-----------------------)-------- (B) 18458// m- v m+ 18459// 18460// First scale v (and m- and m+) such that the exponent is in the range 18461// [alpha, gamma]. 18462 18463const cached_power cached = get_cached_power_for_binary_exponent (m_plus. e ); 18464 18465const diyfp c_minus_k(cached. f , cached. e ); // = c ~= 10^-k 18466 18467// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] 18468const diyfp w = diyfp:: mul (v, c_minus_k); 18469const diyfp w_minus = diyfp:: mul (m_minus, c_minus_k); 18470const diyfp w_plus = diyfp:: mul (m_plus, c_minus_k); 18471 18472// ----(---+---)---------------(---+---)---------------(---+---)---- 18473// w- w w+ 18474// = c*m- = c*v = c*m+ 18475// 18476// diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and 18477// w+ are now off by a small amount. 18478// In fact: 18479// 18480// w - v * 10^k < 1 ulp 18481// 18482// To account for this inaccuracy, add resp. subtract 1 ulp. 18483// 18484// --------+---[---------------(---+---)---------------]---+-------- 18485// w- M- w M+ w+ 18486// 18487// Now any number in [M-, M+] (bounds included) will round to w when input, 18488// regardless of how the input rounding algorithm breaks ties. 18489// 18490// And digit_gen generates the shortest possible such number in [M-, M+]. 18491// Note that this does not mean that Grisu2 always generates the shortest 18492// possible number in the interval (m-, m+). 18493const diyfp M_minus(w_minus. f + 1 , w_minus. e ); 18494const diyfp M_plus (w_plus. f - 1 , w_plus. e ); 18495 18496decimal_exponent = - cached. k ; // = -(-k) = k 18497 18498grisu2_digit_gen (buf, len, decimal_exponent, M_minus, w, M_plus); 18499} 18500 18501/*! 18502v = buf * 10^decimal_exponent 18503len is the length of the buffer (number of decimal digits) 18504The buffer must be large enough, i.e. >= max_digits10. 18505*/ 18506template < typename FloatType > 18507JSON_HEDLEY_NON_NULL ( 1 ) 18508void grisu2 ( char * buf, int & len, int & decimal_exponent, FloatType value) 18509{ 18510static_assert(diyfp::kPrecision >= std:: numeric_limits < FloatType > ::digits + 3 , 18511"internal error: not enough precision" ); 18512 18513JSON_ASSERT (std:: isfinite (value)); 18514JSON_ASSERT (value > 0 ); 18515 18516// If the neighbors (and boundaries) of 'value' are always computed for double-precision 18517// numbers, all float's can be recovered using strtod (and strtof). However, the resulting 18518// decimal representations are not exactly "short". 18519// 18520// The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) 18521// says "value is converted to a string as if by std::sprintf in the default ("C") locale" 18522// and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' 18523// does. 18524// On the other hand, the documentation for 'std::to_chars' requires that "parsing the 18525// representation using the corresponding std::from_chars function recovers value exactly". That 18526// indicates that single precision floating-point numbers should be recovered using 18527// 'std::strtof'. 18528// 18529// NB: If the neighbors are computed for single-precision numbers, there is a single float 18530// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision 18531// value is off by 1 ulp. 18532#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) 18533const boundaries w = compute_boundaries ( static_cast < double > (value)); 18534#else 18535const boundaries w = compute_boundaries (value); 18536#endif 18537 18538grisu2 (buf, len, decimal_exponent, w. minus , w. w , w. plus ); 18539} 18540 18541/*! 18542@brief appends a decimal representation of e to buf 18543@return a pointer to the element following the exponent. 18544@pre -1000 < e < 1000 18545*/ 18546JSON_HEDLEY_NON_NULL ( 1 ) 18547JSON_HEDLEY_RETURNS_NON_NULL 18548inline char * append_exponent ( char * buf, int e) 18549{ 18550JSON_ASSERT (e > -1000 ); 18551JSON_ASSERT (e < 1000 ); 18552 18553if (e < 0 ) 18554{ 18555e = - e; 18556* buf ++ = '-' ; 18557} 18558else 18559{ 18560* buf ++ = '+' ; 18561} 18562 18563auto k = static_cast < std:: uint32_t > (e); 18564if (k < 10 ) 18565{ 18566// Always print at least two digits in the exponent. 18567// This is for compatibility with printf("%g"). 18568* buf ++ = '0' ; 18569* buf ++ = static_cast < char > ( '0' + k); 18570} 18571else if (k < 100 ) 18572{ 18573* buf ++ = static_cast < char > ( '0' + (k / 10 )); 18574k %= 10 ; 18575* buf ++ = static_cast < char > ( '0' + k); 18576} 18577else 18578{ 18579* buf ++ = static_cast < char > ( '0' + (k / 100 )); 18580k %= 100 ; 18581* buf ++ = static_cast < char > ( '0' + (k / 10 )); 18582k %= 10 ; 18583* buf ++ = static_cast < char > ( '0' + k); 18584} 18585 18586return buf; 18587} 18588 18589/*! 18590@brief prettify v = buf * 10^decimal_exponent 18591 18592If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point 18593notation. Otherwise it will be printed in exponential notation. 18594 18595@pre min_exp < 0 18596@pre max_exp > 0 18597*/ 18598JSON_HEDLEY_NON_NULL ( 1 ) 18599JSON_HEDLEY_RETURNS_NON_NULL 18600inline char * format_buffer ( char * buf, int len, int decimal_exponent, 18601int min_exp, int max_exp) 18602{ 18603JSON_ASSERT (min_exp < 0 ); 18604JSON_ASSERT (max_exp > 0 ); 18605 18606const int k = len; 18607const int n = len + decimal_exponent; 18608 18609// v = buf * 10^(n-k) 18610// k is the length of the buffer (number of decimal digits) 18611// n is the position of the decimal point relative to the start of the buffer. 18612 18613if (k <= n && n <= max_exp) 18614{ 18615// digits[000] 18616// len <= max_exp + 2 18617 18618std:: memset (buf + k, '0' , static_cast < size_t > (n) - static_cast < size_t > (k)); 18619// Make it look like a floating-point number (#362, #378) 18620buf[n + 0 ] = '.' ; 18621buf[n + 1 ] = '0' ; 18622return buf + ( static_cast < size_t > (n) + 2 ); 18623} 18624 18625if ( 0 < n && n <= max_exp) 18626{ 18627// dig.its 18628// len <= max_digits10 + 1 18629 18630JSON_ASSERT (k > n); 18631 18632std:: memmove (buf + ( static_cast < size_t > (n) + 1 ), buf + n, static_cast < size_t > (k) - static_cast < size_t > (n)); 18633buf[n] = '.' ; 18634return buf + ( static_cast < size_t > (k) + 1U ); 18635} 18636 18637if (min_exp < n && n <= 0 ) 18638{ 18639// 0.[000]digits 18640// len <= 2 + (-min_exp - 1) + max_digits10 18641 18642std:: memmove (buf + ( 2 + static_cast < size_t > ( - n)), buf, static_cast < size_t > (k)); 18643buf[ 0 ] = '0' ; 18644buf[ 1 ] = '.' ; 18645std:: memset (buf + 2 , '0' , static_cast < size_t > ( - n)); 18646return buf + ( 2U + static_cast < size_t > ( - n) + static_cast < size_t > (k)); 18647} 18648 18649if (k == 1 ) 18650{ 18651// dE+123 18652// len <= 1 + 5 18653 18654buf += 1 ; 18655} 18656else 18657{ 18658// d.igitsE+123 18659// len <= max_digits10 + 1 + 5 18660 18661std:: memmove (buf + 2 , buf + 1 , static_cast < size_t > (k) - 1 ); 18662buf[ 1 ] = '.' ; 18663buf += 1 + static_cast < size_t > (k); 18664} 18665 18666* buf ++ = 'e' ; 18667return append_exponent (buf, n - 1 ); 18668} 18669 18670} // namespace dtoa_impl 18671 18672/*! 18673@brief generates a decimal representation of the floating-point number value in [first, last). 18674 18675The format of the resulting decimal representation is similar to printf's %g 18676format. Returns an iterator pointing past-the-end of the decimal representation. 18677 18678@note The input number must be finite, i.e. NaN's and Inf's are not supported. 18679@note The buffer must be large enough. 18680@note The result is NOT null-terminated. 18681*/ 18682template < typename FloatType > 18683JSON_HEDLEY_NON_NULL ( 1 , 2 ) 18684JSON_HEDLEY_RETURNS_NON_NULL 18685char * to_chars ( char * first, const char * last, FloatType value) 18686{ 18687static_cast < void > ( last ); // maybe unused - fix warning 18688JSON_ASSERT (std:: isfinite (value)); 18689 18690// Use signbit(value) instead of (value < 0) since signbit works for -0. 18691if (std:: signbit (value)) 18692{ 18693value = - value; 18694* first ++ = '-' ; 18695} 18696 18697#ifdef __GNUC__ 18698#pragma GCC diagnostic push 18699#pragma GCC diagnostic ignored "-Wfloat-equal" 18700#endif 18701if (value == 0 ) // +-0 18702{ 18703* first ++ = '0' ; 18704// Make it look like a floating-point number (#362, #378) 18705* first ++ = '.' ; 18706* first ++ = '0' ; 18707return first; 18708} 18709#ifdef __GNUC__ 18710#pragma GCC diagnostic pop 18711#endif 18712 18713JSON_ASSERT (last - first >= std:: numeric_limits < FloatType > ::max_digits10); 18714 18715// Compute v = buffer * 10^decimal_exponent. 18716// The decimal digits are stored in the buffer, which needs to be interpreted 18717// as an unsigned decimal integer. 18718// len is the length of the buffer, i.e. the number of decimal digits. 18719int len = 0 ; 18720int decimal_exponent = 0 ; 18721dtoa_impl:: grisu2 (first, len, decimal_exponent, value); 18722 18723JSON_ASSERT (len <= std:: numeric_limits < FloatType > ::max_digits10); 18724 18725// Format the buffer like printf("%.*g", prec, value) 18726constexpr int kMinExp = -4 ; 18727// Use digits10 here to increase compatibility with version 2. 18728constexpr int kMaxExp = std:: numeric_limits < FloatType > ::digits10; 18729 18730JSON_ASSERT (last - first >= kMaxExp + 2 ); 18731JSON_ASSERT (last - first >= 2 + ( - kMinExp - 1 ) + std:: numeric_limits < FloatType > ::max_digits10); 18732JSON_ASSERT (last - first >= std:: numeric_limits < FloatType > ::max_digits10 + 6 ); 18733 18734return dtoa_impl:: format_buffer (first, len, decimal_exponent, kMinExp, kMaxExp); 18735} 18736 18737} // namespace detail 18738NLOHMANN_JSON_NAMESPACE_END 18739 18740// #include <nlohmann/detail/exceptions.hpp> 18741 18742// #include <nlohmann/detail/macro_scope.hpp> 18743 18744// #include <nlohmann/detail/meta/cpp_future.hpp> 18745 18746// #include <nlohmann/detail/output/binary_writer.hpp> 18747 18748// #include <nlohmann/detail/output/output_adapters.hpp> 18749 18750// #include <nlohmann/detail/string_concat.hpp> 18751 18752// #include <nlohmann/detail/value_t.hpp> 18753 18754 18755NLOHMANN_JSON_NAMESPACE_BEGIN 18756namespace detail 18757{ 18758 18759/////////////////// 18760// serialization // 18761/////////////////// 18762 18763/// how to treat decoding errors 18764enum class error_handler_t 18765{ 18766strict, ///< throw a type_error exception in case of invalid UTF-8 18767replace, ///< replace invalid UTF-8 sequences with U+FFFD 18768ignore ///< ignore invalid UTF-8 sequences 18769}; 18770 18771template < typename BasicJsonType > 18772class serializer 18773{ 18774using string_t = typename BasicJsonType :: string_t ; 18775using number_float_t = typename BasicJsonType :: number_float_t ; 18776using number_integer_t = typename BasicJsonType :: number_integer_t ; 18777using number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 18778using binary_char_t = typename BasicJsonType ::binary_t:: value_type ; 18779static constexpr std:: uint8_t UTF8_ACCEPT = 0 ; 18780static constexpr std:: uint8_t UTF8_REJECT = 1 ; 18781 18782public : 18783/*! 18784@param[in] s output stream to serialize to 18785@param[in] ichar indentation character to use 18786@param[in] error_handler_ how to react on decoding errors 18787*/ 18788serializer ( output_adapter_t < char > s, const char ichar, 18789error_handler_t error_handler_ = error_handler_t::strict) 18790: o (std:: move (s)) 18791, loc (std:: localeconv ()) 18792, thousands_sep (loc -> thousands_sep == nullptr ? '\0' : std:: char_traits < char > ::to_char_type( * (loc -> thousands_sep ))) 18793, decimal_point (loc -> decimal_point == nullptr ? '\0' : std:: char_traits < char > ::to_char_type( * (loc -> decimal_point ))) 18794, indent_char (ichar) 18795, indent_string ( 512 , indent_char) 18796, error_handler (error_handler_) 18797{} 18798 18799// delete because of pointer members 18800serializer ( const serializer & ) = delete ; 18801serializer & operator = ( const serializer & ) = delete ; 18802serializer ( serializer && ) = delete ; 18803serializer & operator = ( serializer && ) = delete ; 18804~serializer() = default ; 18805 18806/*! 18807@brief internal implementation of the serialization function 18808 18809This function is called by the public member function dump and organizes 18810the serialization internally. The indentation level is propagated as 18811additional parameter. In case of arrays and objects, the function is 18812called recursively. 18813 18814- strings and object keys are escaped using `escape_string()` 18815- integer numbers are converted implicitly via `operator<<` 18816- floating-point numbers are converted to a string using `"%g"` format 18817- binary values are serialized as objects containing the subtype and the 18818byte array 18819 18820@param[in] val value to serialize 18821@param[in] pretty_print whether the output shall be pretty-printed 18822@param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters 18823in the output are escaped with `\uXXXX` sequences, and the result consists 18824of ASCII characters only. 18825@param[in] indent_step the indent level 18826@param[in] current_indent the current indent level (only used internally) 18827*/ 18828void dump ( const BasicJsonType & val, 18829const bool pretty_print, 18830const bool ensure_ascii, 18831const unsigned int indent_step, 18832const unsigned int current_indent = 0 ) 18833{ 18834switch (val. m_data . m_type ) 18835{ 18836case value_t::object: 18837{ 18838if (val. m_data . m_value . object -> empty ()) 18839{ 18840o -> write_characters ( "{}" , 2 ); 18841return ; 18842} 18843 18844if (pretty_print) 18845{ 18846o -> write_characters ( "{\n" , 2 ); 18847 18848// variable to hold indentation for recursive calls 18849const auto new_indent = current_indent + indent_step; 18850if ( JSON_HEDLEY_UNLIKELY (indent_string. size () < new_indent)) 18851{ 18852indent_string. resize (indent_string. size () * 2 , ' ' ); 18853} 18854 18855// first n-1 elements 18856auto i = val. m_data . m_value . object -> cbegin (); 18857for (std:: size_t cnt = 0 ; cnt < val. m_data . m_value . object -> size () - 1 ; ++ cnt, ++ i) 18858{ 18859o -> write_characters (indent_string. c_str (), new_indent); 18860o -> write_character ( '\"' ); 18861dump_escaped (i -> first , ensure_ascii); 18862o -> write_characters ( "\": " , 3 ); 18863dump (i -> second , true, ensure_ascii, indent_step, new_indent); 18864o -> write_characters ( ",\n" , 2 ); 18865} 18866 18867// last element 18868JSON_ASSERT (i != val. m_data . m_value . object -> cend ()); 18869JSON_ASSERT (std:: next (i) == val. m_data . m_value . object -> cend ()); 18870o -> write_characters (indent_string. c_str (), new_indent); 18871o -> write_character ( '\"' ); 18872dump_escaped (i -> first , ensure_ascii); 18873o -> write_characters ( "\": " , 3 ); 18874dump (i -> second , true, ensure_ascii, indent_step, new_indent); 18875 18876o -> write_character ( '\n' ); 18877o -> write_characters (indent_string. c_str (), current_indent); 18878o -> write_character ( '}' ); 18879} 18880else 18881{ 18882o -> write_character ( '{' ); 18883 18884// first n-1 elements 18885auto i = val. m_data . m_value . object -> cbegin (); 18886for (std:: size_t cnt = 0 ; cnt < val. m_data . m_value . object -> size () - 1 ; ++ cnt, ++ i) 18887{ 18888o -> write_character ( '\"' ); 18889dump_escaped (i -> first , ensure_ascii); 18890o -> write_characters ( "\":" , 2 ); 18891dump (i -> second , false, ensure_ascii, indent_step, current_indent); 18892o -> write_character ( ',' ); 18893} 18894 18895// last element 18896JSON_ASSERT (i != val. m_data . m_value . object -> cend ()); 18897JSON_ASSERT (std:: next (i) == val. m_data . m_value . object -> cend ()); 18898o -> write_character ( '\"' ); 18899dump_escaped (i -> first , ensure_ascii); 18900o -> write_characters ( "\":" , 2 ); 18901dump (i -> second , false, ensure_ascii, indent_step, current_indent); 18902 18903o -> write_character ( '}' ); 18904} 18905 18906return ; 18907} 18908 18909case value_t::array: 18910{ 18911if (val. m_data . m_value . array -> empty ()) 18912{ 18913o -> write_characters ( "[]" , 2 ); 18914return ; 18915} 18916 18917if (pretty_print) 18918{ 18919o -> write_characters ( "[\n" , 2 ); 18920 18921// variable to hold indentation for recursive calls 18922const auto new_indent = current_indent + indent_step; 18923if ( JSON_HEDLEY_UNLIKELY (indent_string. size () < new_indent)) 18924{ 18925indent_string. resize (indent_string. size () * 2 , ' ' ); 18926} 18927 18928// first n-1 elements 18929for ( auto i = val. m_data . m_value . array -> cbegin (); 18930i != val. m_data . m_value . array -> cend () - 1 ; ++ i) 18931{ 18932o -> write_characters (indent_string. c_str (), new_indent); 18933dump ( * i, true, ensure_ascii, indent_step, new_indent); 18934o -> write_characters ( ",\n" , 2 ); 18935} 18936 18937// last element 18938JSON_ASSERT (!val. m_data . m_value . array -> empty ()); 18939o -> write_characters (indent_string. c_str (), new_indent); 18940dump (val. m_data . m_value . array -> back (), true, ensure_ascii, indent_step, new_indent); 18941 18942o -> write_character ( '\n' ); 18943o -> write_characters (indent_string. c_str (), current_indent); 18944o -> write_character ( ']' ); 18945} 18946else 18947{ 18948o -> write_character ( '[' ); 18949 18950// first n-1 elements 18951for ( auto i = val. m_data . m_value . array -> cbegin (); 18952i != val. m_data . m_value . array -> cend () - 1 ; ++ i) 18953{ 18954dump ( * i, false, ensure_ascii, indent_step, current_indent); 18955o -> write_character ( ',' ); 18956} 18957 18958// last element 18959JSON_ASSERT (!val. m_data . m_value . array -> empty ()); 18960dump (val. m_data . m_value . array -> back (), false, ensure_ascii, indent_step, current_indent); 18961 18962o -> write_character ( ']' ); 18963} 18964 18965return ; 18966} 18967 18968case value_t::string: 18969{ 18970o -> write_character ( '\"' ); 18971dump_escaped ( * val. m_data . m_value . string , ensure_ascii); 18972o -> write_character ( '\"' ); 18973return ; 18974} 18975 18976case value_t::binary: 18977{ 18978if (pretty_print) 18979{ 18980o -> write_characters ( "{\n" , 2 ); 18981 18982// variable to hold indentation for recursive calls 18983const auto new_indent = current_indent + indent_step; 18984if ( JSON_HEDLEY_UNLIKELY (indent_string. size () < new_indent)) 18985{ 18986indent_string. resize (indent_string. size () * 2 , ' ' ); 18987} 18988 18989o -> write_characters (indent_string. c_str (), new_indent); 18990 18991o -> write_characters ( "\"bytes\": [" , 10 ); 18992 18993if (!val. m_data . m_value . binary -> empty ()) 18994{ 18995for ( auto i = val. m_data . m_value . binary -> cbegin (); 18996i != val. m_data . m_value . binary -> cend () - 1 ; ++ i) 18997{ 18998dump_integer ( * i); 18999o -> write_characters ( ", " , 2 ); 19000} 19001dump_integer (val. m_data . m_value . binary -> back ()); 19002} 19003 19004o -> write_characters ( "],\n" , 3 ); 19005o -> write_characters (indent_string. c_str (), new_indent); 19006 19007o -> write_characters ( "\"subtype\": " , 11 ); 19008if (val. m_data . m_value . binary -> has_subtype ()) 19009{ 19010dump_integer (val. m_data . m_value . binary -> subtype ()); 19011} 19012else 19013{ 19014o -> write_characters ( "null" , 4 ); 19015} 19016o -> write_character ( '\n' ); 19017o -> write_characters (indent_string. c_str (), current_indent); 19018o -> write_character ( '}' ); 19019} 19020else 19021{ 19022o -> write_characters ( "{\"bytes\":[" , 10 ); 19023 19024if (!val. m_data . m_value . binary -> empty ()) 19025{ 19026for ( auto i = val. m_data . m_value . binary -> cbegin (); 19027i != val. m_data . m_value . binary -> cend () - 1 ; ++ i) 19028{ 19029dump_integer ( * i); 19030o -> write_character ( ',' ); 19031} 19032dump_integer (val. m_data . m_value . binary -> back ()); 19033} 19034 19035o -> write_characters ( "],\"subtype\":" , 12 ); 19036if (val. m_data . m_value . binary -> has_subtype ()) 19037{ 19038dump_integer (val. m_data . m_value . binary -> subtype ()); 19039o -> write_character ( '}' ); 19040} 19041else 19042{ 19043o -> write_characters ( "null}" , 5 ); 19044} 19045} 19046return ; 19047} 19048 19049case value_t::boolean: 19050{ 19051if (val. m_data . m_value . boolean ) 19052{ 19053o -> write_characters ( "true" , 4 ); 19054} 19055else 19056{ 19057o -> write_characters ( "false" , 5 ); 19058} 19059return ; 19060} 19061 19062case value_t::number_integer: 19063{ 19064dump_integer (val. m_data . m_value . number_integer ); 19065return ; 19066} 19067 19068case value_t::number_unsigned: 19069{ 19070dump_integer (val. m_data . m_value . number_unsigned ); 19071return ; 19072} 19073 19074case value_t::number_float: 19075{ 19076dump_float (val. m_data . m_value . number_float ); 19077return ; 19078} 19079 19080case value_t::discarded: 19081{ 19082o -> write_characters ( "<discarded>" , 11 ); 19083return ; 19084} 19085 19086case value_t::null: 19087{ 19088o -> write_characters ( "null" , 4 ); 19089return ; 19090} 19091 19092default : // LCOV_EXCL_LINE 19093JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 19094} 19095} 19096 19097JSON_PRIVATE_UNLESS_TESTED : 19098/*! 19099@brief dump escaped string 19100 19101Escape a string by replacing certain special characters by a sequence of an 19102escape character (backslash) and another character and other control 19103characters by a sequence of "\u" followed by a four-digit hex 19104representation. The escaped string is written to output stream @a o. 19105 19106@param[in] s the string to escape 19107@param[in] ensure_ascii whether to escape non-ASCII characters with 19108\uXXXX sequences 19109 19110@complexity Linear in the length of string @a s. 19111*/ 19112void dump_escaped ( const string_t & s , const bool ensure_ascii ) 19113{ 19114std:: uint32_t codepoint {}; 19115std:: uint8_t state = UTF8_ACCEPT ; 19116std:: size_t bytes = 0 ; // number of bytes written to string_buffer 19117 19118// number of bytes written at the point of the last valid byte 19119std:: size_t bytes_after_last_accept = 0 ; 19120std:: size_t undumped_chars = 0 ; 19121 19122for (std:: size_t i = 0 ; i < s . size (); ++ i ) 19123{ 19124const auto byte = static_cast <std:: uint8_t >( s [ i ]); 19125 19126switch ( decode ( state , codepoint , byte )) 19127{ 19128case UTF8_ACCEPT : // decode found a new code point 19129{ 19130switch ( codepoint ) 19131{ 19132case 0x08 : // backspace 19133{ 19134string_buffer [ bytes ++] = '\\' ; 19135string_buffer [ bytes ++] = 'b' ; 19136break ; 19137} 19138 19139case 0x09 : // horizontal tab 19140{ 19141string_buffer [ bytes ++] = '\\' ; 19142string_buffer [ bytes ++] = 't' ; 19143break ; 19144} 19145 19146case 0x0A : // newline 19147{ 19148string_buffer [ bytes ++] = '\\' ; 19149string_buffer [ bytes ++] = 'n' ; 19150break ; 19151} 19152 19153case 0x0C : // formfeed 19154{ 19155string_buffer [ bytes ++] = '\\' ; 19156string_buffer [ bytes ++] = 'f' ; 19157break ; 19158} 19159 19160case 0x0D : // carriage return 19161{ 19162string_buffer [ bytes ++] = '\\' ; 19163string_buffer [ bytes ++] = 'r' ; 19164break ; 19165} 19166 19167case 0x22 : // quotation mark 19168{ 19169string_buffer [ bytes ++] = '\\' ; 19170string_buffer [ bytes ++] = '\"' ; 19171break ; 19172} 19173 19174case 0x5C : // reverse solidus 19175{ 19176string_buffer [ bytes ++] = '\\' ; 19177string_buffer [ bytes ++] = '\\' ; 19178break ; 19179} 19180 19181default : 19182{ 19183// escape control characters (0x00..0x1F) or, if 19184// ensure_ascii parameter is used, non-ASCII characters 19185if (( codepoint <= 0x1F ) || ( ensure_ascii && ( codepoint >= 0x7F ))) 19186{ 19187if ( codepoint <= 0xFFFF ) 19188{ 19189// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 19190static_cast < void >((std:: snprintf )( string_buffer . data () + bytes , 7 , "\\u%04x" , 19191static_cast <std:: uint16_t >( codepoint ))); 19192bytes += 6 ; 19193} 19194else 19195{ 19196// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 19197static_cast < void >((std:: snprintf )( string_buffer . data () + bytes , 13 , "\\u%04x\\u%04x" , 19198static_cast <std:: uint16_t >( 0xD7C0u + ( codepoint >> 10u )), 19199static_cast <std:: uint16_t >( 0xDC00u + ( codepoint & 0x3FFu )))); 19200bytes += 12 ; 19201} 19202} 19203else 19204{ 19205// copy byte to buffer (all previous bytes 19206// been copied have in default case above) 19207string_buffer [ bytes ++] = s [ i ]; 19208} 19209break ; 19210} 19211} 19212 19213// write buffer and reset index; there must be 13 bytes 19214// left, as this is the maximal number of bytes to be 19215// written ("\uxxxx\uxxxx\0") for one code point 19216if ( string_buffer . size () - bytes < 13 ) 19217{ 19218o -> write_characters ( string_buffer . data (), bytes ); 19219bytes = 0 ; 19220} 19221 19222// remember the byte position of this accept 19223bytes_after_last_accept = bytes ; 19224undumped_chars = 0 ; 19225break ; 19226} 19227 19228case UTF8_REJECT : // decode found invalid UTF-8 byte 19229{ 19230switch ( error_handler ) 19231{ 19232case error_handler_t:: strict : 19233{ 19234JSON_THROW (type_error:: create ( 316 , concat ( "invalid UTF-8 byte at index " , std:: to_string ( i ), ": 0x" , hex_bytes ( byte | 0 )), nullptr )); 19235} 19236 19237case error_handler_t:: ignore : 19238case error_handler_t:: replace : 19239{ 19240// in case we saw this character the first time, we 19241// would like to read it again, because the byte 19242// may be OK for itself, but just not OK for the 19243// previous sequence 19244if ( undumped_chars > 0 ) 19245{ 19246-- i ; 19247} 19248 19249// reset length buffer to the last accepted index; 19250// thus removing/ignoring the invalid characters 19251bytes = bytes_after_last_accept ; 19252 19253if ( error_handler == error_handler_t:: replace ) 19254{ 19255// add a replacement character 19256if ( ensure_ascii ) 19257{ 19258string_buffer [ bytes ++] = '\\' ; 19259string_buffer [ bytes ++] = 'u' ; 19260string_buffer [ bytes ++] = 'f' ; 19261string_buffer [ bytes ++] = 'f' ; 19262string_buffer [ bytes ++] = 'f' ; 19263string_buffer [ bytes ++] = 'd' ; 19264} 19265else 19266{ 19267string_buffer [ bytes ++] = detail:: binary_writer < BasicJsonType , char >:: to_char_type ( '\xEF' ); 19268string_buffer [ bytes ++] = detail:: binary_writer < BasicJsonType , char >:: to_char_type ( '\xBF' ); 19269string_buffer [ bytes ++] = detail:: binary_writer < BasicJsonType , char >:: to_char_type ( '\xBD' ); 19270} 19271 19272// write buffer and reset index; there must be 13 bytes 19273// left, as this is the maximal number of bytes to be 19274// written ("\uxxxx\uxxxx\0") for one code point 19275if ( string_buffer . size () - bytes < 13 ) 19276{ 19277o -> write_characters ( string_buffer . data (), bytes ); 19278bytes = 0 ; 19279} 19280 19281bytes_after_last_accept = bytes ; 19282} 19283 19284undumped_chars = 0 ; 19285 19286// continue processing the string 19287state = UTF8_ACCEPT ; 19288break ; 19289} 19290 19291default : // LCOV_EXCL_LINE 19292JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 19293} 19294break ; 19295} 19296 19297default : // decode found yet incomplete multi-byte code point 19298{ 19299if (! ensure_ascii ) 19300{ 19301// code point will not be escaped - copy byte to buffer 19302string_buffer [ bytes ++] = s [ i ]; 19303} 19304++ undumped_chars ; 19305break ; 19306} 19307} 19308} 19309 19310// we finished processing the string 19311if ( JSON_HEDLEY_LIKELY ( state == UTF8_ACCEPT )) 19312{ 19313// write buffer 19314if ( bytes > 0 ) 19315{ 19316o -> write_characters ( string_buffer . data (), bytes ); 19317} 19318} 19319else 19320{ 19321// we finish reading, but do not accept: string was incomplete 19322switch ( error_handler ) 19323{ 19324case error_handler_t:: strict : 19325{ 19326JSON_THROW (type_error:: create ( 316 , concat ( "incomplete UTF-8 string; last byte: 0x" , hex_bytes ( static_cast <std:: uint8_t >( s . back () | 0 ))), nullptr )); 19327} 19328 19329case error_handler_t:: ignore : 19330{ 19331// write all accepted bytes 19332o -> write_characters ( string_buffer . data (), bytes_after_last_accept ); 19333break ; 19334} 19335 19336case error_handler_t:: replace : 19337{ 19338// write all accepted bytes 19339o -> write_characters ( string_buffer . data (), bytes_after_last_accept ); 19340// add a replacement character 19341if ( ensure_ascii ) 19342{ 19343o -> write_characters ( "\\ufffd" , 6 ); 19344} 19345else 19346{ 19347o -> write_characters ( "\xEF\xBF\xBD" , 3 ); 19348} 19349break ; 19350} 19351 19352default : // LCOV_EXCL_LINE 19353JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 19354} 19355} 19356} 19357 19358private : 19359/*! 19360@brief count digits 19361 19362Count the number of decimal (base 10) digits for an input unsigned integer. 19363 19364@param[in] x unsigned integer number to count its digits 19365@return number of decimal digits 19366*/ 19367unsigned int count_digits ( number_unsigned_t x ) noexcept 19368{ 19369unsigned int n_digits = 1 ; 19370for (;;) 19371{ 19372if ( x < 10 ) 19373{ 19374return n_digits ; 19375} 19376if ( x < 100 ) 19377{ 19378return n_digits + 1 ; 19379} 19380if ( x < 1000 ) 19381{ 19382return n_digits + 2 ; 19383} 19384if ( x < 10000 ) 19385{ 19386return n_digits + 3 ; 19387} 19388x = x / 10000u ; 19389n_digits += 4 ; 19390} 19391} 19392 19393/*! 19394* @brief convert a byte to a uppercase hex representation 19395* @param[in] byte byte to represent 19396* @return representation ("00".."FF") 19397*/ 19398static std:: string hex_bytes (std:: uint8_t byte ) 19399{ 19400std:: string result = "FF" ; 19401constexpr const char * nibble_to_hex = "0123456789ABCDEF" ; 19402result [ 0 ] = nibble_to_hex [ byte / 16 ]; 19403result [ 1 ] = nibble_to_hex [ byte % 16 ]; 19404return result ; 19405} 19406 19407// templates to avoid warnings about useless casts 19408template < typename NumberType , enable_if_t <std:: is_signed < NumberType >:: value , int > = 0 > 19409bool is_negative_number ( NumberType x ) 19410{ 19411return x < 0 ; 19412} 19413 19414template < typename NumberType , enable_if_t <std:: is_unsigned < NumberType >:: value , int > = 0 > 19415bool is_negative_number ( NumberType /*unused*/ ) 19416{ 19417return false; 19418} 19419 19420/*! 19421@brief dump an integer 19422 19423Dump a given integer to output stream @a o. Works internally with 19424@a number_buffer. 19425 19426@param[in] x integer number (signed or unsigned) to dump 19427@tparam NumberType either @a number_integer_t or @a number_unsigned_t 19428*/ 19429template < typename NumberType , detail:: enable_if_t < 19430std:: is_integral < NumberType >:: value || 19431std:: is_same < NumberType , number_unsigned_t >:: value || 19432std:: is_same < NumberType , number_integer_t >:: value || 19433std:: is_same < NumberType , binary_char_t >:: value , 19434int > = 0 > 19435void dump_integer ( NumberType x ) 19436{ 19437static constexpr std:: array <std:: array < char , 2 >, 100 > digits_to_99 19438{ 19439{ 19440{{ '0' , '0' }}, {{ '0' , '1' }}, {{ '0' , '2' }}, {{ '0' , '3' }}, {{ '0' , '4' }}, {{ '0' , '5' }}, {{ '0' , '6' }}, {{ '0' , '7' }}, {{ '0' , '8' }}, {{ '0' , '9' }}, 19441{{ '1' , '0' }}, {{ '1' , '1' }}, {{ '1' , '2' }}, {{ '1' , '3' }}, {{ '1' , '4' }}, {{ '1' , '5' }}, {{ '1' , '6' }}, {{ '1' , '7' }}, {{ '1' , '8' }}, {{ '1' , '9' }}, 19442{{ '2' , '0' }}, {{ '2' , '1' }}, {{ '2' , '2' }}, {{ '2' , '3' }}, {{ '2' , '4' }}, {{ '2' , '5' }}, {{ '2' , '6' }}, {{ '2' , '7' }}, {{ '2' , '8' }}, {{ '2' , '9' }}, 19443{{ '3' , '0' }}, {{ '3' , '1' }}, {{ '3' , '2' }}, {{ '3' , '3' }}, {{ '3' , '4' }}, {{ '3' , '5' }}, {{ '3' , '6' }}, {{ '3' , '7' }}, {{ '3' , '8' }}, {{ '3' , '9' }}, 19444{{ '4' , '0' }}, {{ '4' , '1' }}, {{ '4' , '2' }}, {{ '4' , '3' }}, {{ '4' , '4' }}, {{ '4' , '5' }}, {{ '4' , '6' }}, {{ '4' , '7' }}, {{ '4' , '8' }}, {{ '4' , '9' }}, 19445{{ '5' , '0' }}, {{ '5' , '1' }}, {{ '5' , '2' }}, {{ '5' , '3' }}, {{ '5' , '4' }}, {{ '5' , '5' }}, {{ '5' , '6' }}, {{ '5' , '7' }}, {{ '5' , '8' }}, {{ '5' , '9' }}, 19446{{ '6' , '0' }}, {{ '6' , '1' }}, {{ '6' , '2' }}, {{ '6' , '3' }}, {{ '6' , '4' }}, {{ '6' , '5' }}, {{ '6' , '6' }}, {{ '6' , '7' }}, {{ '6' , '8' }}, {{ '6' , '9' }}, 19447{{ '7' , '0' }}, {{ '7' , '1' }}, {{ '7' , '2' }}, {{ '7' , '3' }}, {{ '7' , '4' }}, {{ '7' , '5' }}, {{ '7' , '6' }}, {{ '7' , '7' }}, {{ '7' , '8' }}, {{ '7' , '9' }}, 19448{{ '8' , '0' }}, {{ '8' , '1' }}, {{ '8' , '2' }}, {{ '8' , '3' }}, {{ '8' , '4' }}, {{ '8' , '5' }}, {{ '8' , '6' }}, {{ '8' , '7' }}, {{ '8' , '8' }}, {{ '8' , '9' }}, 19449{{ '9' , '0' }}, {{ '9' , '1' }}, {{ '9' , '2' }}, {{ '9' , '3' }}, {{ '9' , '4' }}, {{ '9' , '5' }}, {{ '9' , '6' }}, {{ '9' , '7' }}, {{ '9' , '8' }}, {{ '9' , '9' }}, 19450} 19451}; 19452 19453// special case for "0" 19454if ( x == 0 ) 19455{ 19456o -> write_character ( '0' ); 19457return ; 19458} 19459 19460// use a pointer to fill the buffer 19461auto buffer_ptr = number_buffer . begin (); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) 19462 19463number_unsigned_t abs_value ; 19464 19465unsigned int n_chars {}; 19466 19467if ( is_negative_number ( x )) 19468{ 19469* buffer_ptr = '-' ; 19470abs_value = remove_sign ( static_cast < number_integer_t >( x )); 19471 19472// account one more byte for the minus sign 19473n_chars = 1 + count_digits ( abs_value ); 19474} 19475else 19476{ 19477abs_value = static_cast < number_unsigned_t >( x ); 19478n_chars = count_digits ( abs_value ); 19479} 19480 19481// spare 1 byte for '\0' 19482JSON_ASSERT ( n_chars < number_buffer . size () - 1 ); 19483 19484// jump to the end to generate the string from backward, 19485// so we later avoid reversing the result 19486buffer_ptr += n_chars ; 19487 19488// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu 19489// See: https://www.youtube.com/watch?v=o4-CwDo2zpg 19490while ( abs_value >= 100 ) 19491{ 19492const auto digits_index = static_cast < unsigned >(( abs_value % 100 )); 19493abs_value /= 100 ; 19494*(-- buffer_ptr ) = digits_to_99 [ digits_index ][ 1 ]; 19495*(-- buffer_ptr ) = digits_to_99 [ digits_index ][ 0 ]; 19496} 19497 19498if ( abs_value >= 10 ) 19499{ 19500const auto digits_index = static_cast < unsigned >( abs_value ); 19501*(-- buffer_ptr ) = digits_to_99 [ digits_index ][ 1 ]; 19502*(-- buffer_ptr ) = digits_to_99 [ digits_index ][ 0 ]; 19503} 19504else 19505{ 19506*(-- buffer_ptr ) = static_cast < char >( '0' + abs_value ); 19507} 19508 19509o -> write_characters ( number_buffer . data (), n_chars ); 19510} 19511 19512/*! 19513@brief dump a floating-point number 19514 19515Dump a given floating-point number to output stream @a o. Works internally 19516with @a number_buffer. 19517 19518@param[in] x floating-point number to dump 19519*/ 19520void dump_float ( number_float_t x ) 19521{ 19522// NaN / inf 19523if (!std:: isfinite ( x )) 19524{ 19525o -> write_characters ( "null" , 4 ); 19526return ; 19527} 19528 19529// If number_float_t is an IEEE-754 single or double precision number, 19530// use the Grisu2 algorithm to produce short numbers which are 19531// guaranteed to round-trip, using strtof and strtod, resp. 19532// 19533// NB: The test below works if <long double> == <double>. 19534static constexpr bool is_ieee_single_or_double 19535= (std:: numeric_limits < number_float_t >:: is_iec559 && std:: numeric_limits < number_float_t >:: digits == 24 && std:: numeric_limits < number_float_t >:: max_exponent == 128 ) || 19536(std:: numeric_limits < number_float_t >:: is_iec559 && std:: numeric_limits < number_float_t >:: digits == 53 && std:: numeric_limits < number_float_t >:: max_exponent == 1024 ); 19537 19538dump_float ( x , std:: integral_constant < bool , is_ieee_single_or_double >()); 19539} 19540 19541void dump_float ( number_float_t x , std:: true_type /*is_ieee_single_or_double*/ ) 19542{ 19543auto * begin = number_buffer . data (); 19544auto * end = ::nlohmann::detail:: to_chars ( begin , begin + number_buffer . size (), x ); 19545 19546o -> write_characters ( begin , static_cast < size_t >( end - begin )); 19547} 19548 19549void dump_float ( number_float_t x , std:: false_type /*is_ieee_single_or_double*/ ) 19550{ 19551// get number of digits for a float -> text -> float round-trip 19552static constexpr auto d = std:: numeric_limits < number_float_t >:: max_digits10 ; 19553 19554// the actual conversion 19555// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 19556std:: ptrdiff_t len = (std:: snprintf )( number_buffer . data (), number_buffer . size (), "%.*g" , d , x ); 19557 19558// negative value indicates an error 19559JSON_ASSERT ( len > 0 ); 19560// check if buffer was large enough 19561JSON_ASSERT ( static_cast <std:: size_t >( len ) < number_buffer . size ()); 19562 19563// erase thousands separator 19564if ( thousands_sep != '\0' ) 19565{ 19566// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 19567const auto end = std:: remove ( number_buffer . begin (), number_buffer . begin () + len , thousands_sep ); 19568std:: fill ( end , number_buffer . end (), '\0' ); 19569JSON_ASSERT (( end - number_buffer . begin ()) <= len ); 19570len = ( end - number_buffer . begin ()); 19571} 19572 19573// convert decimal point to '.' 19574if ( decimal_point != '\0' && decimal_point != '.' ) 19575{ 19576// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 19577const auto dec_pos = std:: find ( number_buffer . begin (), number_buffer . end (), decimal_point ); 19578if ( dec_pos != number_buffer . end ()) 19579{ 19580* dec_pos = '.' ; 19581} 19582} 19583 19584o -> write_characters ( number_buffer . data (), static_cast <std:: size_t >( len )); 19585 19586// determine if we need to append ".0" 19587const bool value_is_int_like = 19588std:: none_of ( number_buffer . begin (), number_buffer . begin () + len + 1 , 19589[]( char c ) 19590{ 19591return c == '.' || c == 'e' ; 19592}); 19593 19594if ( value_is_int_like ) 19595{ 19596o -> write_characters ( ".0" , 2 ); 19597} 19598} 19599 19600/*! 19601@brief check whether a string is UTF-8 encoded 19602 19603The function checks each byte of a string whether it is UTF-8 encoded. The 19604result of the check is stored in the @a state parameter. The function must 19605be called initially with state 0 (accept). State 1 means the string must 19606be rejected, because the current byte is not allowed. If the string is 19607completely processed, but the state is non-zero, the string ended 19608prematurely; that is, the last byte indicated more bytes should have 19609followed. 19610 19611@param[in,out] state the state of the decoding 19612@param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) 19613@param[in] byte next byte to decode 19614@return new state 19615 19616@note The function has been edited: a std::array is used. 19617 19618@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> 19619@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 19620*/ 19621static std:: uint8_t decode (std:: uint8_t & state , std:: uint32_t & codep , const std:: uint8_t byte ) noexcept 19622{ 19623static const std:: array <std:: uint8_t , 400 > utf8d = 19624{ 19625{ 196260 , 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 , 0 , 0 , // 00..1F 196270 , 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 , 0 , 0 , // 20..3F 196280 , 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 , 0 , 0 , // 40..5F 196290 , 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 , 0 , 0 , // 60..7F 196301 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , // 80..9F 196317 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , // A0..BF 196328 , 8 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , // C0..DF 196330xA , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x4 , 0x3 , 0x3 , // E0..EF 196340xB , 0x6 , 0x6 , 0x6 , 0x5 , 0x8 , 0x8 , 0x8 , 0x8 , 0x8 , 0x8 , 0x8 , 0x8 , 0x8 , 0x8 , 0x8 , // F0..FF 196350x0 , 0x1 , 0x2 , 0x3 , 0x5 , 0x8 , 0x7 , 0x1 , 0x1 , 0x1 , 0x4 , 0x6 , 0x1 , 0x1 , 0x1 , 0x1 , // s0..s0 196361 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , // s1..s2 196371 , 2 , 1 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , // s3..s4 196381 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 3 , 1 , 3 , 1 , 1 , 1 , 1 , 1 , 1 , // s5..s6 196391 , 3 , 1 , 1 , 1 , 1 , 1 , 3 , 1 , 3 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 3 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 // s7..s8 19640} 19641}; 19642 19643JSON_ASSERT ( byte < utf8d . size ()); 19644const std:: uint8_t type = utf8d [ byte ]; 19645 19646codep = ( state != UTF8_ACCEPT ) 19647? ( byte & 0x3fu ) | ( codep << 6u ) 19648: ( 0xFFu >> type ) & ( byte ); 19649 19650const std:: size_t index = 256u + ( static_cast < size_t >( state ) * 16u ) + static_cast < size_t >( type ); 19651JSON_ASSERT ( index < utf8d . size ()); 19652state = utf8d [ index ]; 19653return state ; 19654} 19655 19656/* 19657* Overload to make the compiler happy while it is instantiating 19658* dump_integer for number_unsigned_t. 19659* Must never be called. 19660*/ 19661number_unsigned_t remove_sign ( number_unsigned_t x ) 19662{ 19663JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 19664return x ; // LCOV_EXCL_LINE 19665} 19666 19667/* 19668* Helper function for dump_integer 19669* 19670* This function takes a negative signed integer and returns its absolute 19671* value as unsigned integer. The plus/minus shuffling is necessary as we can 19672* not directly remove the sign of an arbitrary signed integer as the 19673* absolute values of INT_MIN and INT_MAX are usually not the same. See 19674* #1708 for details. 19675*/ 19676number_unsigned_t remove_sign ( number_integer_t x ) noexcept 19677{ 19678JSON_ASSERT ( x < 0 && x < (std:: numeric_limits < number_integer_t >:: max )()); // NOLINT(misc-redundant-expression) 19679return static_cast < number_unsigned_t >(-( x + 1 )) + 1 ; 19680} 19681 19682private : 19683/// the output of the serializer 19684output_adapter_t < char > o = nullptr ; 19685 19686/// a (hopefully) large enough character buffer 19687std:: array < char , 64 > number_buffer {{}}; 19688 19689/// the locale 19690const std:: lconv * loc = nullptr ; 19691/// the locale's thousand separator character 19692const char thousands_sep = '\0' ; 19693/// the locale's decimal point character 19694const char decimal_point = '\0' ; 19695 19696/// string buffer 19697std:: array < char , 512 > string_buffer {{}}; 19698 19699/// the indentation character 19700const char indent_char ; 19701/// the indentation string 19702string_t indent_string ; 19703 19704/// error_handler how to react on decoding errors 19705const error_handler_t error_handler ; 19706}; 19707 19708} // namespace detail 19709NLOHMANN_JSON_NAMESPACE_END 19710 19711// #include <nlohmann/detail/value_t.hpp> 19712 19713// #include <nlohmann/json_fwd.hpp> 19714 19715// #include <nlohmann/ordered_map.hpp> 19716// __ _____ _____ _____ 19717// __| | __| | | | JSON for Modern C++ 19718// | | |__ | | | | | | version 3.12.0 19719// |_____|_____|_____|_|___| https://github.com/nlohmann/json 19720// 19721// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 19722// SPDX-License-Identifier: MIT 19723 19724 19725 19726#include <functional> // equal_to, less 19727#include <initializer_list> // initializer_list 19728#include <iterator> // input_iterator_tag, iterator_traits 19729#include <memory> // allocator 19730#include <stdexcept> // for out_of_range 19731#include <type_traits> // enable_if, is_convertible 19732#include <utility> // pair 19733#include <vector> // vector 19734 19735// #include <nlohmann/detail/macro_scope.hpp> 19736 19737// #include <nlohmann/detail/meta/type_traits.hpp> 19738 19739 19740NLOHMANN_JSON_NAMESPACE_BEGIN 19741 19742/// ordered_map: a minimal map-like container that preserves insertion order 19743/// for use within nlohmann::basic_json<ordered_map> 19744template < class Key , class T , class IgnoredLess = std :: less < Key >, 19745class Allocator = std:: allocator <std:: pair < const Key , T >>> 19746struct ordered_map : std :: vector <std:: pair < const Key , T >, Allocator > 19747{ 19748using key_type = Key ; 19749using mapped_type = T ; 19750using Container = std:: vector <std:: pair < const Key , T >, Allocator >; 19751using iterator = typename Container :: iterator ; 19752using const_iterator = typename Container :: const_iterator ; 19753using size_type = typename Container :: size_type ; 19754using value_type = typename Container :: value_type ; 19755#ifdef JSON_HAS_CPP_14 19756using key_compare = std:: equal_to <>; 19757#else 19758using key_compare = std:: equal_to < Key >; 19759#endif 19760 19761// Explicit constructors instead of `using Container::Container` 19762// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) 19763ordered_map () noexcept ( noexcept ( Container ())) : Container {} {} 19764explicit ordered_map ( const Allocator & alloc ) noexcept ( noexcept ( Container ( alloc ))) : Container { alloc } {} 19765template < class It > 19766ordered_map ( It first , It last , const Allocator & alloc = Allocator ()) 19767: Container { first , last , alloc } {} 19768ordered_map (std:: initializer_list < value_type > init , const Allocator & alloc = Allocator () ) 19769: Container { init , alloc } {} 19770 19771std:: pair < iterator , bool > emplace ( const key_type & key , T && t ) 19772{ 19773for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19774{ 19775if ( m_compare ( it -> first , key )) 19776{ 19777return { it , false}; 19778} 19779} 19780Container :: emplace_back ( key , std:: forward < T >( t )); 19781return {std:: prev ( this -> end ()), true}; 19782} 19783 19784template < class KeyType , detail:: enable_if_t < 19785detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 19786std:: pair < iterator , bool > emplace ( KeyType && key , T && t ) 19787{ 19788for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19789{ 19790if ( m_compare ( it -> first , key )) 19791{ 19792return { it , false}; 19793} 19794} 19795Container :: emplace_back (std:: forward < KeyType >( key ), std:: forward < T >( t )); 19796return {std:: prev ( this -> end ()), true}; 19797} 19798 19799T & operator[]( const key_type & key ) 19800{ 19801return emplace ( key , T {}). first -> second ; 19802} 19803 19804template < class KeyType , detail:: enable_if_t < 19805detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 19806T & operator[]( KeyType && key ) 19807{ 19808return emplace (std:: forward < KeyType >( key ), T {}). first -> second ; 19809} 19810 19811const T & operator[]( const key_type & key ) const 19812{ 19813return at ( key ); 19814} 19815 19816template < class KeyType , detail:: enable_if_t < 19817detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 19818const T & operator[]( KeyType && key ) const 19819{ 19820return at (std:: forward < KeyType >( key )); 19821} 19822 19823T & at ( const key_type & key ) 19824{ 19825for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19826{ 19827if ( m_compare ( it -> first , key )) 19828{ 19829return it -> second ; 19830} 19831} 19832 19833JSON_THROW (std:: out_of_range ( "key not found" )); 19834} 19835 19836template < class KeyType , detail:: enable_if_t < 19837detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 19838T & at ( KeyType && key ) // NOLINT(cppcoreguidelines-missing-std-forward) 19839{ 19840for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19841{ 19842if ( m_compare ( it -> first , key )) 19843{ 19844return it -> second ; 19845} 19846} 19847 19848JSON_THROW (std:: out_of_range ( "key not found" )); 19849} 19850 19851const T & at ( const key_type & key ) const 19852{ 19853for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19854{ 19855if ( m_compare ( it -> first , key )) 19856{ 19857return it -> second ; 19858} 19859} 19860 19861JSON_THROW (std:: out_of_range ( "key not found" )); 19862} 19863 19864template < class KeyType , detail:: enable_if_t < 19865detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 19866const T & at ( KeyType && key ) const // NOLINT(cppcoreguidelines-missing-std-forward) 19867{ 19868for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19869{ 19870if ( m_compare ( it -> first , key )) 19871{ 19872return it -> second ; 19873} 19874} 19875 19876JSON_THROW (std:: out_of_range ( "key not found" )); 19877} 19878 19879size_type erase ( const key_type & key ) 19880{ 19881for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19882{ 19883if ( m_compare ( it -> first , key )) 19884{ 19885// Since we cannot move const Keys, re-construct them in place 19886for ( auto next = it ; ++ next != this -> end (); ++ it ) 19887{ 19888it ->~ value_type (); // Destroy but keep allocation 19889new (&* it ) value_type {std:: move (* next )}; 19890} 19891Container :: pop_back (); 19892return 1 ; 19893} 19894} 19895return 0 ; 19896} 19897 19898template < class KeyType , detail:: enable_if_t < 19899detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 19900size_type erase ( KeyType && key ) // NOLINT(cppcoreguidelines-missing-std-forward) 19901{ 19902for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19903{ 19904if ( m_compare ( it -> first , key )) 19905{ 19906// Since we cannot move const Keys, re-construct them in place 19907for ( auto next = it ; ++ next != this -> end (); ++ it ) 19908{ 19909it ->~ value_type (); // Destroy but keep allocation 19910new (&* it ) value_type {std:: move (* next )}; 19911} 19912Container :: pop_back (); 19913return 1 ; 19914} 19915} 19916return 0 ; 19917} 19918 19919iterator erase ( iterator pos ) 19920{ 19921return erase ( pos , std:: next ( pos )); 19922} 19923 19924iterator erase ( iterator first , iterator last ) 19925{ 19926if ( first == last ) 19927{ 19928return first ; 19929} 19930 19931const auto elements_affected = std:: distance ( first , last ); 19932const auto offset = std:: distance ( Container :: begin (), first ); 19933 19934// This is the start situation. We need to delete elements_affected 19935// elements (3 in this example: e, f, g), and need to return an 19936// iterator past the last deleted element (h in this example). 19937// Note that offset is the distance from the start of the vector 19938// to first. We will need this later. 19939 19940// [ a, b, c, d, e, f, g, h, i, j ] 19941// ^ ^ 19942// first last 19943 19944// Since we cannot move const Keys, we re-construct them in place. 19945// We start at first and re-construct (viz. copy) the elements from 19946// the back of the vector. Example for first iteration: 19947 19948// ,--------. 19949// v | destroy e and re-construct with h 19950// [ a, b, c, d, e, f, g, h, i, j ] 19951// ^ ^ 19952// it it + elements_affected 19953 19954for ( auto it = first ; std:: next ( it , elements_affected ) != Container :: end (); ++ it ) 19955{ 19956it ->~ value_type (); // destroy but keep allocation 19957new (&* it ) value_type {std:: move (*std:: next ( it , elements_affected ))}; // "move" next element to it 19958} 19959 19960// [ a, b, c, d, h, i, j, h, i, j ] 19961// ^ ^ 19962// first last 19963 19964// remove the unneeded elements at the end of the vector 19965Container :: resize ( this -> size () - static_cast < size_type >( elements_affected )); 19966 19967// [ a, b, c, d, h, i, j ] 19968// ^ ^ 19969// first last 19970 19971// first is now pointing past the last deleted element, but we cannot 19972// use this iterator, because it may have been invalidated by the 19973// resize call. Instead, we can return begin() + offset. 19974return Container :: begin () + offset ; 19975} 19976 19977size_type count ( const key_type & key ) const 19978{ 19979for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19980{ 19981if ( m_compare ( it -> first , key )) 19982{ 19983return 1 ; 19984} 19985} 19986return 0 ; 19987} 19988 19989template < class KeyType , detail:: enable_if_t < 19990detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 19991size_type count ( KeyType && key ) const // NOLINT(cppcoreguidelines-missing-std-forward) 19992{ 19993for ( auto it = this -> begin (); it != this -> end (); ++ it ) 19994{ 19995if ( m_compare ( it -> first , key )) 19996{ 19997return 1 ; 19998} 19999} 20000return 0 ; 20001} 20002 20003iterator find ( const key_type & key ) 20004{ 20005for ( auto it = this -> begin (); it != this -> end (); ++ it ) 20006{ 20007if ( m_compare ( it -> first , key )) 20008{ 20009return it ; 20010} 20011} 20012return Container :: end (); 20013} 20014 20015template < class KeyType , detail:: enable_if_t < 20016detail:: is_usable_as_key_type < key_compare , key_type , KeyType >:: value , int > = 0 > 20017iterator find ( KeyType && key ) // NOLINT(cppcoreguidelines-missing-std-forward) 20018{ 20019for ( auto it = this -> begin (); it != this -> end (); ++ it ) 20020{ 20021if ( m_compare ( it -> first , key )) 20022{ 20023return it ; 20024} 20025} 20026return Container :: end (); 20027} 20028 20029const_iterator find ( const key_type & key ) const 20030{ 20031for ( auto it = this -> begin (); it != this -> end (); ++ it ) 20032{ 20033if ( m_compare ( it -> first , key )) 20034{ 20035return it ; 20036} 20037} 20038return Container :: end (); 20039} 20040 20041std:: pair < iterator , bool > insert ( value_type && value ) 20042{ 20043return emplace ( value . first , std:: move ( value . second )); 20044} 20045 20046std:: pair < iterator , bool > insert ( const value_type & value ) 20047{ 20048for ( auto it = this -> begin (); it != this -> end (); ++ it ) 20049{ 20050if ( m_compare ( it -> first , value . first )) 20051{ 20052return { it , false}; 20053} 20054} 20055Container :: push_back ( value ); 20056return {-- this -> end (), true}; 20057} 20058 20059template < typename InputIt > 20060using require_input_iter = typename std:: enable_if <std:: is_convertible < typename std:: iterator_traits < InputIt >:: iterator_category , 20061std:: input_iterator_tag >:: value >:: type ; 20062 20063template < typename InputIt , typename = require_input_iter < InputIt >> 20064void insert ( InputIt first , InputIt last ) 20065{ 20066for ( auto it = first ; it != last ; ++ it ) 20067{ 20068insert (* it ); 20069} 20070} 20071 20072private : 20073JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare (); 20074}; 20075 20076NLOHMANN_JSON_NAMESPACE_END 20077 20078 20079#if defined( JSON_HAS_CPP_17 ) 20080#if JSON_HAS_STATIC_RTTI 20081#include <any> 20082#endif 20083#include <string_view> 20084#endif 20085 20086/*! 20087@brief namespace for Niels Lohmann 20088@see https://github.com/nlohmann 20089@since version 1.0.0 20090*/ 20091NLOHMANN_JSON_NAMESPACE_BEGIN 20092 20093/*! 20094@brief a class to store JSON values 20095 20096@internal 20097@invariant The member variables @a m_value and @a m_type have the following 20098relationship: 20099- If `m_type == value_t::object`, then `m_value.object != nullptr`. 20100- If `m_type == value_t::array`, then `m_value.array != nullptr`. 20101- If `m_type == value_t::string`, then `m_value.string != nullptr`. 20102The invariants are checked by member function assert_invariant(). 20103 20104@note ObjectType trick from https://stackoverflow.com/a/9860911 20105@endinternal 20106 20107@since version 1.0.0 20108 20109@nosubgrouping 20110*/ 20111NLOHMANN_BASIC_JSON_TPL_DECLARATION 20112class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 20113: public ::nlohmann::detail:: json_base_class < CustomBaseClass > 20114{ 20115private : 20116template <detail:: value_t > friend struct detail:: external_constructor ; 20117 20118template < typename > 20119friend class ::nlohmann:: json_pointer ; 20120// can be restored when json_pointer backwards compatibility is removed 20121// friend ::nlohmann::json_pointer<StringType>; 20122 20123template < typename BasicJsonType , typename InputType > 20124friend class ::nlohmann::detail:: parser ; 20125friend ::nlohmann::detail:: serializer < basic_json >; 20126template < typename BasicJsonType > 20127friend class ::nlohmann::detail:: iter_impl ; 20128template < typename BasicJsonType , typename CharType > 20129friend class ::nlohmann::detail:: binary_writer ; 20130template < typename BasicJsonType , typename InputType , typename SAX > 20131friend class ::nlohmann::detail:: binary_reader ; 20132template < typename BasicJsonType , typename InputAdapterType > 20133friend class ::nlohmann::detail:: json_sax_dom_parser ; 20134template < typename BasicJsonType , typename InputAdapterType > 20135friend class ::nlohmann::detail:: json_sax_dom_callback_parser ; 20136friend class ::nlohmann::detail:: exception ; 20137 20138/// workaround type for MSVC 20139using basic_json_t = NLOHMANN_BASIC_JSON_TPL ; 20140using json_base_class_t = ::nlohmann::detail:: json_base_class < CustomBaseClass >; 20141 20142JSON_PRIVATE_UNLESS_TESTED : 20143// convenience aliases for types residing in namespace detail; 20144using lexer = ::nlohmann::detail:: lexer_base < basic_json >; 20145 20146template < typename InputAdapterType > 20147static ::nlohmann::detail:: parser < basic_json , InputAdapterType > parser ( 20148InputAdapterType adapter , 20149detail:: parser_callback_t < basic_json > cb = nullptr , 20150const bool allow_exceptions = true, 20151const bool ignore_comments = false 20152) 20153{ 20154return ::nlohmann::detail:: parser < basic_json , InputAdapterType >(std:: move ( adapter ), 20155std:: move ( cb ), allow_exceptions , ignore_comments ); 20156} 20157 20158private : 20159using primitive_iterator_t = ::nlohmann::detail:: primitive_iterator_t ; 20160template < typename BasicJsonType > 20161using internal_iterator = ::nlohmann::detail:: internal_iterator < BasicJsonType >; 20162template < typename BasicJsonType > 20163using iter_impl = ::nlohmann::detail:: iter_impl < BasicJsonType >; 20164template < typename Iterator > 20165using iteration_proxy = ::nlohmann::detail:: iteration_proxy < Iterator >; 20166template < typename Base > using json_reverse_iterator = ::nlohmann::detail:: json_reverse_iterator < Base >; 20167 20168template < typename CharType > 20169using output_adapter_t = ::nlohmann::detail:: output_adapter_t < CharType >; 20170 20171template < typename InputType > 20172using binary_reader = ::nlohmann::detail:: binary_reader < basic_json , InputType >; 20173template < typename CharType > using binary_writer = ::nlohmann::detail:: binary_writer < basic_json , CharType >; 20174 20175JSON_PRIVATE_UNLESS_TESTED : 20176using serializer = ::nlohmann::detail:: serializer < basic_json >; 20177 20178public : 20179using value_t = detail:: value_t ; 20180/// JSON Pointer, see @ref nlohmann::json_pointer 20181using json_pointer = ::nlohmann:: json_pointer < StringType >; 20182template < typename T , typename SFINAE > 20183using json_serializer = JSONSerializer < T , SFINAE >; 20184/// how to treat decoding errors 20185using error_handler_t = detail:: error_handler_t ; 20186/// how to treat CBOR tags 20187using cbor_tag_handler_t = detail:: cbor_tag_handler_t ; 20188/// how to encode BJData 20189using bjdata_version_t = detail:: bjdata_version_t ; 20190/// helper type for initializer lists of basic_json values 20191using initializer_list_t = std:: initializer_list <detail:: json_ref < basic_json >>; 20192 20193using input_format_t = detail:: input_format_t ; 20194/// SAX interface type, see @ref nlohmann::json_sax 20195using json_sax_t = json_sax < basic_json >; 20196 20197//////////////// 20198// exceptions // 20199//////////////// 20200 20201/// @name exceptions 20202/// Classes to implement user-defined exceptions. 20203/// @{ 20204 20205using exception = detail:: exception ; 20206using parse_error = detail:: parse_error ; 20207using invalid_iterator = detail:: invalid_iterator ; 20208using type_error = detail:: type_error ; 20209using out_of_range = detail:: out_of_range ; 20210using other_error = detail:: other_error ; 20211 20212/// @} 20213 20214///////////////////// 20215// container types // 20216///////////////////// 20217 20218/// @name container types 20219/// The canonic container types to use @ref basic_json like any other STL 20220/// container. 20221/// @{ 20222 20223/// the type of elements in a basic_json container 20224using value_type = basic_json ; 20225 20226/// the type of an element reference 20227using reference = value_type &; 20228/// the type of an element const reference 20229using const_reference = const value_type &; 20230 20231/// a type to represent differences between iterators 20232using difference_type = std:: ptrdiff_t ; 20233/// a type to represent container sizes 20234using size_type = std:: size_t ; 20235 20236/// the allocator type 20237using allocator_type = AllocatorType < basic_json >; 20238 20239/// the type of an element pointer 20240using pointer = typename std:: allocator_traits < allocator_type >:: pointer ; 20241/// the type of an element const pointer 20242using const_pointer = typename std:: allocator_traits < allocator_type >:: const_pointer ; 20243 20244/// an iterator for a basic_json container 20245using iterator = iter_impl < basic_json >; 20246/// a const iterator for a basic_json container 20247using const_iterator = iter_impl < const basic_json >; 20248/// a reverse iterator for a basic_json container 20249using reverse_iterator = json_reverse_iterator < typename basic_json:: iterator >; 20250/// a const reverse iterator for a basic_json container 20251using const_reverse_iterator = json_reverse_iterator < typename basic_json:: const_iterator >; 20252 20253/// @} 20254 20255/// @brief returns the allocator associated with the container 20256/// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ 20257static allocator_type get_allocator () 20258{ 20259return allocator_type (); 20260} 20261 20262/// @brief returns version information on the library 20263/// @sa https://json.nlohmann.me/api/basic_json/meta/ 20264JSON_HEDLEY_WARN_UNUSED_RESULT 20265static basic_json meta () 20266{ 20267basic_json result ; 20268 20269result [ "copyright" ] = "(C) 2013-2025 Niels Lohmann" ; 20270result [ "name" ] = "JSON for Modern C++" ; 20271result [ "url" ] = "https://github.com/nlohmann/json" ; 20272result [ "version" ][ "string" ] = 20273detail:: concat (std:: to_string ( NLOHMANN_JSON_VERSION_MAJOR ), '.' , 20274std:: to_string ( NLOHMANN_JSON_VERSION_MINOR ), '.' , 20275std:: to_string ( NLOHMANN_JSON_VERSION_PATCH )); 20276result [ "version" ][ "major" ] = NLOHMANN_JSON_VERSION_MAJOR ; 20277result [ "version" ][ "minor" ] = NLOHMANN_JSON_VERSION_MINOR ; 20278result [ "version" ][ "patch" ] = NLOHMANN_JSON_VERSION_PATCH ; 20279 20280#ifdef _WIN32 20281result [ "platform" ] = "win32" ; 20282#elif defined __linux__ 20283result [ "platform" ] = "linux" ; 20284#elif defined __APPLE__ 20285result [ "platform" ] = "apple" ; 20286#elif defined __unix__ 20287result [ "platform" ] = "unix" ; 20288#else 20289result [ "platform" ] = "unknown" ; 20290#endif 20291 20292#if defined( __ICC ) || defined( __INTEL_COMPILER ) 20293result [ "compiler" ] = {{ "family" , "icc" }, { "version" , __INTEL_COMPILER }}; 20294#elif defined( __clang__ ) 20295result [ "compiler" ] = {{ "family" , "clang" }, { "version" , __clang_version__ }}; 20296#elif defined( __GNUC__ ) || defined( __GNUG__ ) 20297result [ "compiler" ] = {{ "family" , "gcc" }, { "version" , detail:: concat ( 20298std:: to_string ( __GNUC__ ), '.' , 20299std:: to_string ( __GNUC_MINOR__ ), '.' , 20300std:: to_string ( __GNUC_PATCHLEVEL__ )) 20301} 20302}; 20303#elif defined( __HP_cc ) || defined( __HP_aCC ) 20304result [ "compiler" ] = "hp" 20305#elif defined( __IBMCPP__ ) 20306result [ "compiler" ] = {{ "family" , "ilecpp" }, { "version" , __IBMCPP__ }}; 20307#elif defined( _MSC_VER ) 20308result [ "compiler" ] = {{ "family" , "msvc" }, { "version" , _MSC_VER }}; 20309#elif defined( __PGI ) 20310result [ "compiler" ] = {{ "family" , "pgcpp" }, { "version" , __PGI }}; 20311#elif defined( __SUNPRO_CC ) 20312result [ "compiler" ] = {{ "family" , "sunpro" }, { "version" , __SUNPRO_CC }}; 20313#else 20314result [ "compiler" ] = {{ "family" , "unknown" }, { "version" , "unknown" }}; 20315#endif 20316 20317#if defined( _MSVC_LANG ) 20318result [ "compiler" ][ "c++" ] = std:: to_string ( _MSVC_LANG ); 20319#elif defined( __cplusplus ) 20320result [ "compiler" ][ "c++" ] = std:: to_string ( __cplusplus ); 20321#else 20322result [ "compiler" ][ "c++" ] = "unknown" ; 20323#endif 20324return result ; 20325} 20326 20327/////////////////////////// 20328// JSON value data types // 20329/////////////////////////// 20330 20331/// @name JSON value data types 20332/// The data types to store a JSON value. These types are derived from 20333/// the template arguments passed to class @ref basic_json. 20334/// @{ 20335 20336/// @brief default object key comparator type 20337/// The actual object key comparator type (@ref object_comparator_t) may be 20338/// different. 20339/// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/ 20340#if defined( JSON_HAS_CPP_14 ) 20341// use of transparent comparator avoids unnecessary repeated construction of temporaries 20342// in functions involving lookup by key with types other than object_t::key_type (aka. StringType) 20343using default_object_comparator_t = std:: less <>; 20344#else 20345using default_object_comparator_t = std:: less < StringType >; 20346#endif 20347 20348/// @brief a type for an object 20349/// @sa https://json.nlohmann.me/api/basic_json/object_t/ 20350using object_t = ObjectType < StringType , 20351basic_json , 20352default_object_comparator_t , 20353AllocatorType <std:: pair < const StringType , 20354basic_json >>>; 20355 20356/// @brief a type for an array 20357/// @sa https://json.nlohmann.me/api/basic_json/array_t/ 20358using array_t = ArrayType < basic_json , AllocatorType < basic_json >>; 20359 20360/// @brief a type for a string 20361/// @sa https://json.nlohmann.me/api/basic_json/string_t/ 20362using string_t = StringType ; 20363 20364/// @brief a type for a boolean 20365/// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ 20366using boolean_t = BooleanType ; 20367 20368/// @brief a type for a number (integer) 20369/// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ 20370using number_integer_t = NumberIntegerType ; 20371 20372/// @brief a type for a number (unsigned) 20373/// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ 20374using number_unsigned_t = NumberUnsignedType ; 20375 20376/// @brief a type for a number (floating-point) 20377/// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ 20378using number_float_t = NumberFloatType ; 20379 20380/// @brief a type for a packed binary type 20381/// @sa https://json.nlohmann.me/api/basic_json/binary_t/ 20382using binary_t = nlohmann:: byte_container_with_subtype < BinaryType >; 20383 20384/// @brief object key comparator type 20385/// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ 20386using object_comparator_t = detail:: actual_object_comparator_t < basic_json >; 20387 20388/// @} 20389 20390private : 20391 20392/// helper for exception-safe object creation 20393template < typename T , typename ... Args > 20394JSON_HEDLEY_RETURNS_NON_NULL 20395static T * create ( Args && ... args ) 20396{ 20397AllocatorType < T > alloc ; 20398using AllocatorTraits = std:: allocator_traits < AllocatorType < T >>; 20399 20400auto deleter = [&]( T * obj ) 20401{ 20402AllocatorTraits :: deallocate ( alloc , obj , 1 ); 20403}; 20404std:: unique_ptr < T , decltype( deleter )> obj ( AllocatorTraits :: allocate ( alloc , 1 ), deleter ); 20405AllocatorTraits :: construct ( alloc , obj . get (), std:: forward < Args >( args )...); 20406JSON_ASSERT ( obj != nullptr ); 20407return obj . release (); 20408} 20409 20410//////////////////////// 20411// JSON value storage // 20412//////////////////////// 20413 20414JSON_PRIVATE_UNLESS_TESTED : 20415/*! 20416@brief a JSON value 20417 20418The actual storage for a JSON value of the @ref basic_json class. This 20419union combines the different storage types for the JSON value types 20420defined in @ref value_t. 20421 20422JSON type | value_t type | used type 20423--------- | --------------- | ------------------------ 20424object | object | pointer to @ref object_t 20425array | array | pointer to @ref array_t 20426string | string | pointer to @ref string_t 20427boolean | boolean | @ref boolean_t 20428number | number_integer | @ref number_integer_t 20429number | number_unsigned | @ref number_unsigned_t 20430number | number_float | @ref number_float_t 20431binary | binary | pointer to @ref binary_t 20432null | null | *no value is stored* 20433 20434@note Variable-length types (objects, arrays, and strings) are stored as 20435pointers. The size of the union should not exceed 64 bits if the default 20436value types are used. 20437 20438@since version 1.0.0 20439*/ 20440union json_value 20441{ 20442/// object (stored with pointer to save storage) 20443object_t * object ; 20444/// array (stored with pointer to save storage) 20445array_t * array ; 20446/// string (stored with pointer to save storage) 20447string_t * string ; 20448/// binary (stored with pointer to save storage) 20449binary_t * binary ; 20450/// boolean 20451boolean_t boolean ; 20452/// number (integer) 20453number_integer_t number_integer ; 20454/// number (unsigned integer) 20455number_unsigned_t number_unsigned ; 20456/// number (floating-point) 20457number_float_t number_float ; 20458 20459/// default constructor (for null values) 20460json_value () = default ; 20461/// constructor for booleans 20462json_value ( boolean_t v ) noexcept : boolean ( v ) {} 20463/// constructor for numbers (integer) 20464json_value ( number_integer_t v ) noexcept : number_integer ( v ) {} 20465/// constructor for numbers (unsigned) 20466json_value ( number_unsigned_t v ) noexcept : number_unsigned ( v ) {} 20467/// constructor for numbers (floating-point) 20468json_value ( number_float_t v ) noexcept : number_float ( v ) {} 20469/// constructor for empty values of a given type 20470json_value ( value_t t ) 20471{ 20472switch ( t ) 20473{ 20474case value_t:: object : 20475{ 20476object = create < object_t >(); 20477break ; 20478} 20479 20480case value_t:: array : 20481{ 20482array = create < array_t >(); 20483break ; 20484} 20485 20486case value_t:: string : 20487{ 20488string = create < string_t >( "" ); 20489break ; 20490} 20491 20492case value_t:: binary : 20493{ 20494binary = create < binary_t >(); 20495break ; 20496} 20497 20498case value_t:: boolean : 20499{ 20500boolean = static_cast < boolean_t >(false); 20501break ; 20502} 20503 20504case value_t:: number_integer : 20505{ 20506number_integer = static_cast < number_integer_t >( 0 ); 20507break ; 20508} 20509 20510case value_t:: number_unsigned : 20511{ 20512number_unsigned = static_cast < number_unsigned_t >( 0 ); 20513break ; 20514} 20515 20516case value_t:: number_float : 20517{ 20518number_float = static_cast < number_float_t >( 0.0 ); 20519break ; 20520} 20521 20522case value_t:: null : 20523{ 20524object = nullptr ; // silence warning, see #821 20525break ; 20526} 20527 20528case value_t:: discarded : 20529default : 20530{ 20531object = nullptr ; // silence warning, see #821 20532if ( JSON_HEDLEY_UNLIKELY ( t == value_t:: null )) 20533{ 20534JSON_THROW (other_error:: create ( 500 , "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0" , nullptr )); // LCOV_EXCL_LINE 20535} 20536break ; 20537} 20538} 20539} 20540 20541/// constructor for strings 20542json_value ( const string_t & value ) : string ( create < string_t >( value )) {} 20543 20544/// constructor for rvalue strings 20545json_value ( string_t && value ) : string ( create < string_t >(std:: move ( value ))) {} 20546 20547/// constructor for objects 20548json_value ( const object_t & value ) : object ( create < object_t >( value )) {} 20549 20550/// constructor for rvalue objects 20551json_value ( object_t && value ) : object ( create < object_t >(std:: move ( value ))) {} 20552 20553/// constructor for arrays 20554json_value ( const array_t & value ) : array ( create < array_t >( value )) {} 20555 20556/// constructor for rvalue arrays 20557json_value ( array_t && value ) : array ( create < array_t >(std:: move ( value ))) {} 20558 20559/// constructor for binary arrays 20560json_value ( const typename binary_t:: container_type & value ) : binary ( create < binary_t >( value )) {} 20561 20562/// constructor for rvalue binary arrays 20563json_value ( typename binary_t:: container_type && value ) : binary ( create < binary_t >(std:: move ( value ))) {} 20564 20565/// constructor for binary arrays (internal type) 20566json_value ( const binary_t & value ) : binary ( create < binary_t >( value )) {} 20567 20568/// constructor for rvalue binary arrays (internal type) 20569json_value ( binary_t && value ) : binary ( create < binary_t >(std:: move ( value ))) {} 20570 20571void destroy ( value_t t ) 20572{ 20573if ( 20574( t == value_t:: object && object == nullptr ) || 20575( t == value_t:: array && array == nullptr ) || 20576( t == value_t:: string && string == nullptr ) || 20577( t == value_t:: binary && binary == nullptr ) 20578) 20579{ 20580//not initialized (e.g. due to exception in the ctor) 20581return ; 20582} 20583if ( t == value_t:: array || t == value_t:: object ) 20584{ 20585// flatten the current json_value to a heap-allocated stack 20586std:: vector < basic_json > stack ; 20587 20588// move the top-level items to stack 20589if ( t == value_t:: array ) 20590{ 20591stack . reserve ( array -> size ()); 20592std:: move ( array -> begin (), array -> end (), std:: back_inserter ( stack )); 20593} 20594else 20595{ 20596stack . reserve ( object -> size ()); 20597for ( auto && it : * object ) 20598{ 20599stack . push_back (std:: move ( it . second )); 20600} 20601} 20602 20603while (! stack . empty ()) 20604{ 20605// move the last item to local variable to be processed 20606basic_json current_item (std:: move ( stack . back ())); 20607stack . pop_back (); 20608 20609// if current_item is array/object, move 20610// its children to the stack to be processed later 20611if ( current_item . is_array ()) 20612{ 20613std:: move ( current_item . m_data . m_value . array -> begin (), current_item . m_data . m_value . array -> end (), std:: back_inserter ( stack )); 20614 20615current_item . m_data . m_value . array -> clear (); 20616} 20617else if ( current_item . is_object ()) 20618{ 20619for ( auto && it : * current_item . m_data . m_value . object ) 20620{ 20621stack . push_back (std:: move ( it . second )); 20622} 20623 20624current_item . m_data . m_value . object -> clear (); 20625} 20626 20627// it's now safe that current_item get destructed 20628// since it doesn't have any children 20629} 20630} 20631 20632switch ( t ) 20633{ 20634case value_t:: object : 20635{ 20636AllocatorType < object_t > alloc ; 20637std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , object ); 20638std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , object , 1 ); 20639break ; 20640} 20641 20642case value_t:: array : 20643{ 20644AllocatorType < array_t > alloc ; 20645std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , array ); 20646std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , array , 1 ); 20647break ; 20648} 20649 20650case value_t:: string : 20651{ 20652AllocatorType < string_t > alloc ; 20653std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , string ); 20654std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , string , 1 ); 20655break ; 20656} 20657 20658case value_t:: binary : 20659{ 20660AllocatorType < binary_t > alloc ; 20661std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , binary ); 20662std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , binary , 1 ); 20663break ; 20664} 20665 20666case value_t:: null : 20667case value_t:: boolean : 20668case value_t:: number_integer : 20669case value_t:: number_unsigned : 20670case value_t:: number_float : 20671case value_t:: discarded : 20672default : 20673{ 20674break ; 20675} 20676} 20677} 20678} ; 20679 20680private : 20681/*! 20682@brief checks the class invariants 20683 20684This function asserts the class invariants. It needs to be called at the 20685end of every constructor to make sure that created objects respect the 20686invariant. Furthermore, it has to be called each time the type of a JSON 20687value is changed, because the invariant expresses a relationship between 20688@a m_type and @a m_value. 20689 20690Furthermore, the parent relation is checked for arrays and objects: If 20691@a check_parents true and the value is an array or object, then the 20692container's elements must have the current value as parent. 20693 20694@param[in] check_parents whether the parent relation should be checked. 20695The value is true by default and should only be set to false 20696during destruction of objects when the invariant does not 20697need to hold. 20698*/ 20699void assert_invariant ( bool check_parents = true) const noexcept 20700{ 20701JSON_ASSERT (m_data. m_type != value_t::object || m_data. m_value . object != nullptr ); 20702JSON_ASSERT (m_data. m_type != value_t::array || m_data. m_value . array != nullptr ); 20703JSON_ASSERT (m_data. m_type != value_t::string || m_data. m_value . string != nullptr ); 20704JSON_ASSERT (m_data. m_type != value_t::binary || m_data. m_value . binary != nullptr ); 20705 20706#if JSON_DIAGNOSTICS 20707JSON_TRY 20708{ 20709// cppcheck-suppress assertWithSideEffect 20710JSON_ASSERT (!check_parents || ! is_structured () || std:: all_of ( begin (), end (), [this]( const basic_json & j) 20711{ 20712return j. m_parent == this; 20713})); 20714} 20715JSON_CATCH (...) {} // LCOV_EXCL_LINE 20716#endif 20717static_cast < void > (check_parents); 20718} 20719 20720void set_parents () 20721{ 20722#if JSON_DIAGNOSTICS 20723switch (m_data. m_type ) 20724{ 20725case value_t::array: 20726{ 20727for ( auto & element : * m_data. m_value . array ) 20728{ 20729element. m_parent = this; 20730} 20731break ; 20732} 20733 20734case value_t::object: 20735{ 20736for ( auto & element : * m_data. m_value . object ) 20737{ 20738element. second . m_parent = this; 20739} 20740break ; 20741} 20742 20743case value_t::null: 20744case value_t::string: 20745case value_t::boolean: 20746case value_t::number_integer: 20747case value_t::number_unsigned: 20748case value_t::number_float: 20749case value_t::binary: 20750case value_t::discarded: 20751default : 20752break ; 20753} 20754#endif 20755} 20756 20757iterator set_parents ( iterator it, typename iterator:: difference_type count_set_parents) 20758{ 20759#if JSON_DIAGNOSTICS 20760for ( typename iterator:: difference_type i = 0 ; i < count_set_parents; ++ i) 20761{ 20762(it + i) -> m_parent = this; 20763} 20764#else 20765static_cast < void > (count_set_parents); 20766#endif 20767return it; 20768} 20769 20770reference set_parent ( reference j, std:: size_t old_capacity = detail:: unknown_size ()) 20771{ 20772#if JSON_DIAGNOSTICS 20773if (old_capacity != detail:: unknown_size ()) 20774{ 20775// see https://github.com/nlohmann/json/issues/2838 20776JSON_ASSERT ( type () == value_t::array); 20777if ( JSON_HEDLEY_UNLIKELY (m_data. m_value . array -> capacity () != old_capacity)) 20778{ 20779// capacity has changed: update all parents 20780set_parents (); 20781return j; 20782} 20783} 20784 20785// ordered_json uses a vector internally, so pointers could have 20786// been invalidated; see https://github.com/nlohmann/json/issues/2962 20787#ifdef JSON_HEDLEY_MSVC_VERSION 20788#pragma warning(push ) 20789#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr 20790#endif 20791if (detail:: is_ordered_map < object_t > ::value) 20792{ 20793set_parents (); 20794return j; 20795} 20796#ifdef JSON_HEDLEY_MSVC_VERSION 20797#pragma warning( pop ) 20798#endif 20799 20800j. m_parent = this; 20801#else 20802static_cast < void > (j); 20803static_cast < void > (old_capacity); 20804#endif 20805return j; 20806} 20807 20808public : 20809////////////////////////// 20810// JSON parser callback // 20811////////////////////////// 20812 20813/// @brief parser event types 20814/// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ 20815using parse_event_t = detail::parse_event_t; 20816 20817/// @brief per-element parser callback type 20818/// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ 20819using parser_callback_t = detail:: parser_callback_t < basic_json > ; 20820 20821////////////////// 20822// constructors // 20823////////////////// 20824 20825/// @name constructors and destructors 20826/// Constructors of class @ref basic_json, copy/move constructor, copy 20827/// assignment, static functions creating objects, and the destructor. 20828/// @{ 20829 20830/// @brief create an empty value with a given type 20831/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20832basic_json ( const value_t v) 20833: m_data (v) 20834{ 20835assert_invariant (); 20836} 20837 20838/// @brief create a null object 20839/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20840basic_json (std:: nullptr_t = nullptr ) noexcept // NOLINT(bugprone-exception-escape) 20841: basic_json (value_t::null) 20842{ 20843assert_invariant (); 20844} 20845 20846/// @brief create a JSON value from compatible types 20847/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20848template < typename CompatibleType , 20849typename U = detail:: uncvref_t < CompatibleType > , 20850detail:: enable_if_t < 20851!detail:: is_basic_json < U > ::value && detail:: is_compatible_type < basic_json_t , U > ::value, int > = 0 > 20852basic_json ( CompatibleType && val) noexcept ( noexcept ( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) 20853JSONSerializer < U > :: to_json (std:: declval < basic_json_t &> (), 20854std:: forward < CompatibleType > (val)))) 20855{ 20856JSONSerializer < U > :: to_json ( * this, std:: forward < CompatibleType > (val)); 20857set_parents (); 20858assert_invariant (); 20859} 20860 20861/// @brief create a JSON value from an existing one 20862/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20863template < typename BasicJsonType , 20864detail:: enable_if_t < 20865detail:: is_basic_json < BasicJsonType > ::value && !std:: is_same < basic_json , BasicJsonType > ::value, int > = 0 > 20866basic_json ( const BasicJsonType & val) 20867#if JSON_DIAGNOSTIC_POSITIONS 20868: start_position (val. start_pos ()), 20869end_position (val. end_pos ()) 20870#endif 20871{ 20872using other_boolean_t = typename BasicJsonType :: boolean_t ; 20873using other_number_float_t = typename BasicJsonType :: number_float_t ; 20874using other_number_integer_t = typename BasicJsonType :: number_integer_t ; 20875using other_number_unsigned_t = typename BasicJsonType :: number_unsigned_t ; 20876using other_string_t = typename BasicJsonType :: string_t ; 20877using other_object_t = typename BasicJsonType :: object_t ; 20878using other_array_t = typename BasicJsonType :: array_t ; 20879using other_binary_t = typename BasicJsonType :: binary_t ; 20880 20881switch (val. type ()) 20882{ 20883case value_t::boolean: 20884JSONSerializer < other_boolean_t > :: to_json ( * this, val. template get < other_boolean_t > ()); 20885break ; 20886case value_t::number_float: 20887JSONSerializer < other_number_float_t > :: to_json ( * this, val. template get < other_number_float_t > ()); 20888break ; 20889case value_t::number_integer: 20890JSONSerializer < other_number_integer_t > :: to_json ( * this, val. template get < other_number_integer_t > ()); 20891break ; 20892case value_t::number_unsigned: 20893JSONSerializer < other_number_unsigned_t > :: to_json ( * this, val. template get < other_number_unsigned_t > ()); 20894break ; 20895case value_t::string: 20896JSONSerializer < other_string_t > :: to_json ( * this, val. template get_ref < const other_string_t &> ()); 20897break ; 20898case value_t::object: 20899JSONSerializer < other_object_t > :: to_json ( * this, val. template get_ref < const other_object_t &> ()); 20900break ; 20901case value_t::array: 20902JSONSerializer < other_array_t > :: to_json ( * this, val. template get_ref < const other_array_t &> ()); 20903break ; 20904case value_t::binary: 20905JSONSerializer < other_binary_t > :: to_json ( * this, val. template get_ref < const other_binary_t &> ()); 20906break ; 20907case value_t::null: 20908* this = nullptr ; 20909break ; 20910case value_t::discarded: 20911m_data. m_type = value_t::discarded; 20912break ; 20913default : // LCOV_EXCL_LINE 20914JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 20915} 20916JSON_ASSERT (m_data. m_type == val. type ()); 20917 20918set_parents (); 20919assert_invariant (); 20920} 20921 20922/// @brief create a container (array or object) from an initializer list 20923/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20924basic_json ( initializer_list_t init, 20925bool type_deduction = true, 20926value_t manual_type = value_t::array) 20927{ 20928// check if each element is an array with two elements whose first 20929// element is a string 20930bool is_an_object = std:: all_of (init. begin (), init. end (), 20931[]( const detail:: json_ref < basic_json >& element_ref) 20932{ 20933// The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int; 20934// (many string types can be constructed from 0 via its null-pointer guise, so we get a 20935// broken call to op[key_type], the wrong semantics and a 4804 warning on Windows) 20936return element_ref -> is_array () && element_ref -> size () == 2 && ( * element_ref)[ static_cast < size_type > ( 0 )]. is_string (); 20937}); 20938 20939// adjust type if type deduction is not wanted 20940if (!type_deduction) 20941{ 20942// if array is wanted, do not create an object though possible 20943if (manual_type == value_t::array) 20944{ 20945is_an_object = false; 20946} 20947 20948// if object is wanted but impossible, throw an exception 20949if ( JSON_HEDLEY_UNLIKELY (manual_type == value_t::object && !is_an_object)) 20950{ 20951JSON_THROW (type_error:: create ( 301 , "cannot create object from initializer list" , nullptr )); 20952} 20953} 20954 20955if (is_an_object) 20956{ 20957// the initializer list is a list of pairs -> create object 20958m_data. m_type = value_t::object; 20959m_data. m_value = value_t::object; 20960 20961for ( auto & element_ref : init) 20962{ 20963auto element = element_ref. moved_or_copied (); 20964m_data. m_value . object -> emplace ( 20965std:: move ( * (( * element. m_data . m_value . array )[ 0 ]. m_data . m_value . string )), 20966std:: move (( * element. m_data . m_value . array )[ 1 ])); 20967} 20968} 20969else 20970{ 20971// the initializer list describes an array -> create array 20972m_data. m_type = value_t::array; 20973m_data. m_value . array = create < array_t > (init. begin (), init. end ()); 20974} 20975 20976set_parents (); 20977assert_invariant (); 20978} 20979 20980/// @brief explicitly create a binary array (without subtype) 20981/// @sa https://json.nlohmann.me/api/basic_json/binary/ 20982JSON_HEDLEY_WARN_UNUSED_RESULT 20983static basic_json binary ( const typename binary_t:: container_type & init) 20984{ 20985auto res = basic_json (); 20986res. m_data . m_type = value_t::binary; 20987res. m_data . m_value = init; 20988return res; 20989} 20990 20991/// @brief explicitly create a binary array (with subtype) 20992/// @sa https://json.nlohmann.me/api/basic_json/binary/ 20993JSON_HEDLEY_WARN_UNUSED_RESULT 20994static basic_json binary ( const typename binary_t:: container_type & init, typename binary_t:: subtype_type subtype) 20995{ 20996auto res = basic_json (); 20997res. m_data . m_type = value_t::binary; 20998res. m_data . m_value = binary_t (init, subtype); 20999return res; 21000} 21001 21002/// @brief explicitly create a binary array 21003/// @sa https://json.nlohmann.me/api/basic_json/binary/ 21004JSON_HEDLEY_WARN_UNUSED_RESULT 21005static basic_json binary ( typename binary_t:: container_type && init) 21006{ 21007auto res = basic_json (); 21008res. m_data . m_type = value_t::binary; 21009res. m_data . m_value = std:: move (init); 21010return res; 21011} 21012 21013/// @brief explicitly create a binary array (with subtype) 21014/// @sa https://json.nlohmann.me/api/basic_json/binary/ 21015JSON_HEDLEY_WARN_UNUSED_RESULT 21016static basic_json binary ( typename binary_t:: container_type && init, typename binary_t:: subtype_type subtype) 21017{ 21018auto res = basic_json (); 21019res. m_data . m_type = value_t::binary; 21020res. m_data . m_value = binary_t (std:: move (init), subtype); 21021return res; 21022} 21023 21024/// @brief explicitly create an array from an initializer list 21025/// @sa https://json.nlohmann.me/api/basic_json/array/ 21026JSON_HEDLEY_WARN_UNUSED_RESULT 21027static basic_json array ( initializer_list_t init = {}) 21028{ 21029return basic_json ( init , false, value_t:: array ); 21030} 21031 21032/// @brief explicitly create an object from an initializer list 21033/// @sa https://json.nlohmann.me/api/basic_json/object/ 21034JSON_HEDLEY_WARN_UNUSED_RESULT 21035static basic_json object (initializer_list_t init = {}) 21036{ 21037return basic_json ( init , false, value_t:: object ); 21038} 21039 21040/// @brief construct an array with count copies of given value 21041/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 21042basic_json (size_type cnt , const basic_json & val ): 21043m_data { cnt , val } 21044{ 21045set_parents (); 21046assert_invariant (); 21047} 21048 21049/// @brief construct a JSON container given an iterator range 21050/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 21051template < class InputIT, typename std::enable_if < 21052std::is_same < InputIT, typename basic_json_t::iterator > :: value || 21053std::is_same < InputIT, typename basic_json_t::const_iterator > :: value , int > ::type = 0 > 21054basic_json (InputIT first , InputIT last ) // NOLINT(performance-unnecessary-value-param) 21055{ 21056JSON_ASSERT ( first . m_object != nullptr ); 21057JSON_ASSERT ( last . m_object != nullptr ); 21058 21059// make sure iterator fits the current value 21060if ( JSON_HEDLEY_UNLIKELY ( first . m_object != last . m_object )) 21061{ 21062JSON_THROW (invalid_iterator:: create ( 201 , "iterators are not compatible" , nullptr )); 21063} 21064 21065// copy type from first iterator 21066m_data . m_type = first . m_object -> m_data . m_type ; 21067 21068// check if iterator range is complete for primitive values 21069switch ( m_data . m_type ) 21070{ 21071case value_t:: boolean : 21072case value_t:: number_float : 21073case value_t:: number_integer : 21074case value_t:: number_unsigned : 21075case value_t:: string : 21076{ 21077if ( JSON_HEDLEY_UNLIKELY (! first . m_it . primitive_iterator . is_begin () 21078|| ! last . m_it . primitive_iterator . is_end ())) 21079{ 21080JSON_THROW (invalid_iterator:: create ( 204 , "iterators out of range" , first . m_object )); 21081} 21082break ; 21083} 21084 21085case value_t:: null : 21086case value_t:: object : 21087case value_t:: array : 21088case value_t:: binary : 21089case value_t:: discarded : 21090default : 21091break ; 21092} 21093 21094switch ( m_data . m_type ) 21095{ 21096case value_t:: number_integer : 21097{ 21098m_data . m_value . number_integer = first . m_object -> m_data . m_value . number_integer ; 21099break ; 21100} 21101 21102case value_t:: number_unsigned : 21103{ 21104m_data . m_value . number_unsigned = first . m_object -> m_data . m_value . number_unsigned ; 21105break ; 21106} 21107 21108case value_t:: number_float : 21109{ 21110m_data . m_value . number_float = first . m_object -> m_data . m_value . number_float ; 21111break ; 21112} 21113 21114case value_t:: boolean : 21115{ 21116m_data . m_value . boolean = first . m_object -> m_data . m_value . boolean ; 21117break ; 21118} 21119 21120case value_t:: string : 21121{ 21122m_data . m_value = * first . m_object -> m_data . m_value . string ; 21123break ; 21124} 21125 21126case value_t:: object : 21127{ 21128m_data . m_value . object = create < object_t > ( first . m_it . object_iterator , 21129last . m_it . object_iterator ); 21130break ; 21131} 21132 21133case value_t:: array : 21134{ 21135m_data . m_value . array = create < array_t > ( first . m_it . array_iterator , 21136last . m_it . array_iterator ); 21137break ; 21138} 21139 21140case value_t:: binary : 21141{ 21142m_data . m_value = * first . m_object -> m_data . m_value . binary ; 21143break ; 21144} 21145 21146case value_t:: null : 21147case value_t:: discarded : 21148default : 21149JSON_THROW (invalid_iterator:: create ( 206 , detail:: concat ( "cannot construct with iterators from " , first . m_object -> type_name ()), first . m_object )); 21150} 21151 21152set_parents (); 21153assert_invariant (); 21154} 21155 21156/////////////////////////////////////// 21157// other constructors and destructor // 21158/////////////////////////////////////// 21159 21160template < typename JsonRef, 21161detail::enable_if_t < detail::conjunction < detail::is_json_ref < JsonRef > , 21162std::is_same < typename JsonRef::value_type, basic_json >> ::value, int > = 0 > 21163basic_json ( const JsonRef & ref ) : basic_json ( ref . moved_or_copied ()) {} 21164 21165/// @brief copy constructor 21166/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 21167basic_json ( const basic_json & other ) 21168: json_base_class_t ( other ) 21169#if JSON_DIAGNOSTIC_POSITIONS 21170, start_position ( other . start_position ) 21171, end_position ( other . end_position ) 21172#endif 21173{ 21174m_data . m_type = other . m_data . m_type ; 21175// check of passed value is valid 21176other . assert_invariant (); 21177 21178switch ( m_data . m_type ) 21179{ 21180case value_t:: object : 21181{ 21182m_data . m_value = * other . m_data . m_value . object ; 21183break ; 21184} 21185 21186case value_t:: array : 21187{ 21188m_data . m_value = * other . m_data . m_value . array ; 21189break ; 21190} 21191 21192case value_t:: string : 21193{ 21194m_data . m_value = * other . m_data . m_value . string ; 21195break ; 21196} 21197 21198case value_t:: boolean : 21199{ 21200m_data . m_value = other . m_data . m_value . boolean ; 21201break ; 21202} 21203 21204case value_t:: number_integer : 21205{ 21206m_data . m_value = other . m_data . m_value . number_integer ; 21207break ; 21208} 21209 21210case value_t:: number_unsigned : 21211{ 21212m_data . m_value = other . m_data . m_value . number_unsigned ; 21213break ; 21214} 21215 21216case value_t:: number_float : 21217{ 21218m_data . m_value = other . m_data . m_value . number_float ; 21219break ; 21220} 21221 21222case value_t:: binary : 21223{ 21224m_data . m_value = * other . m_data . m_value . binary ; 21225break ; 21226} 21227 21228case value_t:: null : 21229case value_t:: discarded : 21230default : 21231break ; 21232} 21233 21234set_parents (); 21235assert_invariant (); 21236} 21237 21238/// @brief move constructor 21239/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 21240basic_json (basic_json && other ) noexcept 21241: json_base_class_t (std:: forward < json_base_class_t > ( other )), 21242m_data (std:: move ( other . m_data )) // cppcheck-suppress[accessForwarded] TODO check 21243#if JSON_DIAGNOSTIC_POSITIONS 21244, start_position ( other . start_position ) // cppcheck-suppress[accessForwarded] TODO check 21245, end_position ( other . end_position ) // cppcheck-suppress[accessForwarded] TODO check 21246#endif 21247{ 21248// check that passed value is valid 21249other . assert_invariant (false); // cppcheck-suppress[accessForwarded] 21250 21251// invalidate payload 21252other . m_data . m_type = value_t:: null ; 21253other . m_data . m_value = {}; 21254 21255#if JSON_DIAGNOSTIC_POSITIONS 21256other . start_position = std::string:: npos ; 21257other . end_position = std::string:: npos ; 21258#endif 21259 21260set_parents (); 21261assert_invariant (); 21262} 21263 21264/// @brief copy assignment 21265/// @sa https://json.nlohmann.me/api/basic_json/operator=/ 21266basic_json & operator = (basic_json other ) noexcept ( 21267std::is_nothrow_move_constructible < value_t > :: value && 21268std::is_nothrow_move_assignable < value_t > :: value && 21269std::is_nothrow_move_constructible < json_value > :: value && 21270std::is_nothrow_move_assignable < json_value > :: value && 21271std::is_nothrow_move_assignable < json_base_class_t > :: value 21272) 21273{ 21274// check that passed value is valid 21275other . assert_invariant (); 21276 21277using std:: swap ; 21278swap ( m_data . m_type , other . m_data . m_type ); 21279swap ( m_data . m_value , other . m_data . m_value ); 21280 21281#if JSON_DIAGNOSTIC_POSITIONS 21282swap ( start_position , other . start_position ); 21283swap ( end_position , other . end_position ); 21284#endif 21285 21286json_base_class_t::operator = (std:: move ( other )); 21287 21288set_parents (); 21289assert_invariant (); 21290return * this ; 21291} 21292 21293/// @brief destructor 21294/// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ 21295~ basic_json () noexcept 21296{ 21297assert_invariant (false); 21298} 21299 21300/// @} 21301 21302public : 21303/////////////////////// 21304// object inspection // 21305/////////////////////// 21306 21307/// @name object inspection 21308/// Functions to inspect the type of a JSON value. 21309/// @{ 21310 21311/// @brief serialization 21312/// @sa https://json.nlohmann.me/api/basic_json/dump/ 21313string_t dump ( const int indent = -1 , 21314const char indent_char = ' ' , 21315const bool ensure_ascii = false, 21316const error_handler_t error_handler = error_handler_t:: strict ) const 21317{ 21318string_t result ; 21319serializer s (detail:: output_adapter < char, string_t > ( result ), indent_char , error_handler ); 21320 21321if ( indent >= 0 ) 21322{ 21323s . dump ( * this , true, ensure_ascii , static_cast < unsigned int > ( indent )); 21324} 21325else 21326{ 21327s . dump ( * this , false, ensure_ascii , 0 ); 21328} 21329 21330return result ; 21331} 21332 21333/// @brief return the type of the JSON value (explicit) 21334/// @sa https://json.nlohmann.me/api/basic_json/type/ 21335constexpr value_t type () const noexcept 21336{ 21337return m_data . m_type ; 21338} 21339 21340/// @brief return whether type is primitive 21341/// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ 21342constexpr bool is_primitive () const noexcept 21343{ 21344return is_null () || is_string () || is_boolean () || is_number () || is_binary (); 21345} 21346 21347/// @brief return whether type is structured 21348/// @sa https://json.nlohmann.me/api/basic_json/is_structured/ 21349constexpr bool is_structured () const noexcept 21350{ 21351return is_array () || is_object (); 21352} 21353 21354/// @brief return whether value is null 21355/// @sa https://json.nlohmann.me/api/basic_json/is_null/ 21356constexpr bool is_null () const noexcept 21357{ 21358return m_data . m_type == value_t:: null ; 21359} 21360 21361/// @brief return whether value is a boolean 21362/// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ 21363constexpr bool is_boolean () const noexcept 21364{ 21365return m_data . m_type == value_t:: boolean ; 21366} 21367 21368/// @brief return whether value is a number 21369/// @sa https://json.nlohmann.me/api/basic_json/is_number/ 21370constexpr bool is_number () const noexcept 21371{ 21372return is_number_integer () || is_number_float (); 21373} 21374 21375/// @brief return whether value is an integer number 21376/// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ 21377constexpr bool is_number_integer () const noexcept 21378{ 21379return m_data . m_type == value_t:: number_integer || m_data . m_type == value_t:: number_unsigned ; 21380} 21381 21382/// @brief return whether value is an unsigned integer number 21383/// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ 21384constexpr bool is_number_unsigned () const noexcept 21385{ 21386return m_data . m_type == value_t:: number_unsigned ; 21387} 21388 21389/// @brief return whether value is a floating-point number 21390/// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ 21391constexpr bool is_number_float () const noexcept 21392{ 21393return m_data . m_type == value_t:: number_float ; 21394} 21395 21396/// @brief return whether value is an object 21397/// @sa https://json.nlohmann.me/api/basic_json/is_object/ 21398constexpr bool is_object () const noexcept 21399{ 21400return m_data . m_type == value_t:: object ; 21401} 21402 21403/// @brief return whether value is an array 21404/// @sa https://json.nlohmann.me/api/basic_json/is_array/ 21405constexpr bool is_array () const noexcept 21406{ 21407return m_data . m_type == value_t:: array ; 21408} 21409 21410/// @brief return whether value is a string 21411/// @sa https://json.nlohmann.me/api/basic_json/is_string/ 21412constexpr bool is_string () const noexcept 21413{ 21414return m_data . m_type == value_t:: string ; 21415} 21416 21417/// @brief return whether value is a binary array 21418/// @sa https://json.nlohmann.me/api/basic_json/is_binary/ 21419constexpr bool is_binary () const noexcept 21420{ 21421return m_data . m_type == value_t:: binary ; 21422} 21423 21424/// @brief return whether value is discarded 21425/// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ 21426constexpr bool is_discarded () const noexcept 21427{ 21428return m_data . m_type == value_t:: discarded ; 21429} 21430 21431/// @brief return the type of the JSON value (implicit) 21432/// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ 21433constexpr operator value_t() const noexcept 21434{ 21435return m_data . m_type ; 21436} 21437 21438/// @} 21439 21440private : 21441////////////////// 21442// value access // 21443////////////////// 21444 21445/// get a boolean (explicit) 21446boolean_t get_impl (boolean_t * /*unused*/ ) const 21447{ 21448if ( JSON_HEDLEY_LIKELY ( is_boolean ())) 21449{ 21450return m_data . m_value . boolean ; 21451} 21452 21453JSON_THROW (type_error:: create ( 302 , detail:: concat ( "type must be boolean, but is " , type_name ()), this )); 21454} 21455 21456/// get a pointer to the value (object) 21457object_t * get_impl_ptr (object_t * /*unused*/ ) noexcept 21458{ 21459return is_object () ? m_data . m_value . object : nullptr ; 21460} 21461 21462/// get a pointer to the value (object) 21463constexpr const object_t * get_impl_ptr ( const object_t * /*unused*/ ) const noexcept 21464{ 21465return is_object () ? m_data . m_value . object : nullptr ; 21466} 21467 21468/// get a pointer to the value (array) 21469array_t * get_impl_ptr (array_t * /*unused*/ ) noexcept 21470{ 21471return is_array () ? m_data . m_value . array : nullptr ; 21472} 21473 21474/// get a pointer to the value (array) 21475constexpr const array_t * get_impl_ptr ( const array_t * /*unused*/ ) const noexcept 21476{ 21477return is_array () ? m_data . m_value . array : nullptr ; 21478} 21479 21480/// get a pointer to the value (string) 21481string_t * get_impl_ptr (string_t * /*unused*/ ) noexcept 21482{ 21483return is_string () ? m_data . m_value . string : nullptr ; 21484} 21485 21486/// get a pointer to the value (string) 21487constexpr const string_t * get_impl_ptr ( const string_t * /*unused*/ ) const noexcept 21488{ 21489return is_string () ? m_data . m_value . string : nullptr ; 21490} 21491 21492/// get a pointer to the value (boolean) 21493boolean_t * get_impl_ptr (boolean_t * /*unused*/ ) noexcept 21494{ 21495return is_boolean () ? & m_data . m_value . boolean : nullptr ; 21496} 21497 21498/// get a pointer to the value (boolean) 21499constexpr const boolean_t * get_impl_ptr ( const boolean_t * /*unused*/ ) const noexcept 21500{ 21501return is_boolean () ? & m_data . m_value . boolean : nullptr ; 21502} 21503 21504/// get a pointer to the value (integer number) 21505number_integer_t * get_impl_ptr (number_integer_t * /*unused*/ ) noexcept 21506{ 21507return m_data . m_type == value_t:: number_integer ? & m_data . m_value . number_integer : nullptr ; 21508} 21509 21510/// get a pointer to the value (integer number) 21511constexpr const number_integer_t * get_impl_ptr ( const number_integer_t * /*unused*/ ) const noexcept 21512{ 21513return m_data . m_type == value_t:: number_integer ? & m_data . m_value . number_integer : nullptr ; 21514} 21515 21516/// get a pointer to the value (unsigned number) 21517number_unsigned_t * get_impl_ptr (number_unsigned_t * /*unused*/ ) noexcept 21518{ 21519return is_number_unsigned () ? & m_data . m_value . number_unsigned : nullptr ; 21520} 21521 21522/// get a pointer to the value (unsigned number) 21523constexpr const number_unsigned_t * get_impl_ptr ( const number_unsigned_t * /*unused*/ ) const noexcept 21524{ 21525return is_number_unsigned () ? & m_data . m_value . number_unsigned : nullptr ; 21526} 21527 21528/// get a pointer to the value (floating-point number) 21529number_float_t * get_impl_ptr (number_float_t * /*unused*/ ) noexcept 21530{ 21531return is_number_float () ? & m_data . m_value . number_float : nullptr ; 21532} 21533 21534/// get a pointer to the value (floating-point number) 21535constexpr const number_float_t * get_impl_ptr ( const number_float_t * /*unused*/ ) const noexcept 21536{ 21537return is_number_float () ? & m_data . m_value . number_float : nullptr ; 21538} 21539 21540/// get a pointer to the value (binary) 21541binary_t * get_impl_ptr (binary_t * /*unused*/ ) noexcept 21542{ 21543return is_binary () ? m_data . m_value . binary : nullptr ; 21544} 21545 21546/// get a pointer to the value (binary) 21547constexpr const binary_t * get_impl_ptr ( const binary_t * /*unused*/ ) const noexcept 21548{ 21549return is_binary () ? m_data . m_value . binary : nullptr ; 21550} 21551 21552/*! 21553@brief helper function to implement get_ref() 21554 21555This function helps to implement get_ref() without code duplication for 21556const and non-const overloads 21557 21558@tparam ThisType will be deduced as `basic_json` or `const basic_json` 21559 21560@throw type_error.303 if ReferenceType does not match underlying value 21561type of the current JSON 21562*/ 21563template < typename ReferenceType, typename ThisType > 21564static ReferenceType get_ref_impl (ThisType & obj ) 21565{ 21566// delegate the call to get_ptr<>() 21567auto * ptr = obj . template get_ptr < typename std::add_pointer < ReferenceType > ::type > (); 21568 21569if ( JSON_HEDLEY_LIKELY ( ptr != nullptr )) 21570{ 21571return * ptr ; 21572} 21573 21574JSON_THROW (type_error:: create ( 303 , detail:: concat ( "incompatible ReferenceType for get_ref, actual type is " , obj . type_name ()), & obj )); 21575} 21576 21577public : 21578/// @name value access 21579/// Direct access to the stored value of a JSON value. 21580/// @{ 21581 21582/// @brief get a pointer value (implicit) 21583/// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 21584template < typename PointerType , typename std ::enable_if < 21585std::is_pointer < PointerType > ::value, int > :: type = 0 > 21586auto get_ptr () noexcept -> decltype(std:: declval < basic_json_t &> (). get_impl_ptr (std:: declval < PointerType > ())) 21587{ 21588// delegate the call to get_impl_ptr<>() 21589return get_impl_ptr ( static_cast < PointerType > ( nullptr )); 21590} 21591 21592/// @brief get a pointer value (implicit) 21593/// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 21594template < typename PointerType, typename std::enable_if < 21595std::is_pointer < PointerType > :: value && 21596std::is_const < typename std::remove_pointer < PointerType > ::type > :: value , int > ::type = 0 > 21597constexpr auto get_ptr () const noexcept -> decltype(std:: declval < const basic_json_t &> (). get_impl_ptr (std:: declval < PointerType > ())) 21598{ 21599// delegate the call to get_impl_ptr<>() const 21600return get_impl_ptr ( static_cast < PointerType > ( nullptr )); 21601} 21602 21603private : 21604/*! 21605@brief get a value (explicit) 21606 21607Explicit type conversion between the JSON value and a compatible value 21608which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 21609and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 21610The value is converted by calling the @ref json_serializer<ValueType> 21611`from_json()` method. 21612 21613The function is equivalent to executing 21614@code {.cpp} 21615ValueType ret; 21616JSONSerializer<ValueType>::from_json(*this, ret); 21617return ret; 21618@endcode 21619 21620This overloads is chosen if: 21621- @a ValueType is not @ref basic_json, 21622- @ref json_serializer<ValueType> has a `from_json()` method of the form 21623`void from_json(const basic_json&, ValueType&)`, and 21624- @ref json_serializer<ValueType> does not have a `from_json()` method of 21625the form `ValueType from_json(const basic_json&)` 21626 21627@tparam ValueType the returned value type 21628 21629@return copy of the JSON value, converted to @a ValueType 21630 21631@throw what @ref json_serializer<ValueType> `from_json()` method throws 21632 21633@liveexample{The example below shows several conversions from JSON values 21634to other types. There a few things to note: (1) Floating-point numbers can 21635be converted to integers\, (2) A JSON array can be converted to a standard 21636`std::vector<short>`\, (3) A JSON object can be converted to C++ 21637associative containers such as `std::unordered_map<std::string\, 21638json>`.,get__ValueType_const} 21639 21640@since version 2.1.0 21641*/ 21642template < typename ValueType , 21643detail ::enable_if_t < 21644detail::is_default_constructible < ValueType > :: value && 21645detail::has_from_json < basic_json_t, ValueType > :: value , 21646int > = 0 > 21647ValueType get_impl ( detail :: priority_tag < 0 > /*unused*/ ) const noexcept ( noexcept ( 21648JSONSerializer < ValueType > :: from_json (std:: declval < const basic_json_t &> (), std:: declval < ValueType &> ()))) 21649{ 21650auto ret = ValueType (); 21651JSONSerializer < ValueType > :: from_json ( * this , ret ); 21652return ret ; 21653} 21654 21655/*! 21656@brief get a value (explicit); special case 21657 21658Explicit type conversion between the JSON value and a compatible value 21659which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 21660and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 21661The value is converted by calling the @ref json_serializer<ValueType> 21662`from_json()` method. 21663 21664The function is equivalent to executing 21665@code {.cpp} 21666return JSONSerializer<ValueType>::from_json(*this); 21667@endcode 21668 21669This overloads is chosen if: 21670- @a ValueType is not @ref basic_json and 21671- @ref json_serializer<ValueType> has a `from_json()` method of the form 21672`ValueType from_json(const basic_json&)` 21673 21674@note If @ref json_serializer<ValueType> has both overloads of 21675`from_json()`, this one is chosen. 21676 21677@tparam ValueType the returned value type 21678 21679@return copy of the JSON value, converted to @a ValueType 21680 21681@throw what @ref json_serializer<ValueType> `from_json()` method throws 21682 21683@since version 2.1.0 21684*/ 21685template < typename ValueType, 21686detail::enable_if_t < 21687detail::has_non_default_from_json < basic_json_t, ValueType > ::value, 21688int > = 0 > 21689ValueType get_impl (detail::priority_tag < 1 > /*unused*/ ) const noexcept ( noexcept ( 21690JSONSerializer < ValueType > :: from_json (std:: declval < const basic_json_t &> ()))) 21691{ 21692return JSONSerializer < ValueType > :: from_json ( * this ); 21693} 21694 21695/*! 21696@brief get special-case overload 21697 21698This overloads converts the current @ref basic_json in a different 21699@ref basic_json type 21700 21701@tparam BasicJsonType == @ref basic_json 21702 21703@return a copy of *this, converted into @a BasicJsonType 21704 21705@complexity Depending on the implementation of the called `from_json()` 21706method. 21707 21708@since version 3.2.0 21709*/ 21710template < typename BasicJsonType, 21711detail::enable_if_t < 21712detail::is_basic_json < BasicJsonType > ::value, 21713int > = 0 > 21714BasicJsonType get_impl (detail::priority_tag < 2 > /*unused*/ ) const 21715{ 21716return * this ; 21717} 21718 21719/*! 21720@brief get special-case overload 21721 21722This overloads avoids a lot of template boilerplate, it can be seen as the 21723identity method 21724 21725@tparam BasicJsonType == @ref basic_json 21726 21727@return a copy of *this 21728 21729@complexity Constant. 21730 21731@since version 2.1.0 21732*/ 21733template < typename BasicJsonType, 21734detail::enable_if_t < 21735std::is_same < BasicJsonType, basic_json_t > ::value, 21736int > = 0 > 21737basic_json get_impl (detail::priority_tag < 3 > /*unused*/ ) const 21738{ 21739return * this ; 21740} 21741 21742/*! 21743@brief get a pointer value (explicit) 21744@copydoc get() 21745*/ 21746template < typename PointerType, 21747detail::enable_if_t < 21748std::is_pointer < PointerType > ::value, 21749int > = 0 > 21750constexpr auto get_impl (detail::priority_tag < 4 > /*unused*/ ) const noexcept 21751-> decltype(std:: declval < const basic_json_t &> (). template get_ptr < PointerType > ()) 21752{ 21753// delegate the call to get_ptr 21754return get_ptr < PointerType > (); 21755} 21756 21757public : 21758/*! 21759@brief get a (pointer) value (explicit) 21760 21761Performs explicit type conversion between the JSON value and a compatible value if required. 21762 21763- If the requested type is a pointer to the internally stored JSON value that pointer is returned. 21764No copies are made. 21765 21766- If the requested type is the current @ref basic_json, or a different @ref basic_json convertible 21767from the current @ref basic_json. 21768 21769- Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()` 21770method. 21771 21772@tparam ValueTypeCV the provided value type 21773@tparam ValueType the returned value type 21774 21775@return copy of the JSON value, converted to @tparam ValueType if necessary 21776 21777@throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required 21778 21779@since version 2.1.0 21780*/ 21781template < typename ValueTypeCV , typename ValueType = detail ::uncvref_t < ValueTypeCV >> 21782#if defined( JSON_HAS_CPP_14 ) 21783constexpr 21784#endif 21785auto get () const noexcept ( 21786noexcept (std:: declval < const basic_json_t &> (). template get_impl < ValueType > (detail::priority_tag < 4 > {}))) 21787-> decltype(std:: declval < const basic_json_t &> (). template get_impl < ValueType > (detail::priority_tag < 4 > {})) 21788{ 21789// we cannot static_assert on ValueTypeCV being non-const, because 21790// there is support for get<const basic_json_t>(), which is why we 21791// still need the uncvref 21792static_assert (!std::is_reference < ValueTypeCV > :: value , 21793"get() cannot be used with reference types, you might want to use get_ref()" ); 21794return get_impl < ValueType > (detail::priority_tag < 4 > {}); 21795} 21796 21797/*! 21798@brief get a pointer value (explicit) 21799 21800Explicit pointer access to the internally stored JSON value. No copies are 21801made. 21802 21803@warning The pointer becomes invalid if the underlying JSON object 21804changes. 21805 21806@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref 21807object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 21808@ref number_unsigned_t, or @ref number_float_t. 21809 21810@return pointer to the internally stored JSON value if the requested 21811pointer type @a PointerType fits to the JSON value; `nullptr` otherwise 21812 21813@complexity Constant. 21814 21815@liveexample{The example below shows how pointers to internal values of a 21816JSON value can be requested. Note that no type conversions are made and a 21817`nullptr` is returned if the value and the requested pointer type does not 21818match.,get__PointerType} 21819 21820@sa see @ref get_ptr() for explicit pointer-member access 21821 21822@since version 1.0.0 21823*/ 21824template < typename PointerType, typename std::enable_if < 21825std::is_pointer < PointerType > ::value, int > ::type = 0 > 21826auto get () noexcept -> decltype(std:: declval < basic_json_t &> (). template get_ptr < PointerType > ()) 21827{ 21828// delegate the call to get_ptr 21829return get_ptr < PointerType > (); 21830} 21831 21832/// @brief get a value (explicit) 21833/// @sa https://json.nlohmann.me/api/basic_json/get_to/ 21834template < typename ValueType, 21835detail::enable_if_t < 21836!detail::is_basic_json < ValueType > :: value && 21837detail::has_from_json < basic_json_t, ValueType > :: value , 21838int > = 0 > 21839ValueType & get_to (ValueType & v ) const noexcept ( noexcept ( 21840JSONSerializer < ValueType > :: from_json (std:: declval < const basic_json_t &> (), v ))) 21841{ 21842JSONSerializer < ValueType > :: from_json ( * this , v ); 21843return v ; 21844} 21845 21846// specialization to allow calling get_to with a basic_json value 21847// see https://github.com/nlohmann/json/issues/2175 21848template < typename ValueType, 21849detail::enable_if_t < 21850detail::is_basic_json < ValueType > ::value, 21851int > = 0 > 21852ValueType & get_to (ValueType & v ) const 21853{ 21854v = * this ; 21855return v ; 21856} 21857 21858template < 21859typename T, std::size_t N , 21860typename Array = T ( & )[ N ], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21861detail::enable_if_t < 21862detail::has_from_json < basic_json_t, Array > ::value, int > = 0 > 21863Array get_to (T ( & v )[ N ]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21864noexcept ( noexcept (JSONSerializer < Array > :: from_json ( 21865std:: declval < const basic_json_t &> (), v ))) 21866{ 21867JSONSerializer < Array > :: from_json ( * this , v ); 21868return v ; 21869} 21870 21871/// @brief get a reference value (implicit) 21872/// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21873template < typename ReferenceType, typename std::enable_if < 21874std::is_reference < ReferenceType > ::value, int > ::type = 0 > 21875ReferenceType get_ref () 21876{ 21877// delegate call to get_ref_impl 21878return get_ref_impl < ReferenceType > ( * this ); 21879} 21880 21881/// @brief get a reference value (implicit) 21882/// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21883template < typename ReferenceType, typename std::enable_if < 21884std::is_reference < ReferenceType > :: value && 21885std::is_const < typename std::remove_reference < ReferenceType > ::type > :: value , int > ::type = 0 > 21886ReferenceType get_ref () const 21887{ 21888// delegate call to get_ref_impl 21889return get_ref_impl < ReferenceType > ( * this ); 21890} 21891 21892/*! 21893@brief get a value (implicit) 21894 21895Implicit type conversion between the JSON value and a compatible value. 21896The call is realized by calling @ref get() const. 21897 21898@tparam ValueType non-pointer type compatible to the JSON value, for 21899instance `int` for JSON integer numbers, `bool` for JSON booleans, or 21900`std::vector` types for JSON arrays. The character type of @ref string_t 21901as well as an initializer list of this type is excluded to avoid 21902ambiguities as these types implicitly convert to `std::string`. 21903 21904@return copy of the JSON value, converted to type @a ValueType 21905 21906@throw type_error.302 in case passed type @a ValueType is incompatible 21907to the JSON value type (e.g., the JSON value is of type boolean, but a 21908string is requested); see example below 21909 21910@complexity Linear in the size of the JSON value. 21911 21912@liveexample{The example below shows several conversions from JSON values 21913to other types. There a few things to note: (1) Floating-point numbers can 21914be converted to integers\, (2) A JSON array can be converted to a standard 21915`std::vector<short>`\, (3) A JSON object can be converted to C++ 21916associative containers such as `std::unordered_map<std::string\, 21917json>`.,operator__ValueType} 21918 21919@since version 1.0.0 21920*/ 21921template < typename ValueType, typename std::enable_if < 21922detail::conjunction < 21923detail::negation < std::is_pointer < ValueType >> , 21924detail:: negation < std:: is_same < ValueType, std::nullptr_t >> , 21925detail:: negation < std:: is_same < ValueType, detail::json_ref < basic_json >>> , 21926detail::negation < std::is_same < ValueType, typename string_t::value_type >> , 21927detail::negation < detail::is_basic_json < ValueType >> , 21928detail::negation < std::is_same < ValueType, std::initializer_list < typename string_t::value_type >>> , 21929#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914 )) 21930detail:: negation <std:: is_same < ValueType , std:: string_view >>, 21931#endif 21932#if defined( JSON_HAS_CPP_17 ) && JSON_HAS_STATIC_RTTI 21933detail :: negation <std:: is_same < ValueType , std:: any >>, 21934#endif 21935detail:: is_detected_lazy <detail:: get_template_function , const basic_json_t &, ValueType > 21936>:: value , int >:: type = 0 > 21937JSON_EXPLICIT operator ValueType () const 21938{ 21939// delegate the call to get<>() const 21940return get < ValueType >(); 21941} 21942 21943/// @brief get a binary value 21944/// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21945binary_t & get_binary () 21946{ 21947if (! is_binary ()) 21948{ 21949JSON_THROW (type_error:: create ( 302 , detail:: concat ( "type must be binary, but is " , type_name ()), this )); 21950} 21951 21952return * get_ptr < binary_t *>(); 21953} 21954 21955/// @brief get a binary value 21956/// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21957const binary_t & get_binary () const 21958{ 21959if (! is_binary ()) 21960{ 21961JSON_THROW (type_error:: create ( 302 , detail:: concat ( "type must be binary, but is " , type_name ()), this )); 21962} 21963 21964return * get_ptr < const binary_t *>(); 21965} 21966 21967/// @} 21968 21969//////////////////// 21970// element access // 21971//////////////////// 21972 21973/// @name element access 21974/// Access to the JSON value. 21975/// @{ 21976 21977/// @brief access specified array element with bounds checking 21978/// @sa https://json.nlohmann.me/api/basic_json/at/ 21979reference at ( size_type idx ) 21980{ 21981// at only works for arrays 21982if ( JSON_HEDLEY_LIKELY ( is_array ())) 21983{ 21984JSON_TRY 21985{ 21986return set_parent ( m_data . m_value . array -> at ( idx )); 21987} 21988JSON_CATCH (std:: out_of_range &) 21989{ 21990// create better exception explanation 21991JSON_THROW (out_of_range:: create ( 401 , detail:: concat ( "array index " , std:: to_string ( idx ), " is out of range" ), this )); 21992} // cppcheck-suppress[missingReturn] 21993} 21994else 21995{ 21996JSON_THROW (type_error:: create ( 304 , detail:: concat ( "cannot use at() with " , type_name ()), this )); 21997} 21998} 21999 22000/// @brief access specified array element with bounds checking 22001/// @sa https://json.nlohmann.me/api/basic_json/at/ 22002const_reference at ( size_type idx ) const 22003{ 22004// at only works for arrays 22005if ( JSON_HEDLEY_LIKELY ( is_array ())) 22006{ 22007JSON_TRY 22008{ 22009return m_data . m_value . array -> at ( idx ); 22010} 22011JSON_CATCH (std:: out_of_range &) 22012{ 22013// create better exception explanation 22014JSON_THROW (out_of_range:: create ( 401 , detail:: concat ( "array index " , std:: to_string ( idx ), " is out of range" ), this )); 22015} // cppcheck-suppress[missingReturn] 22016} 22017else 22018{ 22019JSON_THROW (type_error:: create ( 304 , detail:: concat ( "cannot use at() with " , type_name ()), this )); 22020} 22021} 22022 22023/// @brief access specified object element with bounds checking 22024/// @sa https://json.nlohmann.me/api/basic_json/at/ 22025reference at ( const typename object_t:: key_type & key ) 22026{ 22027// at only works for objects 22028if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 22029{ 22030JSON_THROW (type_error:: create ( 304 , detail:: concat ( "cannot use at() with " , type_name ()), this )); 22031} 22032 22033auto it = m_data . m_value . object -> find ( key ); 22034if ( it == m_data . m_value . object -> end ()) 22035{ 22036JSON_THROW (out_of_range:: create ( 403 , detail:: concat ( "key '" , key , "' not found" ), this )); 22037} 22038return set_parent ( it -> second ); 22039} 22040 22041/// @brief access specified object element with bounds checking 22042/// @sa https://json.nlohmann.me/api/basic_json/at/ 22043template < class KeyType , detail:: enable_if_t < 22044detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22045reference at ( KeyType && key ) 22046{ 22047// at only works for objects 22048if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 22049{ 22050JSON_THROW (type_error:: create ( 304 , detail:: concat ( "cannot use at() with " , type_name ()), this )); 22051} 22052 22053auto it = m_data . m_value . object -> find (std:: forward < KeyType >( key )); 22054if ( it == m_data . m_value . object -> end ()) 22055{ 22056JSON_THROW (out_of_range:: create ( 403 , detail:: concat ( "key '" , string_t (std:: forward < KeyType >( key )), "' not found" ), this )); 22057} 22058return set_parent ( it -> second ); 22059} 22060 22061/// @brief access specified object element with bounds checking 22062/// @sa https://json.nlohmann.me/api/basic_json/at/ 22063const_reference at ( const typename object_t:: key_type & key ) const 22064{ 22065// at only works for objects 22066if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 22067{ 22068JSON_THROW (type_error:: create ( 304 , detail:: concat ( "cannot use at() with " , type_name ()), this )); 22069} 22070 22071auto it = m_data . m_value . object -> find ( key ); 22072if ( it == m_data . m_value . object -> end ()) 22073{ 22074JSON_THROW (out_of_range:: create ( 403 , detail:: concat ( "key '" , key , "' not found" ), this )); 22075} 22076return it -> second ; 22077} 22078 22079/// @brief access specified object element with bounds checking 22080/// @sa https://json.nlohmann.me/api/basic_json/at/ 22081template < class KeyType , detail:: enable_if_t < 22082detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22083const_reference at ( KeyType && key ) const 22084{ 22085// at only works for objects 22086if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 22087{ 22088JSON_THROW (type_error:: create ( 304 , detail:: concat ( "cannot use at() with " , type_name ()), this )); 22089} 22090 22091auto it = m_data . m_value . object -> find (std:: forward < KeyType >( key )); 22092if ( it == m_data . m_value . object -> end ()) 22093{ 22094JSON_THROW (out_of_range:: create ( 403 , detail:: concat ( "key '" , string_t (std:: forward < KeyType >( key )), "' not found" ), this )); 22095} 22096return it -> second ; 22097} 22098 22099/// @brief access specified array element 22100/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 22101reference operator[]( size_type idx ) 22102{ 22103// implicitly convert null value to an empty array 22104if ( is_null ()) 22105{ 22106m_data . m_type = value_t:: array ; 22107m_data . m_value . array = create < array_t >(); 22108assert_invariant (); 22109} 22110 22111// operator[] only works for arrays 22112if ( JSON_HEDLEY_LIKELY ( is_array ())) 22113{ 22114// fill up array with null values if given idx is outside range 22115if ( idx >= m_data . m_value . array -> size ()) 22116{ 22117#if JSON_DIAGNOSTICS 22118// remember array size & capacity before resizing 22119const auto old_size = m_data . m_value . array -> size (); 22120const auto old_capacity = m_data . m_value . array -> capacity (); 22121#endif 22122m_data . m_value . array -> resize ( idx + 1 ); 22123 22124#if JSON_DIAGNOSTICS 22125if ( JSON_HEDLEY_UNLIKELY ( m_data . m_value . array -> capacity () != old_capacity )) 22126{ 22127// capacity has changed: update all parents 22128set_parents (); 22129} 22130else 22131{ 22132// set parent for values added above 22133set_parents ( begin () + static_cast < typename iterator:: difference_type >( old_size ), static_cast < typename iterator:: difference_type >( idx + 1 - old_size )); 22134} 22135#endif 22136assert_invariant (); 22137} 22138 22139return m_data . m_value . array ->operator[]( idx ); 22140} 22141 22142JSON_THROW (type_error:: create ( 305 , detail:: concat ( "cannot use operator[] with a numeric argument with " , type_name ()), this )); 22143} 22144 22145/// @brief access specified array element 22146/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 22147const_reference operator[]( size_type idx ) const 22148{ 22149// const operator[] only works for arrays 22150if ( JSON_HEDLEY_LIKELY ( is_array ())) 22151{ 22152return m_data . m_value . array ->operator[]( idx ); 22153} 22154 22155JSON_THROW (type_error:: create ( 305 , detail:: concat ( "cannot use operator[] with a numeric argument with " , type_name ()), this )); 22156} 22157 22158/// @brief access specified object element 22159/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 22160reference operator[]( typename object_t:: key_type key ) // NOLINT(performance-unnecessary-value-param) 22161{ 22162// implicitly convert null value to an empty object 22163if ( is_null ()) 22164{ 22165m_data . m_type = value_t:: object ; 22166m_data . m_value . object = create < object_t >(); 22167assert_invariant (); 22168} 22169 22170// operator[] only works for objects 22171if ( JSON_HEDLEY_LIKELY ( is_object ())) 22172{ 22173auto result = m_data . m_value . object -> emplace (std:: move ( key ), nullptr ); 22174return set_parent ( result . first -> second ); 22175} 22176 22177JSON_THROW (type_error:: create ( 305 , detail:: concat ( "cannot use operator[] with a string argument with " , type_name ()), this )); 22178} 22179 22180/// @brief access specified object element 22181/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 22182const_reference operator[]( const typename object_t:: key_type & key ) const 22183{ 22184// const operator[] only works for objects 22185if ( JSON_HEDLEY_LIKELY ( is_object ())) 22186{ 22187auto it = m_data . m_value . object -> find ( key ); 22188JSON_ASSERT ( it != m_data . m_value . object -> end ()); 22189return it -> second ; 22190} 22191 22192JSON_THROW (type_error:: create ( 305 , detail:: concat ( "cannot use operator[] with a string argument with " , type_name ()), this )); 22193} 22194 22195// these two functions resolve a (const) char * ambiguity affecting Clang and MSVC 22196// (they seemingly cannot be constrained to resolve the ambiguity) 22197template < typename T > 22198reference operator[]( T * key ) 22199{ 22200return operator []( typename object_t:: key_type ( key )); 22201} 22202 22203template < typename T > 22204const_reference operator[]( T * key ) const 22205{ 22206return operator []( typename object_t:: key_type ( key )); 22207} 22208 22209/// @brief access specified object element 22210/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 22211template < class KeyType , detail:: enable_if_t < 22212detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22213reference operator[]( KeyType && key ) 22214{ 22215// implicitly convert null value to an empty object 22216if ( is_null ()) 22217{ 22218m_data . m_type = value_t:: object ; 22219m_data . m_value . object = create < object_t >(); 22220assert_invariant (); 22221} 22222 22223// operator[] only works for objects 22224if ( JSON_HEDLEY_LIKELY ( is_object ())) 22225{ 22226auto result = m_data . m_value . object -> emplace (std:: forward < KeyType >( key ), nullptr ); 22227return set_parent ( result . first -> second ); 22228} 22229 22230JSON_THROW (type_error:: create ( 305 , detail:: concat ( "cannot use operator[] with a string argument with " , type_name ()), this )); 22231} 22232 22233/// @brief access specified object element 22234/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 22235template < class KeyType , detail:: enable_if_t < 22236detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22237const_reference operator[]( KeyType && key ) const 22238{ 22239// const operator[] only works for objects 22240if ( JSON_HEDLEY_LIKELY ( is_object ())) 22241{ 22242auto it = m_data . m_value . object -> find (std:: forward < KeyType >( key )); 22243JSON_ASSERT ( it != m_data . m_value . object -> end ()); 22244return it -> second ; 22245} 22246 22247JSON_THROW (type_error:: create ( 305 , detail:: concat ( "cannot use operator[] with a string argument with " , type_name ()), this )); 22248} 22249 22250private : 22251template < typename KeyType > 22252using is_comparable_with_object_key = detail:: is_comparable < 22253object_comparator_t , const typename object_t:: key_type &, KeyType >; 22254 22255template < typename ValueType > 22256using value_return_type = std:: conditional < 22257detail:: is_c_string_uncvref < ValueType >:: value , 22258string_t , typename std:: decay < ValueType >:: type >; 22259 22260public : 22261/// @brief access specified object element with default value 22262/// @sa https://json.nlohmann.me/api/basic_json/value/ 22263template < class ValueType , detail:: enable_if_t < 22264!detail:: is_transparent < object_comparator_t >:: value 22265&& detail:: is_getable < basic_json_t , ValueType >:: value 22266&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22267ValueType value ( const typename object_t:: key_type & key , const ValueType & default_value ) const 22268{ 22269// value only works for objects 22270if ( JSON_HEDLEY_LIKELY ( is_object ())) 22271{ 22272// if key is found, return value and given default value otherwise 22273const auto it = find ( key ); 22274if ( it != end ()) 22275{ 22276return it -> template get < ValueType >(); 22277} 22278 22279return default_value ; 22280} 22281 22282JSON_THROW (type_error:: create ( 306 , detail:: concat ( "cannot use value() with " , type_name ()), this )); 22283} 22284 22285/// @brief access specified object element with default value 22286/// @sa https://json.nlohmann.me/api/basic_json/value/ 22287template < class ValueType , class ReturnType = typename value_return_type < ValueType >:: type , 22288detail:: enable_if_t < 22289!detail:: is_transparent < object_comparator_t >:: value 22290&& detail:: is_getable < basic_json_t , ReturnType >:: value 22291&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22292ReturnType value ( const typename object_t:: key_type & key , ValueType && default_value ) const 22293{ 22294// value only works for objects 22295if ( JSON_HEDLEY_LIKELY ( is_object ())) 22296{ 22297// if key is found, return value and given default value otherwise 22298const auto it = find ( key ); 22299if ( it != end ()) 22300{ 22301return it -> template get < ReturnType >(); 22302} 22303 22304return std:: forward < ValueType >( default_value ); 22305} 22306 22307JSON_THROW (type_error:: create ( 306 , detail:: concat ( "cannot use value() with " , type_name ()), this )); 22308} 22309 22310/// @brief access specified object element with default value 22311/// @sa https://json.nlohmann.me/api/basic_json/value/ 22312template < class ValueType , class KeyType , detail:: enable_if_t < 22313detail:: is_transparent < object_comparator_t >:: value 22314&& !detail:: is_json_pointer < KeyType >:: value 22315&& is_comparable_with_object_key < KeyType >:: value 22316&& detail:: is_getable < basic_json_t , ValueType >:: value 22317&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22318ValueType value ( KeyType && key , const ValueType & default_value ) const 22319{ 22320// value only works for objects 22321if ( JSON_HEDLEY_LIKELY ( is_object ())) 22322{ 22323// if key is found, return value and given default value otherwise 22324const auto it = find (std:: forward < KeyType >( key )); 22325if ( it != end ()) 22326{ 22327return it -> template get < ValueType >(); 22328} 22329 22330return default_value ; 22331} 22332 22333JSON_THROW (type_error:: create ( 306 , detail:: concat ( "cannot use value() with " , type_name ()), this )); 22334} 22335 22336/// @brief access specified object element via JSON Pointer with default value 22337/// @sa https://json.nlohmann.me/api/basic_json/value/ 22338template < class ValueType , class KeyType , class ReturnType = typename value_return_type < ValueType >:: type , 22339detail:: enable_if_t < 22340detail:: is_transparent < object_comparator_t >:: value 22341&& !detail:: is_json_pointer < KeyType >:: value 22342&& is_comparable_with_object_key < KeyType >:: value 22343&& detail:: is_getable < basic_json_t , ReturnType >:: value 22344&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22345ReturnType value ( KeyType && key , ValueType && default_value ) const 22346{ 22347// value only works for objects 22348if ( JSON_HEDLEY_LIKELY ( is_object ())) 22349{ 22350// if key is found, return value and given default value otherwise 22351const auto it = find (std:: forward < KeyType >( key )); 22352if ( it != end ()) 22353{ 22354return it -> template get < ReturnType >(); 22355} 22356 22357return std:: forward < ValueType >( default_value ); 22358} 22359 22360JSON_THROW (type_error:: create ( 306 , detail:: concat ( "cannot use value() with " , type_name ()), this )); 22361} 22362 22363/// @brief access specified object element via JSON Pointer with default value 22364/// @sa https://json.nlohmann.me/api/basic_json/value/ 22365template < class ValueType , detail:: enable_if_t < 22366detail:: is_getable < basic_json_t , ValueType >:: value 22367&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22368ValueType value ( const json_pointer & ptr , const ValueType & default_value ) const 22369{ 22370// value only works for objects 22371if ( JSON_HEDLEY_LIKELY ( is_object ())) 22372{ 22373// if pointer resolves a value, return it or use default value 22374JSON_TRY 22375{ 22376return ptr . get_checked ( this ). template get < ValueType >(); 22377} 22378JSON_INTERNAL_CATCH ( out_of_range &) 22379{ 22380return default_value ; 22381} 22382} 22383 22384JSON_THROW (type_error:: create ( 306 , detail:: concat ( "cannot use value() with " , type_name ()), this )); 22385} 22386 22387/// @brief access specified object element via JSON Pointer with default value 22388/// @sa https://json.nlohmann.me/api/basic_json/value/ 22389template < class ValueType , class ReturnType = typename value_return_type < ValueType >:: type , 22390detail:: enable_if_t < 22391detail:: is_getable < basic_json_t , ReturnType >:: value 22392&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22393ReturnType value ( const json_pointer & ptr , ValueType && default_value ) const 22394{ 22395// value only works for objects 22396if ( JSON_HEDLEY_LIKELY ( is_object ())) 22397{ 22398// if pointer resolves a value, return it or use default value 22399JSON_TRY 22400{ 22401return ptr . get_checked ( this ). template get < ReturnType >(); 22402} 22403JSON_INTERNAL_CATCH ( out_of_range &) 22404{ 22405return std:: forward < ValueType >( default_value ); 22406} 22407} 22408 22409JSON_THROW (type_error:: create ( 306 , detail:: concat ( "cannot use value() with " , type_name ()), this )); 22410} 22411 22412template < class ValueType , class BasicJsonType , detail:: enable_if_t < 22413detail:: is_basic_json < BasicJsonType >:: value 22414&& detail:: is_getable < basic_json_t , ValueType >:: value 22415&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22416JSON_HEDLEY_DEPRECATED_FOR ( 3.11.0 , basic_json:: json_pointer or nlohmann:: json_pointer <basic_json:: string_t >) // NOLINT(readability/alt_tokens) 22417ValueType value ( const ::nlohmann:: json_pointer < BasicJsonType >& ptr , const ValueType & default_value ) const 22418{ 22419return value ( ptr . convert (), default_value ); 22420} 22421 22422template < class ValueType , class BasicJsonType , class ReturnType = typename value_return_type < ValueType >:: type , 22423detail:: enable_if_t < 22424detail:: is_basic_json < BasicJsonType >:: value 22425&& detail:: is_getable < basic_json_t , ReturnType >:: value 22426&& !std:: is_same < value_t , detail:: uncvref_t < ValueType >>:: value , int > = 0 > 22427JSON_HEDLEY_DEPRECATED_FOR ( 3.11.0 , basic_json::json_pointer or nlohmann :: json_pointer <basic_json:: string_t >) // NOLINT(readability/alt_tokens) 22428ReturnType value ( const ::nlohmann:: json_pointer < BasicJsonType >& ptr , ValueType && default_value ) const 22429{ 22430return value ( ptr . convert (), std:: forward < ValueType >( default_value )); 22431} 22432 22433/// @brief access the first element 22434/// @sa https://json.nlohmann.me/api/basic_json/front/ 22435reference front () 22436{ 22437return * begin (); 22438} 22439 22440/// @brief access the first element 22441/// @sa https://json.nlohmann.me/api/basic_json/front/ 22442const_reference front () const 22443{ 22444return * cbegin (); 22445} 22446 22447/// @brief access the last element 22448/// @sa https://json.nlohmann.me/api/basic_json/back/ 22449reference back () 22450{ 22451auto tmp = end (); 22452-- tmp ; 22453return * tmp ; 22454} 22455 22456/// @brief access the last element 22457/// @sa https://json.nlohmann.me/api/basic_json/back/ 22458const_reference back () const 22459{ 22460auto tmp = cend (); 22461-- tmp ; 22462return * tmp ; 22463} 22464 22465/// @brief remove element given an iterator 22466/// @sa https://json.nlohmann.me/api/basic_json/erase/ 22467template < class IteratorType , detail:: enable_if_t < 22468std:: is_same < IteratorType , typename basic_json_t:: iterator >:: value || 22469std:: is_same < IteratorType , typename basic_json_t:: const_iterator >:: value , int > = 0 > 22470IteratorType erase ( IteratorType pos ) // NOLINT(performance-unnecessary-value-param) 22471{ 22472// make sure iterator fits the current value 22473if ( JSON_HEDLEY_UNLIKELY ( this != pos . m_object )) 22474{ 22475JSON_THROW (invalid_iterator:: create ( 202 , "iterator does not fit current value" , this )); 22476} 22477 22478IteratorType result = end (); 22479 22480switch ( m_data . m_type ) 22481{ 22482case value_t:: boolean : 22483case value_t:: number_float : 22484case value_t:: number_integer : 22485case value_t:: number_unsigned : 22486case value_t:: string : 22487case value_t:: binary : 22488{ 22489if ( JSON_HEDLEY_UNLIKELY (! pos . m_it . primitive_iterator . is_begin ())) 22490{ 22491JSON_THROW (invalid_iterator:: create ( 205 , "iterator out of range" , this )); 22492} 22493 22494if ( is_string ()) 22495{ 22496AllocatorType < string_t > alloc ; 22497std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , m_data . m_value . string ); 22498std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , m_data . m_value . string , 1 ); 22499m_data . m_value . string = nullptr ; 22500} 22501else if ( is_binary ()) 22502{ 22503AllocatorType < binary_t > alloc ; 22504std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , m_data . m_value . binary ); 22505std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , m_data . m_value . binary , 1 ); 22506m_data . m_value . binary = nullptr ; 22507} 22508 22509m_data . m_type = value_t:: null ; 22510assert_invariant (); 22511break ; 22512} 22513 22514case value_t:: object : 22515{ 22516result . m_it . object_iterator = m_data . m_value . object -> erase ( pos . m_it . object_iterator ); 22517break ; 22518} 22519 22520case value_t:: array : 22521{ 22522result . m_it . array_iterator = m_data . m_value . array -> erase ( pos . m_it . array_iterator ); 22523break ; 22524} 22525 22526case value_t:: null : 22527case value_t:: discarded : 22528default : 22529JSON_THROW (type_error:: create ( 307 , detail:: concat ( "cannot use erase() with " , type_name ()), this )); 22530} 22531 22532return result ; 22533} 22534 22535/// @brief remove elements given an iterator range 22536/// @sa https://json.nlohmann.me/api/basic_json/erase/ 22537template < class IteratorType , detail:: enable_if_t < 22538std:: is_same < IteratorType , typename basic_json_t:: iterator >:: value || 22539std:: is_same < IteratorType , typename basic_json_t:: const_iterator >:: value , int > = 0 > 22540IteratorType erase ( IteratorType first , IteratorType last ) // NOLINT(performance-unnecessary-value-param) 22541{ 22542// make sure iterator fits the current value 22543if ( JSON_HEDLEY_UNLIKELY ( this != first . m_object || this != last . m_object )) 22544{ 22545JSON_THROW (invalid_iterator:: create ( 203 , "iterators do not fit current value" , this )); 22546} 22547 22548IteratorType result = end (); 22549 22550switch ( m_data . m_type ) 22551{ 22552case value_t:: boolean : 22553case value_t:: number_float : 22554case value_t:: number_integer : 22555case value_t:: number_unsigned : 22556case value_t:: string : 22557case value_t:: binary : 22558{ 22559if ( JSON_HEDLEY_LIKELY (! first . m_it . primitive_iterator . is_begin () 22560|| ! last . m_it . primitive_iterator . is_end ())) 22561{ 22562JSON_THROW (invalid_iterator:: create ( 204 , "iterators out of range" , this )); 22563} 22564 22565if ( is_string ()) 22566{ 22567AllocatorType < string_t > alloc ; 22568std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , m_data . m_value . string ); 22569std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , m_data . m_value . string , 1 ); 22570m_data . m_value . string = nullptr ; 22571} 22572else if ( is_binary ()) 22573{ 22574AllocatorType < binary_t > alloc ; 22575std:: allocator_traits <decltype( alloc )>:: destroy ( alloc , m_data . m_value . binary ); 22576std:: allocator_traits <decltype( alloc )>:: deallocate ( alloc , m_data . m_value . binary , 1 ); 22577m_data . m_value . binary = nullptr ; 22578} 22579 22580m_data . m_type = value_t:: null ; 22581assert_invariant (); 22582break ; 22583} 22584 22585case value_t:: object : 22586{ 22587result . m_it . object_iterator = m_data . m_value . object -> erase ( first . m_it . object_iterator , 22588last . m_it . object_iterator ); 22589break ; 22590} 22591 22592case value_t:: array : 22593{ 22594result . m_it . array_iterator = m_data . m_value . array -> erase ( first . m_it . array_iterator , 22595last . m_it . array_iterator ); 22596break ; 22597} 22598 22599case value_t:: null : 22600case value_t:: discarded : 22601default : 22602JSON_THROW (type_error:: create ( 307 , detail:: concat ( "cannot use erase() with " , type_name ()), this )); 22603} 22604 22605return result ; 22606} 22607 22608private : 22609template < typename KeyType , detail:: enable_if_t < 22610detail:: has_erase_with_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22611size_type erase_internal ( KeyType && key ) 22612{ 22613// this erase only works for objects 22614if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 22615{ 22616JSON_THROW (type_error:: create ( 307 , detail:: concat ( "cannot use erase() with " , type_name ()), this )); 22617} 22618 22619return m_data . m_value . object -> erase (std:: forward < KeyType >( key )); 22620} 22621 22622template < typename KeyType , detail:: enable_if_t < 22623!detail:: has_erase_with_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22624size_type erase_internal ( KeyType && key ) 22625{ 22626// this erase only works for objects 22627if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 22628{ 22629JSON_THROW (type_error:: create ( 307 , detail:: concat ( "cannot use erase() with " , type_name ()), this )); 22630} 22631 22632const auto it = m_data . m_value . object -> find (std:: forward < KeyType >( key )); 22633if ( it != m_data . m_value . object -> end ()) 22634{ 22635m_data . m_value . object -> erase ( it ); 22636return 1 ; 22637} 22638return 0 ; 22639} 22640 22641public : 22642 22643/// @brief remove element from a JSON object given a key 22644/// @sa https://json.nlohmann.me/api/basic_json/erase/ 22645size_type erase ( const typename object_t:: key_type & key ) 22646{ 22647// the indirection via erase_internal() is added to avoid making this 22648// function a template and thus de-rank it during overload resolution 22649return erase_internal ( key ); 22650} 22651 22652/// @brief remove element from a JSON object given a key 22653/// @sa https://json.nlohmann.me/api/basic_json/erase/ 22654template < class KeyType , detail:: enable_if_t < 22655detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22656size_type erase ( KeyType && key ) 22657{ 22658return erase_internal (std:: forward < KeyType >( key )); 22659} 22660 22661/// @brief remove element from a JSON array given an index 22662/// @sa https://json.nlohmann.me/api/basic_json/erase/ 22663void erase ( const size_type idx ) 22664{ 22665// this erase only works for arrays 22666if ( JSON_HEDLEY_LIKELY ( is_array ())) 22667{ 22668if ( JSON_HEDLEY_UNLIKELY ( idx >= size ())) 22669{ 22670JSON_THROW (out_of_range:: create ( 401 , detail:: concat ( "array index " , std:: to_string ( idx ), " is out of range" ), this )); 22671} 22672 22673m_data . m_value . array -> erase ( m_data . m_value . array -> begin () + static_cast < difference_type >( idx )); 22674} 22675else 22676{ 22677JSON_THROW (type_error:: create ( 307 , detail:: concat ( "cannot use erase() with " , type_name ()), this )); 22678} 22679} 22680 22681/// @} 22682 22683//////////// 22684// lookup // 22685//////////// 22686 22687/// @name lookup 22688/// @{ 22689 22690/// @brief find an element in a JSON object 22691/// @sa https://json.nlohmann.me/api/basic_json/find/ 22692iterator find ( const typename object_t:: key_type & key ) 22693{ 22694auto result = end (); 22695 22696if ( is_object ()) 22697{ 22698result . m_it . object_iterator = m_data . m_value . object -> find ( key ); 22699} 22700 22701return result ; 22702} 22703 22704/// @brief find an element in a JSON object 22705/// @sa https://json.nlohmann.me/api/basic_json/find/ 22706const_iterator find ( const typename object_t:: key_type & key ) const 22707{ 22708auto result = cend (); 22709 22710if ( is_object ()) 22711{ 22712result . m_it . object_iterator = m_data . m_value . object -> find ( key ); 22713} 22714 22715return result ; 22716} 22717 22718/// @brief find an element in a JSON object 22719/// @sa https://json.nlohmann.me/api/basic_json/find/ 22720template < class KeyType , detail:: enable_if_t < 22721detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22722iterator find ( KeyType && key ) 22723{ 22724auto result = end (); 22725 22726if ( is_object ()) 22727{ 22728result . m_it . object_iterator = m_data . m_value . object -> find (std:: forward < KeyType >( key )); 22729} 22730 22731return result ; 22732} 22733 22734/// @brief find an element in a JSON object 22735/// @sa https://json.nlohmann.me/api/basic_json/find/ 22736template < class KeyType , detail:: enable_if_t < 22737detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22738const_iterator find ( KeyType && key ) const 22739{ 22740auto result = cend (); 22741 22742if ( is_object ()) 22743{ 22744result . m_it . object_iterator = m_data . m_value . object -> find (std:: forward < KeyType >( key )); 22745} 22746 22747return result ; 22748} 22749 22750/// @brief returns the number of occurrences of a key in a JSON object 22751/// @sa https://json.nlohmann.me/api/basic_json/count/ 22752size_type count ( const typename object_t:: key_type & key ) const 22753{ 22754// return 0 for all nonobject types 22755return is_object () ? m_data . m_value . object -> count ( key ) : 0 ; 22756} 22757 22758/// @brief returns the number of occurrences of a key in a JSON object 22759/// @sa https://json.nlohmann.me/api/basic_json/count/ 22760template < class KeyType , detail:: enable_if_t < 22761detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22762size_type count ( KeyType && key ) const 22763{ 22764// return 0 for all nonobject types 22765return is_object () ? m_data . m_value . object -> count (std:: forward < KeyType >( key )) : 0 ; 22766} 22767 22768/// @brief check the existence of an element in a JSON object 22769/// @sa https://json.nlohmann.me/api/basic_json/contains/ 22770bool contains ( const typename object_t:: key_type & key ) const 22771{ 22772return is_object () && m_data . m_value . object -> find ( key ) != m_data . m_value . object -> end (); 22773} 22774 22775/// @brief check the existence of an element in a JSON object 22776/// @sa https://json.nlohmann.me/api/basic_json/contains/ 22777template < class KeyType , detail:: enable_if_t < 22778detail:: is_usable_as_basic_json_key_type < basic_json_t , KeyType >:: value , int > = 0 > 22779bool contains ( KeyType && key ) const 22780{ 22781return is_object () && m_data . m_value . object -> find (std:: forward < KeyType >( key )) != m_data . m_value . object -> end (); 22782} 22783 22784/// @brief check the existence of an element in a JSON object given a JSON pointer 22785/// @sa https://json.nlohmann.me/api/basic_json/contains/ 22786bool contains ( const json_pointer & ptr ) const 22787{ 22788return ptr . contains ( this ); 22789} 22790 22791template < typename BasicJsonType , detail:: enable_if_t <detail:: is_basic_json < BasicJsonType >:: value , int > = 0 > 22792JSON_HEDLEY_DEPRECATED_FOR ( 3.11.0 , basic_json::json_pointer or nlohmann :: json_pointer <basic_json:: string_t >) // NOLINT(readability/alt_tokens) 22793bool contains ( const typename ::nlohmann:: json_pointer < BasicJsonType >& ptr ) const 22794{ 22795return ptr . contains ( this ); 22796} 22797 22798/// @} 22799 22800/////////////// 22801// iterators // 22802/////////////// 22803 22804/// @name iterators 22805/// @{ 22806 22807/// @brief returns an iterator to the first element 22808/// @sa https://json.nlohmann.me/api/basic_json/begin/ 22809iterator begin () noexcept 22810{ 22811iterator result ( this ); 22812result . set_begin (); 22813return result ; 22814} 22815 22816/// @brief returns an iterator to the first element 22817/// @sa https://json.nlohmann.me/api/basic_json/begin/ 22818const_iterator begin () const noexcept 22819{ 22820return cbegin (); 22821} 22822 22823/// @brief returns a const iterator to the first element 22824/// @sa https://json.nlohmann.me/api/basic_json/cbegin/ 22825const_iterator cbegin () const noexcept 22826{ 22827const_iterator result ( this ); 22828result . set_begin (); 22829return result ; 22830} 22831 22832/// @brief returns an iterator to one past the last element 22833/// @sa https://json.nlohmann.me/api/basic_json/end/ 22834iterator end () noexcept 22835{ 22836iterator result ( this ); 22837result . set_end (); 22838return result ; 22839} 22840 22841/// @brief returns an iterator to one past the last element 22842/// @sa https://json.nlohmann.me/api/basic_json/end/ 22843const_iterator end () const noexcept 22844{ 22845return cend (); 22846} 22847 22848/// @brief returns an iterator to one past the last element 22849/// @sa https://json.nlohmann.me/api/basic_json/cend/ 22850const_iterator cend () const noexcept 22851{ 22852const_iterator result ( this ); 22853result . set_end (); 22854return result ; 22855} 22856 22857/// @brief returns an iterator to the reverse-beginning 22858/// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22859reverse_iterator rbegin () noexcept 22860{ 22861return reverse_iterator ( end ()); 22862} 22863 22864/// @brief returns an iterator to the reverse-beginning 22865/// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22866const_reverse_iterator rbegin () const noexcept 22867{ 22868return crbegin (); 22869} 22870 22871/// @brief returns an iterator to the reverse-end 22872/// @sa https://json.nlohmann.me/api/basic_json/rend/ 22873reverse_iterator rend () noexcept 22874{ 22875return reverse_iterator ( begin ()); 22876} 22877 22878/// @brief returns an iterator to the reverse-end 22879/// @sa https://json.nlohmann.me/api/basic_json/rend/ 22880const_reverse_iterator rend () const noexcept 22881{ 22882return crend (); 22883} 22884 22885/// @brief returns a const reverse iterator to the last element 22886/// @sa https://json.nlohmann.me/api/basic_json/crbegin/ 22887const_reverse_iterator crbegin () const noexcept 22888{ 22889return const_reverse_iterator ( cend ()); 22890} 22891 22892/// @brief returns a const reverse iterator to one before the first 22893/// @sa https://json.nlohmann.me/api/basic_json/crend/ 22894const_reverse_iterator crend () const noexcept 22895{ 22896return const_reverse_iterator ( cbegin ()); 22897} 22898 22899public : 22900/// @brief wrapper to access iterator member functions in range-based for 22901/// @sa https://json.nlohmann.me/api/basic_json/items/ 22902/// @deprecated This function is deprecated since 3.1.0 and will be removed in 22903/// version 4.0.0 of the library. Please use @ref items() instead; 22904/// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22905JSON_HEDLEY_DEPRECATED_FOR ( 3.1 . 0 , items ()) 22906static iteration_proxy < iterator > iterator_wrapper ( reference ref ) noexcept 22907{ 22908return ref . items (); 22909} 22910 22911/// @brief wrapper to access iterator member functions in range-based for 22912/// @sa https://json.nlohmann.me/api/basic_json/items/ 22913/// @deprecated This function is deprecated since 3.1.0 and will be removed in 22914/// version 4.0.0 of the library. Please use @ref items() instead; 22915/// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22916JSON_HEDLEY_DEPRECATED_FOR ( 3.1 . 0 , items ()) 22917static iteration_proxy < const_iterator > iterator_wrapper ( const_reference ref ) noexcept 22918{ 22919return ref . items (); 22920} 22921 22922/// @brief helper to access iterator member functions in range-based for 22923/// @sa https://json.nlohmann.me/api/basic_json/items/ 22924iteration_proxy < iterator > items () noexcept 22925{ 22926return iteration_proxy < iterator >(* this ); 22927} 22928 22929/// @brief helper to access iterator member functions in range-based for 22930/// @sa https://json.nlohmann.me/api/basic_json/items/ 22931iteration_proxy < const_iterator > items () const noexcept 22932{ 22933return iteration_proxy < const_iterator >(* this ); 22934} 22935 22936/// @} 22937 22938////////////// 22939// capacity // 22940////////////// 22941 22942/// @name capacity 22943/// @{ 22944 22945/// @brief checks whether the container is empty. 22946/// @sa https://json.nlohmann.me/api/basic_json/empty/ 22947bool empty () const noexcept 22948{ 22949switch ( m_data . m_type ) 22950{ 22951case value_t:: null : 22952{ 22953// null values are empty 22954return true; 22955} 22956 22957case value_t:: array : 22958{ 22959// delegate call to array_t::empty() 22960return m_data . m_value . array -> empty (); 22961} 22962 22963case value_t:: object : 22964{ 22965// delegate call to object_t::empty() 22966return m_data . m_value . object -> empty (); 22967} 22968 22969case value_t:: string : 22970case value_t:: boolean : 22971case value_t:: number_integer : 22972case value_t:: number_unsigned : 22973case value_t:: number_float : 22974case value_t:: binary : 22975case value_t:: discarded : 22976default : 22977{ 22978// all other types are nonempty 22979return false; 22980} 22981} 22982} 22983 22984/// @brief returns the number of elements 22985/// @sa https://json.nlohmann.me/api/basic_json/size/ 22986size_type size () const noexcept 22987{ 22988switch ( m_data . m_type ) 22989{ 22990case value_t:: null : 22991{ 22992// null values are empty 22993return 0 ; 22994} 22995 22996case value_t:: array : 22997{ 22998// delegate call to array_t::size() 22999return m_data . m_value . array -> size (); 23000} 23001 23002case value_t:: object : 23003{ 23004// delegate call to object_t::size() 23005return m_data . m_value . object -> size (); 23006} 23007 23008case value_t:: string : 23009case value_t:: boolean : 23010case value_t:: number_integer : 23011case value_t:: number_unsigned : 23012case value_t:: number_float : 23013case value_t:: binary : 23014case value_t:: discarded : 23015default : 23016{ 23017// all other types have size 1 23018return 1 ; 23019} 23020} 23021} 23022 23023/// @brief returns the maximum possible number of elements 23024/// @sa https://json.nlohmann.me/api/basic_json/max_size/ 23025size_type max_size () const noexcept 23026{ 23027switch ( m_data . m_type ) 23028{ 23029case value_t:: array : 23030{ 23031// delegate call to array_t::max_size() 23032return m_data . m_value . array -> max_size (); 23033} 23034 23035case value_t:: object : 23036{ 23037// delegate call to object_t::max_size() 23038return m_data . m_value . object -> max_size (); 23039} 23040 23041case value_t:: null : 23042case value_t:: string : 23043case value_t:: boolean : 23044case value_t:: number_integer : 23045case value_t:: number_unsigned : 23046case value_t:: number_float : 23047case value_t:: binary : 23048case value_t:: discarded : 23049default : 23050{ 23051// all other types have max_size() == size() 23052return size (); 23053} 23054} 23055} 23056 23057/// @} 23058 23059/////////////// 23060// modifiers // 23061/////////////// 23062 23063/// @name modifiers 23064/// @{ 23065 23066/// @brief clears the contents 23067/// @sa https://json.nlohmann.me/api/basic_json/clear/ 23068void clear () noexcept 23069{ 23070switch ( m_data . m_type ) 23071{ 23072case value_t:: number_integer : 23073{ 23074m_data . m_value . number_integer = 0 ; 23075break ; 23076} 23077 23078case value_t:: number_unsigned : 23079{ 23080m_data . m_value . number_unsigned = 0 ; 23081break ; 23082} 23083 23084case value_t:: number_float : 23085{ 23086m_data . m_value . number_float = 0.0 ; 23087break ; 23088} 23089 23090case value_t:: boolean : 23091{ 23092m_data . m_value . boolean = false; 23093break ; 23094} 23095 23096case value_t:: string : 23097{ 23098m_data . m_value . string -> clear (); 23099break ; 23100} 23101 23102case value_t:: binary : 23103{ 23104m_data . m_value . binary -> clear (); 23105break ; 23106} 23107 23108case value_t:: array : 23109{ 23110m_data . m_value . array -> clear (); 23111break ; 23112} 23113 23114case value_t:: object : 23115{ 23116m_data . m_value . object -> clear (); 23117break ; 23118} 23119 23120case value_t:: null : 23121case value_t:: discarded : 23122default : 23123break ; 23124} 23125} 23126 23127/// @brief add an object to an array 23128/// @sa https://json.nlohmann.me/api/basic_json/push_back/ 23129void push_back ( basic_json && val ) 23130{ 23131// push_back only works for null objects or arrays 23132if ( JSON_HEDLEY_UNLIKELY (!( is_null () || is_array ()))) 23133{ 23134JSON_THROW (type_error:: create ( 308 , detail:: concat ( "cannot use push_back() with " , type_name ()), this )); 23135} 23136 23137// transform null object into an array 23138if ( is_null ()) 23139{ 23140m_data . m_type = value_t:: array ; 23141m_data . m_value = value_t:: array ; 23142assert_invariant (); 23143} 23144 23145// add element to array (move semantics) 23146const auto old_capacity = m_data . m_value . array -> capacity (); 23147m_data . m_value . array -> push_back (std:: move ( val )); 23148set_parent ( m_data . m_value . array -> back (), old_capacity ); 23149// if val is moved from, basic_json move constructor marks it null, so we do not call the destructor 23150} 23151 23152/// @brief add an object to an array 23153/// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 23154reference operator+=( basic_json && val ) 23155{ 23156push_back (std:: move ( val )); 23157return * this ; 23158} 23159 23160/// @brief add an object to an array 23161/// @sa https://json.nlohmann.me/api/basic_json/push_back/ 23162void push_back ( const basic_json & val ) 23163{ 23164// push_back only works for null objects or arrays 23165if ( JSON_HEDLEY_UNLIKELY (!( is_null () || is_array ()))) 23166{ 23167JSON_THROW (type_error:: create ( 308 , detail:: concat ( "cannot use push_back() with " , type_name ()), this )); 23168} 23169 23170// transform null object into an array 23171if ( is_null ()) 23172{ 23173m_data . m_type = value_t:: array ; 23174m_data . m_value = value_t:: array ; 23175assert_invariant (); 23176} 23177 23178// add element to array 23179const auto old_capacity = m_data . m_value . array -> capacity (); 23180m_data . m_value . array -> push_back ( val ); 23181set_parent ( m_data . m_value . array -> back (), old_capacity ); 23182} 23183 23184/// @brief add an object to an array 23185/// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 23186reference operator+=( const basic_json & val ) 23187{ 23188push_back ( val ); 23189return * this ; 23190} 23191 23192/// @brief add an object to an object 23193/// @sa https://json.nlohmann.me/api/basic_json/push_back/ 23194void push_back ( const typename object_t:: value_type & val ) 23195{ 23196// push_back only works for null objects or objects 23197if ( JSON_HEDLEY_UNLIKELY (!( is_null () || is_object ()))) 23198{ 23199JSON_THROW (type_error:: create ( 308 , detail:: concat ( "cannot use push_back() with " , type_name ()), this )); 23200} 23201 23202// transform null object into an object 23203if ( is_null ()) 23204{ 23205m_data . m_type = value_t:: object ; 23206m_data . m_value = value_t:: object ; 23207assert_invariant (); 23208} 23209 23210// add element to object 23211auto res = m_data . m_value . object -> insert ( val ); 23212set_parent ( res . first -> second ); 23213} 23214 23215/// @brief add an object to an object 23216/// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 23217reference operator+=( const typename object_t:: value_type & val ) 23218{ 23219push_back ( val ); 23220return * this ; 23221} 23222 23223/// @brief add an object to an object 23224/// @sa https://json.nlohmann.me/api/basic_json/push_back/ 23225void push_back ( initializer_list_t init ) 23226{ 23227if ( is_object () && init . size () == 2 && (* init . begin ())-> is_string ()) 23228{ 23229basic_json && key = init . begin ()-> moved_or_copied (); 23230push_back ( typename object_t:: value_type ( 23231std:: move ( key . get_ref < string_t &>()), ( init . begin () + 1 )-> moved_or_copied ())); 23232} 23233else 23234{ 23235push_back ( basic_json ( init )); 23236} 23237} 23238 23239/// @brief add an object to an object 23240/// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 23241reference operator+=( initializer_list_t init ) 23242{ 23243push_back ( init ); 23244return * this ; 23245} 23246 23247/// @brief add an object to an array 23248/// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ 23249template < class ... Args > 23250reference emplace_back ( Args && ... args ) 23251{ 23252// emplace_back only works for null objects or arrays 23253if ( JSON_HEDLEY_UNLIKELY (!( is_null () || is_array ()))) 23254{ 23255JSON_THROW (type_error:: create ( 311 , detail:: concat ( "cannot use emplace_back() with " , type_name ()), this )); 23256} 23257 23258// transform null object into an array 23259if ( is_null ()) 23260{ 23261m_data . m_type = value_t:: array ; 23262m_data . m_value = value_t:: array ; 23263assert_invariant (); 23264} 23265 23266// add element to array (perfect forwarding) 23267const auto old_capacity = m_data . m_value . array -> capacity (); 23268m_data . m_value . array -> emplace_back (std:: forward < Args >( args )...); 23269return set_parent ( m_data . m_value . array -> back (), old_capacity ); 23270} 23271 23272/// @brief add an object to an object if key does not exist 23273/// @sa https://json.nlohmann.me/api/basic_json/emplace/ 23274template < class ... Args > 23275std:: pair < iterator , bool > emplace ( Args && ... args ) 23276{ 23277// emplace only works for null objects or arrays 23278if ( JSON_HEDLEY_UNLIKELY (!( is_null () || is_object ()))) 23279{ 23280JSON_THROW (type_error:: create ( 311 , detail:: concat ( "cannot use emplace() with " , type_name ()), this )); 23281} 23282 23283// transform null object into an object 23284if ( is_null ()) 23285{ 23286m_data . m_type = value_t:: object ; 23287m_data . m_value = value_t:: object ; 23288assert_invariant (); 23289} 23290 23291// add element to array (perfect forwarding) 23292auto res = m_data . m_value . object -> emplace (std:: forward < Args >( args )...); 23293set_parent ( res . first -> second ); 23294 23295// create result iterator and set iterator to the result of emplace 23296auto it = begin (); 23297it . m_it . object_iterator = res . first ; 23298 23299// return pair of iterator and boolean 23300return { it , res . second }; 23301} 23302 23303/// Helper for insertion of an iterator 23304/// @note: This uses std::distance to support GCC 4.8, 23305/// see https://github.com/nlohmann/json/pull/1257 23306template < typename ... Args > 23307iterator insert_iterator ( const_iterator pos , Args && ... args ) // NOLINT(performance-unnecessary-value-param) 23308{ 23309iterator result ( this ); 23310JSON_ASSERT ( m_data . m_value . array != nullptr ); 23311 23312auto insert_pos = std:: distance ( m_data . m_value . array -> begin (), pos . m_it . array_iterator ); 23313m_data . m_value . array -> insert ( pos . m_it . array_iterator , std:: forward < Args >( args )...); 23314result . m_it . array_iterator = m_data . m_value . array -> begin () + insert_pos ; 23315 23316// This could have been written as: 23317// result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); 23318// but the return value of insert is missing in GCC 4.8, so it is written this way instead. 23319 23320set_parents (); 23321return result ; 23322} 23323 23324/// @brief inserts element into array 23325/// @sa https://json.nlohmann.me/api/basic_json/insert/ 23326iterator insert ( const_iterator pos , const basic_json & val ) // NOLINT(performance-unnecessary-value-param) 23327{ 23328// insert only works for arrays 23329if ( JSON_HEDLEY_LIKELY ( is_array ())) 23330{ 23331// check if iterator pos fits to this JSON value 23332if ( JSON_HEDLEY_UNLIKELY ( pos . m_object != this )) 23333{ 23334JSON_THROW (invalid_iterator:: create ( 202 , "iterator does not fit current value" , this )); 23335} 23336 23337// insert to array and return iterator 23338return insert_iterator ( pos , val ); 23339} 23340 23341JSON_THROW (type_error:: create ( 309 , detail:: concat ( "cannot use insert() with " , type_name ()), this )); 23342} 23343 23344/// @brief inserts element into array 23345/// @sa https://json.nlohmann.me/api/basic_json/insert/ 23346iterator insert ( const_iterator pos , basic_json && val ) // NOLINT(performance-unnecessary-value-param) 23347{ 23348return insert ( pos , val ); 23349} 23350 23351/// @brief inserts copies of element into array 23352/// @sa https://json.nlohmann.me/api/basic_json/insert/ 23353iterator insert ( const_iterator pos , size_type cnt , const basic_json & val ) // NOLINT(performance-unnecessary-value-param) 23354{ 23355// insert only works for arrays 23356if ( JSON_HEDLEY_LIKELY ( is_array ())) 23357{ 23358// check if iterator pos fits to this JSON value 23359if ( JSON_HEDLEY_UNLIKELY ( pos . m_object != this )) 23360{ 23361JSON_THROW (invalid_iterator:: create ( 202 , "iterator does not fit current value" , this )); 23362} 23363 23364// insert to array and return iterator 23365return insert_iterator ( pos , cnt , val ); 23366} 23367 23368JSON_THROW (type_error:: create ( 309 , detail:: concat ( "cannot use insert() with " , type_name ()), this )); 23369} 23370 23371/// @brief inserts range of elements into array 23372/// @sa https://json.nlohmann.me/api/basic_json/insert/ 23373iterator insert ( const_iterator pos , const_iterator first , const_iterator last ) // NOLINT(performance-unnecessary-value-param) 23374{ 23375// insert only works for arrays 23376if ( JSON_HEDLEY_UNLIKELY (! is_array ())) 23377{ 23378JSON_THROW (type_error:: create ( 309 , detail:: concat ( "cannot use insert() with " , type_name ()), this )); 23379} 23380 23381// check if iterator pos fits to this JSON value 23382if ( JSON_HEDLEY_UNLIKELY ( pos . m_object != this )) 23383{ 23384JSON_THROW (invalid_iterator:: create ( 202 , "iterator does not fit current value" , this )); 23385} 23386 23387// check if range iterators belong to the same JSON object 23388if ( JSON_HEDLEY_UNLIKELY ( first . m_object != last . m_object )) 23389{ 23390JSON_THROW (invalid_iterator:: create ( 210 , "iterators do not fit" , this )); 23391} 23392 23393if ( JSON_HEDLEY_UNLIKELY ( first . m_object == this )) 23394{ 23395JSON_THROW (invalid_iterator:: create ( 211 , "passed iterators may not belong to container" , this )); 23396} 23397 23398// insert to array and return iterator 23399return insert_iterator ( pos , first . m_it . array_iterator , last . m_it . array_iterator ); 23400} 23401 23402/// @brief inserts elements from initializer list into array 23403/// @sa https://json.nlohmann.me/api/basic_json/insert/ 23404iterator insert ( const_iterator pos , initializer_list_t ilist ) // NOLINT(performance-unnecessary-value-param) 23405{ 23406// insert only works for arrays 23407if ( JSON_HEDLEY_UNLIKELY (! is_array ())) 23408{ 23409JSON_THROW (type_error:: create ( 309 , detail:: concat ( "cannot use insert() with " , type_name ()), this )); 23410} 23411 23412// check if iterator pos fits to this JSON value 23413if ( JSON_HEDLEY_UNLIKELY ( pos . m_object != this )) 23414{ 23415JSON_THROW (invalid_iterator:: create ( 202 , "iterator does not fit current value" , this )); 23416} 23417 23418// insert to array and return iterator 23419return insert_iterator ( pos , ilist . begin (), ilist . end ()); 23420} 23421 23422/// @brief inserts range of elements into object 23423/// @sa https://json.nlohmann.me/api/basic_json/insert/ 23424void insert ( const_iterator first , const_iterator last ) // NOLINT(performance-unnecessary-value-param) 23425{ 23426// insert only works for objects 23427if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 23428{ 23429JSON_THROW (type_error:: create ( 309 , detail:: concat ( "cannot use insert() with " , type_name ()), this )); 23430} 23431 23432// check if range iterators belong to the same JSON object 23433if ( JSON_HEDLEY_UNLIKELY ( first . m_object != last . m_object )) 23434{ 23435JSON_THROW (invalid_iterator:: create ( 210 , "iterators do not fit" , this )); 23436} 23437 23438// passed iterators must belong to objects 23439if ( JSON_HEDLEY_UNLIKELY (! first . m_object -> is_object ())) 23440{ 23441JSON_THROW (invalid_iterator:: create ( 202 , "iterators first and last must point to objects" , this )); 23442} 23443 23444m_data . m_value . object -> insert ( first . m_it . object_iterator , last . m_it . object_iterator ); 23445set_parents (); 23446} 23447 23448/// @brief updates a JSON object from another object, overwriting existing keys 23449/// @sa https://json.nlohmann.me/api/basic_json/update/ 23450void update ( const_reference j , bool merge_objects = false) 23451{ 23452update ( j . begin (), j . end (), merge_objects ); 23453} 23454 23455/// @brief updates a JSON object from another object, overwriting existing keys 23456/// @sa https://json.nlohmann.me/api/basic_json/update/ 23457void update ( const_iterator first , const_iterator last , bool merge_objects = false) // NOLINT(performance-unnecessary-value-param) 23458{ 23459// implicitly convert null value to an empty object 23460if ( is_null ()) 23461{ 23462m_data . m_type = value_t:: object ; 23463m_data . m_value . object = create < object_t >(); 23464assert_invariant (); 23465} 23466 23467if ( JSON_HEDLEY_UNLIKELY (! is_object ())) 23468{ 23469JSON_THROW (type_error:: create ( 312 , detail:: concat ( "cannot use update() with " , type_name ()), this )); 23470} 23471 23472// check if range iterators belong to the same JSON object 23473if ( JSON_HEDLEY_UNLIKELY ( first . m_object != last . m_object )) 23474{ 23475JSON_THROW (invalid_iterator:: create ( 210 , "iterators do not fit" , this )); 23476} 23477 23478// passed iterators must belong to objects 23479if ( JSON_HEDLEY_UNLIKELY (! first . m_object -> is_object ())) 23480{ 23481JSON_THROW (type_error:: create ( 312 , detail:: concat ( "cannot use update() with " , first . m_object -> type_name ()), first . m_object )); 23482} 23483 23484for ( auto it = first ; it != last ; ++ it ) 23485{ 23486if ( merge_objects && it . value (). is_object ()) 23487{ 23488auto it2 = m_data . m_value . object -> find ( it . key ()); 23489if ( it2 != m_data . m_value . object -> end ()) 23490{ 23491it2 -> second . update ( it . value (), true); 23492continue ; 23493} 23494} 23495m_data . m_value . object ->operator[]( it . key ()) = it . value (); 23496#if JSON_DIAGNOSTICS 23497m_data . m_value . object ->operator[]( it . key ()). m_parent = this ; 23498#endif 23499} 23500} 23501 23502/// @brief exchanges the values 23503/// @sa https://json.nlohmann.me/api/basic_json/swap/ 23504void swap ( reference other ) noexcept ( 23505std:: is_nothrow_move_constructible < value_t >:: value && 23506std:: is_nothrow_move_assignable < value_t >:: value && 23507std:: is_nothrow_move_constructible < json_value >:: value && // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23508std:: is_nothrow_move_assignable < json_value >:: value 23509) 23510{ 23511std:: swap ( m_data . m_type , other . m_data . m_type ); 23512std:: swap ( m_data . m_value , other . m_data . m_value ); 23513 23514set_parents (); 23515other . set_parents (); 23516assert_invariant (); 23517} 23518 23519/// @brief exchanges the values 23520/// @sa https://json.nlohmann.me/api/basic_json/swap/ 23521friend void swap ( reference left , reference right ) noexcept ( 23522std:: is_nothrow_move_constructible < value_t >:: value && 23523std:: is_nothrow_move_assignable < value_t >:: value && 23524std:: is_nothrow_move_constructible < json_value >:: value && // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23525std:: is_nothrow_move_assignable < json_value >:: value 23526) 23527{ 23528left . swap ( right ); 23529} 23530 23531/// @brief exchanges the values 23532/// @sa https://json.nlohmann.me/api/basic_json/swap/ 23533void swap ( array_t & other ) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23534{ 23535// swap only works for arrays 23536if ( JSON_HEDLEY_LIKELY ( is_array ())) 23537{ 23538using std:: swap ; 23539swap (*( m_data . m_value . array ), other ); 23540} 23541else 23542{ 23543JSON_THROW (type_error:: create ( 310 , detail:: concat ( "cannot use swap(array_t&) with " , type_name ()), this )); 23544} 23545} 23546 23547/// @brief exchanges the values 23548/// @sa https://json.nlohmann.me/api/basic_json/swap/ 23549void swap ( object_t & other ) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23550{ 23551// swap only works for objects 23552if ( JSON_HEDLEY_LIKELY ( is_object ())) 23553{ 23554using std:: swap ; 23555swap (*( m_data . m_value . object ), other ); 23556} 23557else 23558{ 23559JSON_THROW (type_error:: create ( 310 , detail:: concat ( "cannot use swap(object_t&) with " , type_name ()), this )); 23560} 23561} 23562 23563/// @brief exchanges the values 23564/// @sa https://json.nlohmann.me/api/basic_json/swap/ 23565void swap ( string_t & other ) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23566{ 23567// swap only works for strings 23568if ( JSON_HEDLEY_LIKELY ( is_string ())) 23569{ 23570using std:: swap ; 23571swap (*( m_data . m_value . string ), other ); 23572} 23573else 23574{ 23575JSON_THROW (type_error:: create ( 310 , detail:: concat ( "cannot use swap(string_t&) with " , type_name ()), this )); 23576} 23577} 23578 23579/// @brief exchanges the values 23580/// @sa https://json.nlohmann.me/api/basic_json/swap/ 23581void swap ( binary_t & other ) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23582{ 23583// swap only works for strings 23584if ( JSON_HEDLEY_LIKELY ( is_binary ())) 23585{ 23586using std:: swap ; 23587swap (*( m_data . m_value . binary ), other ); 23588} 23589else 23590{ 23591JSON_THROW (type_error:: create ( 310 , detail:: concat ( "cannot use swap(binary_t&) with " , type_name ()), this )); 23592} 23593} 23594 23595/// @brief exchanges the values 23596/// @sa https://json.nlohmann.me/api/basic_json/swap/ 23597void swap ( typename binary_t:: container_type & other ) // NOLINT(bugprone-exception-escape) 23598{ 23599// swap only works for strings 23600if ( JSON_HEDLEY_LIKELY ( is_binary ())) 23601{ 23602using std:: swap ; 23603swap (*( m_data . m_value . binary ), other ); 23604} 23605else 23606{ 23607JSON_THROW (type_error:: create ( 310 , detail:: concat ( "cannot use swap(binary_t::container_type&) with " , type_name ()), this )); 23608} 23609} 23610 23611/// @} 23612 23613////////////////////////////////////////// 23614// lexicographical comparison operators // 23615////////////////////////////////////////// 23616 23617/// @name lexicographical comparison operators 23618/// @{ 23619 23620// note parentheses around operands are necessary; see 23621// https://github.com/nlohmann/json/issues/1530 23622#define JSON_IMPLEMENT_OPERATOR ( op , null_result , unordered_result , default_result ) \ 23623const auto lhs_type = lhs.type(); \ 23624const auto rhs_type = rhs.type(); \ 23625\ 23626if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \ 23627{ \ 23628switch ( lhs_type ) \ 23629{ \ 23630case value_t:: array : \ 23631return (* lhs . m_data . m_value . array ) op (* rhs . m_data . m_value . array ); \ 23632\ 23633case value_t:: object : \ 23634return (* lhs . m_data . m_value . object ) op (* rhs . m_data . m_value . object ); \ 23635\ 23636case value_t:: null : \ 23637return ( null_result ); \ 23638\ 23639case value_t:: string : \ 23640return (* lhs . m_data . m_value . string ) op (* rhs . m_data . m_value . string ); \ 23641\ 23642case value_t:: boolean : \ 23643return ( lhs . m_data . m_value . boolean ) op ( rhs . m_data . m_value . boolean ); \ 23644\ 23645case value_t:: number_integer : \ 23646return ( lhs . m_data . m_value . number_integer ) op ( rhs . m_data . m_value . number_integer ); \ 23647\ 23648case value_t:: number_unsigned : \ 23649return ( lhs . m_data . m_value . number_unsigned ) op ( rhs . m_data . m_value . number_unsigned ); \ 23650\ 23651case value_t:: number_float : \ 23652return ( lhs . m_data . m_value . number_float ) op ( rhs . m_data . m_value . number_float ); \ 23653\ 23654case value_t:: binary : \ 23655return (* lhs . m_data . m_value . binary ) op (* rhs . m_data . m_value . binary ); \ 23656\ 23657case value_t:: discarded : \ 23658default : \ 23659return ( unordered_result ); \ 23660} \ 23661} \ 23662else if ( lhs_type == value_t:: number_integer && rhs_type == value_t:: number_float ) \ 23663{ \ 23664return static_cast < number_float_t >( lhs . m_data . m_value . number_integer ) op rhs . m_data . m_value . number_float ; \ 23665} \ 23666else if ( lhs_type == value_t:: number_float && rhs_type == value_t:: number_integer ) \ 23667{ \ 23668return lhs . m_data . m_value . number_float op static_cast < number_float_t >( rhs . m_data . m_value . number_integer ); \ 23669} \ 23670else if ( lhs_type == value_t:: number_unsigned && rhs_type == value_t:: number_float ) \ 23671{ \ 23672return static_cast < number_float_t >( lhs . m_data . m_value . number_unsigned ) op rhs . m_data . m_value . number_float ; \ 23673} \ 23674else if ( lhs_type == value_t:: number_float && rhs_type == value_t:: number_unsigned ) \ 23675{ \ 23676return lhs . m_data . m_value . number_float op static_cast < number_float_t >( rhs . m_data . m_value . number_unsigned ); \ 23677} \ 23678else if ( lhs_type == value_t:: number_unsigned && rhs_type == value_t:: number_integer ) \ 23679{ \ 23680return static_cast < number_integer_t >( lhs . m_data . m_value . number_unsigned ) op rhs . m_data . m_value . number_integer ; \ 23681} \ 23682else if ( lhs_type == value_t:: number_integer && rhs_type == value_t:: number_unsigned ) \ 23683{ \ 23684return lhs . m_data . m_value . number_integer op static_cast < number_integer_t >( rhs . m_data . m_value . number_unsigned ); \ 23685} \ 23686else if ( compares_unordered ( lhs , rhs ))\ 23687{\ 23688return ( unordered_result );\ 23689}\ 23690\ 23691return ( default_result ); 23692 23693JSON_PRIVATE_UNLESS_TESTED : 23694// returns true if: 23695// - any operand is NaN and the other operand is of number type 23696// - any operand is discarded 23697// in legacy mode, discarded values are considered ordered if 23698// an operation is computed as an odd number of inverses of others 23699static bool compares_unordered ( const_reference lhs , const_reference rhs , bool inverse = false) noexcept 23700{ 23701if (( lhs . is_number_float () && std:: isnan ( lhs . m_data . m_value . number_float ) && rhs . is_number ()) 23702|| ( rhs . is_number_float () && std:: isnan ( rhs . m_data . m_value . number_float ) && lhs . is_number ())) 23703{ 23704return true; 23705} 23706#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 23707return ( lhs . is_discarded () || rhs . is_discarded ()) && ! inverse ; 23708#else 23709static_cast < void >( inverse ); 23710return lhs . is_discarded () || rhs . is_discarded (); 23711#endif 23712} 23713 23714private : 23715bool compares_unordered ( const_reference rhs , bool inverse = false) const noexcept 23716{ 23717return compares_unordered (* this , rhs , inverse ); 23718} 23719 23720public : 23721#if JSON_HAS_THREE_WAY_COMPARISON 23722/// @brief comparison: equal 23723/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23724bool operator==( const_reference rhs ) const noexcept 23725{ 23726#ifdef __GNUC__ 23727#pragma GCC diagnostic push 23728#pragma GCC diagnostic ignored "-Wfloat-equal" 23729#endif 23730const_reference lhs = * this ; 23731JSON_IMPLEMENT_OPERATOR ( ==, true, false, false) 23732#ifdef __GNUC__ 23733#pragma GCC diagnostic pop 23734#endif 23735} 23736 23737/// @brief comparison: equal 23738/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23739template < typename ScalarType > 23740requires std:: is_scalar_v < ScalarType > 23741bool operator==( ScalarType rhs ) const noexcept 23742{ 23743return * this == basic_json ( rhs ); 23744} 23745 23746/// @brief comparison: not equal 23747/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23748bool operator!=( const_reference rhs ) const noexcept 23749{ 23750if ( compares_unordered ( rhs , true)) 23751{ 23752return false; 23753} 23754return ! operator ==( rhs ); 23755} 23756 23757/// @brief comparison: 3-way 23758/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 23759std:: partial_ordering operator<=>( const_reference rhs ) const noexcept // *NOPAD* 23760{ 23761const_reference lhs = * this ; 23762// default_result is used if we cannot compare values. In that case, 23763// we compare types. 23764JSON_IMPLEMENT_OPERATOR (<=>, // *NOPAD* 23765std::partial_ordering:: equivalent , 23766std::partial_ordering:: unordered , 23767lhs_type <=> rhs_type ) // *NOPAD* 23768} 23769 23770/// @brief comparison: 3-way 23771/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 23772template < typename ScalarType > 23773requires std:: is_scalar_v < ScalarType > 23774std:: partial_ordering operator<=>( ScalarType rhs ) const noexcept // *NOPAD* 23775{ 23776return * this <=> basic_json ( rhs ); // *NOPAD* 23777} 23778 23779#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 23780// all operators that are computed as an odd number of inverses of others 23781// need to be overloaded to emulate the legacy comparison behavior 23782 23783/// @brief comparison: less than or equal 23784/// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23785JSON_HEDLEY_DEPRECATED_FOR ( 3.11 . 0 , undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON ) 23786bool operator<=( const_reference rhs ) const noexcept 23787{ 23788if ( compares_unordered ( rhs , true)) 23789{ 23790return false; 23791} 23792return !( rhs < * this ); 23793} 23794 23795/// @brief comparison: less than or equal 23796/// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23797template < typename ScalarType > 23798requires std:: is_scalar_v < ScalarType > 23799bool operator<=( ScalarType rhs ) const noexcept 23800{ 23801return * this <= basic_json ( rhs ); 23802} 23803 23804/// @brief comparison: greater than or equal 23805/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23806JSON_HEDLEY_DEPRECATED_FOR ( 3.11 . 0 , undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON ) 23807bool operator>=( const_reference rhs ) const noexcept 23808{ 23809if ( compares_unordered ( rhs , true)) 23810{ 23811return false; 23812} 23813return !(* this < rhs ); 23814} 23815 23816/// @brief comparison: greater than or equal 23817/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23818template < typename ScalarType > 23819requires std:: is_scalar_v < ScalarType > 23820bool operator>=( ScalarType rhs ) const noexcept 23821{ 23822return * this >= basic_json ( rhs ); 23823} 23824#endif 23825#else 23826/// @brief comparison: equal 23827/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23828friend bool operator==( const_reference lhs , const_reference rhs ) noexcept 23829{ 23830#ifdef __GNUC__ 23831#pragma GCC diagnostic push 23832#pragma GCC diagnostic ignored "-Wfloat-equal" 23833#endif 23834JSON_IMPLEMENT_OPERATOR ( ==, true, false, false) 23835#ifdef __GNUC__ 23836#pragma GCC diagnostic pop 23837#endif 23838} 23839 23840/// @brief comparison: equal 23841/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23842template < typename ScalarType , typename std:: enable_if < 23843std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23844friend bool operator==( const_reference lhs , ScalarType rhs ) noexcept 23845{ 23846return lhs == basic_json ( rhs ); 23847} 23848 23849/// @brief comparison: equal 23850/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23851template < typename ScalarType , typename std:: enable_if < 23852std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23853friend bool operator==( ScalarType lhs , const_reference rhs ) noexcept 23854{ 23855return basic_json ( lhs ) == rhs ; 23856} 23857 23858/// @brief comparison: not equal 23859/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23860friend bool operator!=( const_reference lhs , const_reference rhs ) noexcept 23861{ 23862if ( compares_unordered ( lhs , rhs , true)) 23863{ 23864return false; 23865} 23866return !( lhs == rhs ); 23867} 23868 23869/// @brief comparison: not equal 23870/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23871template < typename ScalarType , typename std:: enable_if < 23872std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23873friend bool operator!=( const_reference lhs , ScalarType rhs ) noexcept 23874{ 23875return lhs != basic_json ( rhs ); 23876} 23877 23878/// @brief comparison: not equal 23879/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23880template < typename ScalarType , typename std:: enable_if < 23881std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23882friend bool operator!=( ScalarType lhs , const_reference rhs ) noexcept 23883{ 23884return basic_json ( lhs ) != rhs ; 23885} 23886 23887/// @brief comparison: less than 23888/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23889friend bool operator<( const_reference lhs , const_reference rhs ) noexcept 23890{ 23891// default_result is used if we cannot compare values. In that case, 23892// we compare types. Note we have to call the operator explicitly, 23893// because MSVC has problems otherwise. 23894JSON_IMPLEMENT_OPERATOR ( <, false, false, operator <( lhs_type , rhs_type )) 23895} 23896 23897/// @brief comparison: less than 23898/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23899template < typename ScalarType , typename std:: enable_if < 23900std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23901friend bool operator<( const_reference lhs , ScalarType rhs ) noexcept 23902{ 23903return lhs < basic_json ( rhs ); 23904} 23905 23906/// @brief comparison: less than 23907/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23908template < typename ScalarType , typename std:: enable_if < 23909std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23910friend bool operator<( ScalarType lhs , const_reference rhs ) noexcept 23911{ 23912return basic_json ( lhs ) < rhs ; 23913} 23914 23915/// @brief comparison: less than or equal 23916/// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23917friend bool operator<=( const_reference lhs , const_reference rhs ) noexcept 23918{ 23919if ( compares_unordered ( lhs , rhs , true)) 23920{ 23921return false; 23922} 23923return !( rhs < lhs ); 23924} 23925 23926/// @brief comparison: less than or equal 23927/// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23928template < typename ScalarType , typename std:: enable_if < 23929std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23930friend bool operator<=( const_reference lhs , ScalarType rhs ) noexcept 23931{ 23932return lhs <= basic_json ( rhs ); 23933} 23934 23935/// @brief comparison: less than or equal 23936/// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23937template < typename ScalarType , typename std:: enable_if < 23938std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23939friend bool operator<=( ScalarType lhs , const_reference rhs ) noexcept 23940{ 23941return basic_json ( lhs ) <= rhs ; 23942} 23943 23944/// @brief comparison: greater than 23945/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23946friend bool operator>( const_reference lhs , const_reference rhs ) noexcept 23947{ 23948// double inverse 23949if ( compares_unordered ( lhs , rhs )) 23950{ 23951return false; 23952} 23953return !( lhs <= rhs ); 23954} 23955 23956/// @brief comparison: greater than 23957/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23958template < typename ScalarType , typename std:: enable_if < 23959std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23960friend bool operator>( const_reference lhs , ScalarType rhs ) noexcept 23961{ 23962return lhs > basic_json ( rhs ); 23963} 23964 23965/// @brief comparison: greater than 23966/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23967template < typename ScalarType , typename std:: enable_if < 23968std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23969friend bool operator>( ScalarType lhs , const_reference rhs ) noexcept 23970{ 23971return basic_json ( lhs ) > rhs ; 23972} 23973 23974/// @brief comparison: greater than or equal 23975/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23976friend bool operator>=( const_reference lhs , const_reference rhs ) noexcept 23977{ 23978if ( compares_unordered ( lhs , rhs , true)) 23979{ 23980return false; 23981} 23982return !( lhs < rhs ); 23983} 23984 23985/// @brief comparison: greater than or equal 23986/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23987template < typename ScalarType , typename std:: enable_if < 23988std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23989friend bool operator>=( const_reference lhs , ScalarType rhs ) noexcept 23990{ 23991return lhs >= basic_json ( rhs ); 23992} 23993 23994/// @brief comparison: greater than or equal 23995/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23996template < typename ScalarType , typename std:: enable_if < 23997std:: is_scalar < ScalarType >:: value , int >:: type = 0 > 23998friend bool operator>=( ScalarType lhs , const_reference rhs ) noexcept 23999{ 24000return basic_json ( lhs ) >= rhs ; 24001} 24002#endif 24003 24004#undef JSON_IMPLEMENT_OPERATOR 24005 24006/// @} 24007 24008/////////////////// 24009// serialization // 24010/////////////////// 24011 24012/// @name serialization 24013/// @{ 24014#ifndef JSON_NO_IO 24015/// @brief serialize to stream 24016/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 24017friend std:: ostream & operator<<(std:: ostream & o , const basic_json & j ) 24018{ 24019// read width member and use it as indentation parameter if nonzero 24020const bool pretty_print = o . width () > 0 ; 24021const auto indentation = pretty_print ? o . width () : 0 ; 24022 24023// reset width to 0 for subsequent calls to this stream 24024o . width ( 0 ); 24025 24026// do the actual serialization 24027serializer s (detail:: output_adapter < char >( o ), o . fill ()); 24028s . dump ( j , pretty_print , false, static_cast < unsigned int >( indentation )); 24029return o ; 24030} 24031 24032/// @brief serialize to stream 24033/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 24034/// @deprecated This function is deprecated since 3.0.0 and will be removed in 24035/// version 4.0.0 of the library. Please use 24036/// operator<<(std::ostream&, const basic_json&) instead; that is, 24037/// replace calls like `j >> o;` with `o << j;`. 24038JSON_HEDLEY_DEPRECATED_FOR ( 3.0 . 0 , operator <<(std:: ostream &, const basic_json &)) 24039friend std :: ostream & operator >>( const basic_json & j , std:: ostream & o ) 24040{ 24041return o << j ; 24042} 24043#endif // JSON_NO_IO 24044/// @} 24045 24046///////////////////// 24047// deserialization // 24048///////////////////// 24049 24050/// @name deserialization 24051/// @{ 24052 24053/// @brief deserialize from a compatible input 24054/// @sa https://json.nlohmann.me/api/basic_json/parse/ 24055template < typename InputType > 24056JSON_HEDLEY_WARN_UNUSED_RESULT 24057static basic_json parse ( InputType && i , 24058parser_callback_t cb = nullptr , 24059const bool allow_exceptions = true, 24060const bool ignore_comments = false) 24061{ 24062basic_json result ; 24063parser (detail:: input_adapter (std:: forward < InputType >( i )), std:: move ( cb ), allow_exceptions , ignore_comments ). parse (true, result ); // cppcheck-suppress[accessMoved,accessForwarded] 24064return result ; 24065} 24066 24067/// @brief deserialize from a pair of character iterators 24068/// @sa https://json.nlohmann.me/api/basic_json/parse/ 24069template < typename IteratorType > 24070JSON_HEDLEY_WARN_UNUSED_RESULT 24071static basic_json parse ( IteratorType first , 24072IteratorType last , 24073parser_callback_t cb = nullptr , 24074const bool allow_exceptions = true, 24075const bool ignore_comments = false) 24076{ 24077basic_json result ; 24078parser (detail:: input_adapter (std:: move ( first ), std:: move ( last )), std:: move ( cb ), allow_exceptions , ignore_comments ). parse (true, result ); // cppcheck-suppress[accessMoved] 24079return result ; 24080} 24081 24082JSON_HEDLEY_WARN_UNUSED_RESULT 24083JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , parse ( ptr , ptr + len )) 24084static basic_json parse (detail:: span_input_adapter && i , 24085parser_callback_t cb = nullptr , 24086const bool allow_exceptions = true, 24087const bool ignore_comments = false) 24088{ 24089basic_json result ; 24090parser ( i . get (), std:: move ( cb ), allow_exceptions , ignore_comments ). parse (true, result ); // cppcheck-suppress[accessMoved] 24091return result ; 24092} 24093 24094/// @brief check if the input is valid JSON 24095/// @sa https://json.nlohmann.me/api/basic_json/accept/ 24096template < typename InputType > 24097static bool accept ( InputType && i , 24098const bool ignore_comments = false) 24099{ 24100return parser (detail:: input_adapter (std:: forward < InputType >( i )), nullptr , false, ignore_comments ). accept (true); 24101} 24102 24103/// @brief check if the input is valid JSON 24104/// @sa https://json.nlohmann.me/api/basic_json/accept/ 24105template < typename IteratorType > 24106static bool accept ( IteratorType first , IteratorType last , 24107const bool ignore_comments = false) 24108{ 24109return parser (detail:: input_adapter (std:: move ( first ), std:: move ( last )), nullptr , false, ignore_comments ). accept (true); 24110} 24111 24112JSON_HEDLEY_WARN_UNUSED_RESULT 24113JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , accept ( ptr , ptr + len )) 24114static bool accept (detail:: span_input_adapter && i , 24115const bool ignore_comments = false) 24116{ 24117return parser ( i . get (), nullptr , false, ignore_comments ). accept (true); 24118} 24119 24120/// @brief generate SAX events 24121/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 24122template < typename InputType , typename SAX > 24123JSON_HEDLEY_NON_NULL ( 2 ) 24124static bool sax_parse ( InputType && i , SAX * sax , 24125input_format_t format = input_format_t:: json , 24126const bool strict = true, 24127const bool ignore_comments = false) 24128{ 24129auto ia = detail:: input_adapter (std:: forward < InputType >( i )); 24130return format == input_format_t:: json 24131? parser (std:: move ( ia ), nullptr , true, ignore_comments ). sax_parse ( sax , strict ) 24132: detail:: binary_reader < basic_json , decltype( ia ), SAX >(std:: move ( ia ), format ). sax_parse ( format , sax , strict ); 24133} 24134 24135/// @brief generate SAX events 24136/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 24137template < class IteratorType , class SAX > 24138JSON_HEDLEY_NON_NULL ( 3 ) 24139static bool sax_parse ( IteratorType first , IteratorType last , SAX * sax , 24140input_format_t format = input_format_t:: json , 24141const bool strict = true, 24142const bool ignore_comments = false) 24143{ 24144auto ia = detail:: input_adapter (std:: move ( first ), std:: move ( last )); 24145return format == input_format_t:: json 24146? parser (std:: move ( ia ), nullptr , true, ignore_comments ). sax_parse ( sax , strict ) 24147: detail:: binary_reader < basic_json , decltype( ia ), SAX >(std:: move ( ia ), format ). sax_parse ( format , sax , strict ); 24148} 24149 24150/// @brief generate SAX events 24151/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 24152/// @deprecated This function is deprecated since 3.8.0 and will be removed in 24153/// version 4.0.0 of the library. Please use 24154/// sax_parse(ptr, ptr + len) instead. 24155template < typename SAX > 24156JSON_HEDLEY_DEPRECATED_FOR ( 3.8.0 , sax_parse ( ptr , ptr + len , ...)) 24157JSON_HEDLEY_NON_NULL ( 2 ) 24158static bool sax_parse (detail:: span_input_adapter && i , SAX * sax , 24159input_format_t format = input_format_t:: json , 24160const bool strict = true, 24161const bool ignore_comments = false) 24162{ 24163auto ia = i . get (); 24164return format == input_format_t:: json 24165// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24166? parser (std:: move ( ia ), nullptr , true, ignore_comments ). sax_parse ( sax , strict ) 24167// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24168: detail:: binary_reader < basic_json , decltype( ia ), SAX >(std:: move ( ia ), format ). sax_parse ( format , sax , strict ); 24169} 24170#ifndef JSON_NO_IO 24171/// @brief deserialize from stream 24172/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 24173/// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in 24174/// version 4.0.0 of the library. Please use 24175/// operator>>(std::istream&, basic_json&) instead; that is, 24176/// replace calls like `j << i;` with `i >> j;`. 24177JSON_HEDLEY_DEPRECATED_FOR ( 3.0 . 0 , operator >>(std:: istream &, basic_json &)) 24178friend std :: istream & operator <<( basic_json & j , std:: istream & i ) 24179{ 24180return operator >>( i , j ); 24181} 24182 24183/// @brief deserialize from stream 24184/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 24185friend std :: istream & operator >>(std:: istream & i , basic_json & j ) 24186{ 24187parser (detail:: input_adapter ( i )). parse (false, j ); 24188return i ; 24189} 24190#endif // JSON_NO_IO 24191/// @} 24192 24193/////////////////////////// 24194// convenience functions // 24195/////////////////////////// 24196 24197/// @brief return the type as string 24198/// @sa https://json.nlohmann.me/api/basic_json/type_name/ 24199JSON_HEDLEY_RETURNS_NON_NULL 24200const char * type_name () const noexcept 24201{ 24202switch ( m_data . m_type ) 24203{ 24204case value_t:: null : 24205return "null" ; 24206case value_t:: object : 24207return "object" ; 24208case value_t:: array : 24209return "array" ; 24210case value_t:: string : 24211return "string" ; 24212case value_t:: boolean : 24213return "boolean" ; 24214case value_t:: binary : 24215return "binary" ; 24216case value_t:: discarded : 24217return "discarded" ; 24218case value_t:: number_integer : 24219case value_t:: number_unsigned : 24220case value_t:: number_float : 24221default : 24222return "number" ; 24223} 24224} 24225 24226JSON_PRIVATE_UNLESS_TESTED : 24227////////////////////// 24228// member variables // 24229////////////////////// 24230 24231struct data 24232{ 24233/// the type of the current element 24234value_t m_type = value_t:: null ; 24235 24236/// the value of the current element 24237json_value m_value = {}; 24238 24239data ( const value_t v ) 24240: m_type ( v ), m_value ( v ) 24241{ 24242} 24243 24244data ( size_type cnt , const basic_json & val ) 24245: m_type (value_t:: array ) 24246{ 24247m_value . array = create < array_t >( cnt , val ); 24248} 24249 24250data () noexcept = default ; 24251data ( data &&) noexcept = default ; 24252data ( const data &) noexcept = delete ; 24253data & operator=( data &&) noexcept = delete ; 24254data & operator=( const data &) noexcept = delete ; 24255 24256~ data () noexcept 24257{ 24258m_value . destroy ( m_type ); 24259} 24260} ; 24261 24262data m_data = {}; 24263 24264#if JSON_DIAGNOSTICS 24265/// a pointer to a parent value (for debugging purposes) 24266basic_json * m_parent = nullptr ; 24267#endif 24268 24269#if JSON_DIAGNOSTIC_POSITIONS 24270/// the start position of the value 24271std:: size_t start_position = std::string::npos; 24272/// the end position of the value 24273std:: size_t end_position = std::string::npos; 24274public : 24275constexpr std:: size_t start_pos () const noexcept 24276{ 24277return start_position; 24278} 24279 24280constexpr std:: size_t end_pos () const noexcept 24281{ 24282return end_position; 24283} 24284#endif 24285 24286////////////////////////////////////////// 24287// binary serialization/deserialization // 24288////////////////////////////////////////// 24289 24290/// @name binary serialization/deserialization support 24291/// @{ 24292 24293public : 24294/// @brief create a CBOR serialization of a given JSON value 24295/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 24296static std:: vector < std:: uint8_t > to_cbor ( const basic_json & j) 24297{ 24298std::vector < std::uint8_t > result; 24299to_cbor (j, result); 24300return result; 24301} 24302 24303/// @brief create a CBOR serialization of a given JSON value 24304/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 24305static void to_cbor ( const basic_json & j, detail:: output_adapter < std:: uint8_t > o) 24306{ 24307binary_writer < std:: uint8_t > (o). write_cbor (j); 24308} 24309 24310/// @brief create a CBOR serialization of a given JSON value 24311/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 24312static void to_cbor ( const basic_json & j, detail:: output_adapter < char > o) 24313{ 24314binary_writer < char > (o). write_cbor (j); 24315} 24316 24317/// @brief create a MessagePack serialization of a given JSON value 24318/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 24319static std:: vector < std:: uint8_t > to_msgpack ( const basic_json & j) 24320{ 24321std:: vector < std:: uint8_t > result; 24322to_msgpack (j, result); 24323return result; 24324} 24325 24326/// @brief create a MessagePack serialization of a given JSON value 24327/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 24328static void to_msgpack ( const basic_json & j, detail:: output_adapter < std:: uint8_t > o) 24329{ 24330binary_writer < std:: uint8_t > (o). write_msgpack (j); 24331} 24332 24333/// @brief create a MessagePack serialization of a given JSON value 24334/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 24335static void to_msgpack ( const basic_json & j, detail:: output_adapter < char > o) 24336{ 24337binary_writer < char > (o). write_msgpack (j); 24338} 24339 24340/// @brief create a UBJSON serialization of a given JSON value 24341/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 24342static std:: vector < std:: uint8_t > to_ubjson ( const basic_json & j, 24343const bool use_size = false, 24344const bool use_type = false) 24345{ 24346std:: vector < std:: uint8_t > result; 24347to_ubjson (j, result, use_size, use_type); 24348return result; 24349} 24350 24351/// @brief create a UBJSON serialization of a given JSON value 24352/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 24353static void to_ubjson ( const basic_json & j, detail:: output_adapter < std:: uint8_t > o, 24354const bool use_size = false, const bool use_type = false) 24355{ 24356binary_writer < std:: uint8_t > (o). write_ubjson (j, use_size, use_type); 24357} 24358 24359/// @brief create a UBJSON serialization of a given JSON value 24360/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 24361static void to_ubjson ( const basic_json & j, detail:: output_adapter < char > o, 24362const bool use_size = false, const bool use_type = false) 24363{ 24364binary_writer < char > (o). write_ubjson (j, use_size, use_type); 24365} 24366 24367/// @brief create a BJData serialization of a given JSON value 24368/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 24369static std:: vector < std:: uint8_t > to_bjdata ( const basic_json & j, 24370const bool use_size = false, 24371const bool use_type = false, 24372const bjdata_version_t version = bjdata_version_t::draft2) 24373{ 24374std:: vector < std:: uint8_t > result; 24375to_bjdata (j, result, use_size, use_type, version); 24376return result; 24377} 24378 24379/// @brief create a BJData serialization of a given JSON value 24380/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 24381static void to_bjdata ( const basic_json & j, detail:: output_adapter < std:: uint8_t > o, 24382const bool use_size = false, const bool use_type = false, 24383const bjdata_version_t version = bjdata_version_t::draft2) 24384{ 24385binary_writer < std:: uint8_t > (o). write_ubjson (j, use_size, use_type, true, true, version); 24386} 24387 24388/// @brief create a BJData serialization of a given JSON value 24389/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 24390static void to_bjdata ( const basic_json & j, detail:: output_adapter < char > o, 24391const bool use_size = false, const bool use_type = false, 24392const bjdata_version_t version = bjdata_version_t::draft2) 24393{ 24394binary_writer < char > (o). write_ubjson (j, use_size, use_type, true, true, version); 24395} 24396 24397/// @brief create a BSON serialization of a given JSON value 24398/// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 24399static std:: vector < std:: uint8_t > to_bson ( const basic_json & j) 24400{ 24401std:: vector < std:: uint8_t > result; 24402to_bson (j, result); 24403return result; 24404} 24405 24406/// @brief create a BSON serialization of a given JSON value 24407/// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 24408static void to_bson ( const basic_json & j, detail:: output_adapter < std:: uint8_t > o) 24409{ 24410binary_writer < std:: uint8_t > (o). write_bson (j); 24411} 24412 24413/// @brief create a BSON serialization of a given JSON value 24414/// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 24415static void to_bson ( const basic_json & j, detail:: output_adapter < char > o) 24416{ 24417binary_writer < char > (o). write_bson (j); 24418} 24419 24420/// @brief create a JSON value from an input in CBOR format 24421/// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 24422template < typename InputType > 24423JSON_HEDLEY_WARN_UNUSED_RESULT 24424static basic_json from_cbor ( InputType && i, 24425const bool strict = true, 24426const bool allow_exceptions = true, 24427const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 24428{ 24429basic_json result; 24430auto ia = detail:: input_adapter (std:: forward < InputType > (i)); 24431detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24432const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::cbor). sax_parse (input_format_t::cbor, & sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] 24433return res ? result : basic_json (value_t::discarded); 24434} 24435 24436/// @brief create a JSON value from an input in CBOR format 24437/// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 24438template < typename IteratorType > 24439JSON_HEDLEY_WARN_UNUSED_RESULT 24440static basic_json from_cbor ( IteratorType first, IteratorType last, 24441const bool strict = true, 24442const bool allow_exceptions = true, 24443const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 24444{ 24445basic_json result; 24446auto ia = detail:: input_adapter (std:: move (first), std:: move (last)); 24447detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24448const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::cbor). sax_parse (input_format_t::cbor, & sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] 24449return res ? result : basic_json (value_t::discarded); 24450} 24451 24452template < typename T > 24453JSON_HEDLEY_WARN_UNUSED_RESULT 24454JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_cbor (ptr, ptr + len)) 24455static basic_json from_cbor ( const T * ptr, std:: size_t len, 24456const bool strict = true, 24457const bool allow_exceptions = true, 24458const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 24459{ 24460return from_cbor (ptr, ptr + len, strict, allow_exceptions, tag_handler); 24461} 24462 24463JSON_HEDLEY_WARN_UNUSED_RESULT 24464JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_cbor (ptr, ptr + len)) 24465static basic_json from_cbor (detail:: span_input_adapter && i, 24466const bool strict = true, 24467const bool allow_exceptions = true, 24468const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 24469{ 24470basic_json result; 24471auto ia = i. get (); 24472detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24473// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24474const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::cbor). sax_parse (input_format_t::cbor, & sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] 24475return res ? result : basic_json (value_t::discarded); 24476} 24477 24478/// @brief create a JSON value from an input in MessagePack format 24479/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 24480template < typename InputType > 24481JSON_HEDLEY_WARN_UNUSED_RESULT 24482static basic_json from_msgpack ( InputType && i, 24483const bool strict = true, 24484const bool allow_exceptions = true) 24485{ 24486basic_json result; 24487auto ia = detail:: input_adapter (std:: forward < InputType > (i)); 24488detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24489const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::msgpack). sax_parse (input_format_t::msgpack, & sdp, strict); // cppcheck-suppress[accessMoved] 24490return res ? result : basic_json (value_t::discarded); 24491} 24492 24493/// @brief create a JSON value from an input in MessagePack format 24494/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 24495template < typename IteratorType > 24496JSON_HEDLEY_WARN_UNUSED_RESULT 24497static basic_json from_msgpack ( IteratorType first, IteratorType last, 24498const bool strict = true, 24499const bool allow_exceptions = true) 24500{ 24501basic_json result; 24502auto ia = detail:: input_adapter (std:: move (first), std:: move (last)); 24503detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24504const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::msgpack). sax_parse (input_format_t::msgpack, & sdp, strict); // cppcheck-suppress[accessMoved] 24505return res ? result : basic_json (value_t::discarded); 24506} 24507 24508template < typename T > 24509JSON_HEDLEY_WARN_UNUSED_RESULT 24510JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_msgpack (ptr, ptr + len)) 24511static basic_json from_msgpack ( const T * ptr, std:: size_t len, 24512const bool strict = true, 24513const bool allow_exceptions = true) 24514{ 24515return from_msgpack (ptr, ptr + len, strict, allow_exceptions); 24516} 24517 24518JSON_HEDLEY_WARN_UNUSED_RESULT 24519JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_msgpack (ptr, ptr + len)) 24520static basic_json from_msgpack (detail:: span_input_adapter && i, 24521const bool strict = true, 24522const bool allow_exceptions = true) 24523{ 24524basic_json result; 24525auto ia = i. get (); 24526detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24527// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24528const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::msgpack). sax_parse (input_format_t::msgpack, & sdp, strict); // cppcheck-suppress[accessMoved] 24529return res ? result : basic_json (value_t::discarded); 24530} 24531 24532/// @brief create a JSON value from an input in UBJSON format 24533/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 24534template < typename InputType > 24535JSON_HEDLEY_WARN_UNUSED_RESULT 24536static basic_json from_ubjson ( InputType && i, 24537const bool strict = true, 24538const bool allow_exceptions = true) 24539{ 24540basic_json result; 24541auto ia = detail:: input_adapter (std:: forward < InputType > (i)); 24542detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24543const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::ubjson). sax_parse (input_format_t::ubjson, & sdp, strict); // cppcheck-suppress[accessMoved] 24544return res ? result : basic_json (value_t::discarded); 24545} 24546 24547/// @brief create a JSON value from an input in UBJSON format 24548/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 24549template < typename IteratorType > 24550JSON_HEDLEY_WARN_UNUSED_RESULT 24551static basic_json from_ubjson ( IteratorType first, IteratorType last, 24552const bool strict = true, 24553const bool allow_exceptions = true) 24554{ 24555basic_json result; 24556auto ia = detail:: input_adapter (std:: move (first), std:: move (last)); 24557detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24558const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::ubjson). sax_parse (input_format_t::ubjson, & sdp, strict); // cppcheck-suppress[accessMoved] 24559return res ? result : basic_json (value_t::discarded); 24560} 24561 24562template < typename T > 24563JSON_HEDLEY_WARN_UNUSED_RESULT 24564JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_ubjson (ptr, ptr + len)) 24565static basic_json from_ubjson ( const T * ptr, std:: size_t len, 24566const bool strict = true, 24567const bool allow_exceptions = true) 24568{ 24569return from_ubjson (ptr, ptr + len, strict, allow_exceptions); 24570} 24571 24572JSON_HEDLEY_WARN_UNUSED_RESULT 24573JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_ubjson (ptr, ptr + len)) 24574static basic_json from_ubjson (detail:: span_input_adapter && i, 24575const bool strict = true, 24576const bool allow_exceptions = true) 24577{ 24578basic_json result; 24579auto ia = i. get (); 24580detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24581// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24582const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::ubjson). sax_parse (input_format_t::ubjson, & sdp, strict); // cppcheck-suppress[accessMoved] 24583return res ? result : basic_json (value_t::discarded); 24584} 24585 24586/// @brief create a JSON value from an input in BJData format 24587/// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 24588template < typename InputType > 24589JSON_HEDLEY_WARN_UNUSED_RESULT 24590static basic_json from_bjdata ( InputType && i, 24591const bool strict = true, 24592const bool allow_exceptions = true) 24593{ 24594basic_json result; 24595auto ia = detail:: input_adapter (std:: forward < InputType > (i)); 24596detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24597const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::bjdata). sax_parse (input_format_t::bjdata, & sdp, strict); // cppcheck-suppress[accessMoved] 24598return res ? result : basic_json (value_t::discarded); 24599} 24600 24601/// @brief create a JSON value from an input in BJData format 24602/// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 24603template < typename IteratorType > 24604JSON_HEDLEY_WARN_UNUSED_RESULT 24605static basic_json from_bjdata ( IteratorType first, IteratorType last, 24606const bool strict = true, 24607const bool allow_exceptions = true) 24608{ 24609basic_json result; 24610auto ia = detail:: input_adapter (std:: move (first), std:: move (last)); 24611detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24612const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::bjdata). sax_parse (input_format_t::bjdata, & sdp, strict); // cppcheck-suppress[accessMoved] 24613return res ? result : basic_json (value_t::discarded); 24614} 24615 24616/// @brief create a JSON value from an input in BSON format 24617/// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 24618template < typename InputType > 24619JSON_HEDLEY_WARN_UNUSED_RESULT 24620static basic_json from_bson ( InputType && i, 24621const bool strict = true, 24622const bool allow_exceptions = true) 24623{ 24624basic_json result; 24625auto ia = detail:: input_adapter (std:: forward < InputType > (i)); 24626detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24627const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::bson). sax_parse (input_format_t::bson, & sdp, strict); // cppcheck-suppress[accessMoved] 24628return res ? result : basic_json (value_t::discarded); 24629} 24630 24631/// @brief create a JSON value from an input in BSON format 24632/// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 24633template < typename IteratorType > 24634JSON_HEDLEY_WARN_UNUSED_RESULT 24635static basic_json from_bson ( IteratorType first, IteratorType last, 24636const bool strict = true, 24637const bool allow_exceptions = true) 24638{ 24639basic_json result; 24640auto ia = detail:: input_adapter (std:: move (first), std:: move (last)); 24641detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24642const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::bson). sax_parse (input_format_t::bson, & sdp, strict); // cppcheck-suppress[accessMoved] 24643return res ? result : basic_json (value_t::discarded); 24644} 24645 24646template < typename T > 24647JSON_HEDLEY_WARN_UNUSED_RESULT 24648JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_bson (ptr, ptr + len)) 24649static basic_json from_bson ( const T * ptr, std:: size_t len, 24650const bool strict = true, 24651const bool allow_exceptions = true) 24652{ 24653return from_bson (ptr, ptr + len, strict, allow_exceptions); 24654} 24655 24656JSON_HEDLEY_WARN_UNUSED_RESULT 24657JSON_HEDLEY_DEPRECATED_FOR ( 3.8 . 0 , from_bson (ptr, ptr + len)) 24658static basic_json from_bson (detail:: span_input_adapter && i, 24659const bool strict = true, 24660const bool allow_exceptions = true) 24661{ 24662basic_json result; 24663auto ia = i. get (); 24664detail:: json_sax_dom_parser < basic_json , decltype(ia) > sdp ( result , allow_exceptions ); 24665// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24666const bool res = binary_reader < decltype(ia) > (std:: move (ia), input_format_t::bson). sax_parse (input_format_t::bson, & sdp, strict); // cppcheck-suppress[accessMoved] 24667return res ? result : basic_json (value_t::discarded); 24668} 24669/// @} 24670 24671////////////////////////// 24672// JSON Pointer support // 24673////////////////////////// 24674 24675/// @name JSON Pointer functions 24676/// @{ 24677 24678/// @brief access specified element via JSON Pointer 24679/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 24680reference operator[]( const json_pointer & ptr) 24681{ 24682return ptr. get_unchecked (this); 24683} 24684 24685template < typename BasicJsonType , detail:: enable_if_t < detail:: is_basic_json < BasicJsonType > :: value , int > = 0 > 24686JSON_HEDLEY_DEPRECATED_FOR ( 3.11.0 , basic_json::json_pointer or nlohmann:: json_pointer < basic_json:: string_t > ) // NOLINT(readability/alt_tokens) 24687reference operator[]( const ::nlohmann:: json_pointer < BasicJsonType >& ptr) 24688{ 24689return ptr. get_unchecked (this); 24690} 24691 24692/// @brief access specified element via JSON Pointer 24693/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 24694const_reference operator[]( const json_pointer & ptr) const 24695{ 24696return ptr. get_unchecked (this); 24697} 24698 24699template < typename BasicJsonType , detail:: enable_if_t < detail:: is_basic_json < BasicJsonType > :: value , int > = 0 > 24700JSON_HEDLEY_DEPRECATED_FOR ( 3.11.0 , basic_json::json_pointer or nlohmann:: json_pointer < basic_json:: string_t > ) // NOLINT(readability/alt_tokens) 24701const_reference operator[]( const ::nlohmann:: json_pointer < BasicJsonType >& ptr) const 24702{ 24703return ptr. get_unchecked (this); 24704} 24705 24706/// @brief access specified element via JSON Pointer 24707/// @sa https://json.nlohmann.me/api/basic_json/at/ 24708reference at ( const json_pointer & ptr) 24709{ 24710return ptr. get_checked (this); 24711} 24712 24713template < typename BasicJsonType , detail:: enable_if_t < detail:: is_basic_json < BasicJsonType > :: value , int > = 0 > 24714JSON_HEDLEY_DEPRECATED_FOR ( 3.11.0 , basic_json::json_pointer or nlohmann:: json_pointer < basic_json:: string_t > ) // NOLINT(readability/alt_tokens) 24715reference at ( const ::nlohmann:: json_pointer < BasicJsonType >& ptr) 24716{ 24717return ptr. get_checked (this); 24718} 24719 24720/// @brief access specified element via JSON Pointer 24721/// @sa https://json.nlohmann.me/api/basic_json/at/ 24722const_reference at ( const json_pointer & ptr) const 24723{ 24724return ptr. get_checked (this); 24725} 24726 24727template < typename BasicJsonType , detail:: enable_if_t < detail:: is_basic_json < BasicJsonType > :: value , int > = 0 > 24728JSON_HEDLEY_DEPRECATED_FOR ( 3.11.0 , basic_json::json_pointer or nlohmann:: json_pointer < basic_json:: string_t > ) // NOLINT(readability/alt_tokens) 24729const_reference at ( const ::nlohmann:: json_pointer < BasicJsonType >& ptr) const 24730{ 24731return ptr. get_checked (this); 24732} 24733 24734/// @brief return flattened JSON value 24735/// @sa https://json.nlohmann.me/api/basic_json/flatten/ 24736basic_json flatten () const 24737{ 24738basic_json result (value_t:: object ); 24739json_pointer:: flatten ( "" , * this, result); 24740return result; 24741} 24742 24743/// @brief unflatten a previously flattened JSON value 24744/// @sa https://json.nlohmann.me/api/basic_json/unflatten/ 24745basic_json unflatten () const 24746{ 24747return json_pointer:: unflatten ( * this); 24748} 24749 24750/// @} 24751 24752////////////////////////// 24753// JSON Patch functions // 24754////////////////////////// 24755 24756/// @name JSON Patch functions 24757/// @{ 24758 24759/// @brief applies a JSON patch in-place without copying the object 24760/// @sa https://json.nlohmann.me/api/basic_json/patch/ 24761void patch_inplace ( const basic_json & json_patch) 24762{ 24763basic_json & result = * this; 24764// the valid JSON Patch operations 24765enum class patch_operations {add, remove, replace, move, copy, test, invalid}; 24766 24767const auto get_op = []( const string_t & op) 24768{ 24769if (op == "add" ) 24770{ 24771return patch_operations::add; 24772} 24773if (op == "remove" ) 24774{ 24775return patch_operations::remove; 24776} 24777if (op == "replace" ) 24778{ 24779return patch_operations::replace; 24780} 24781if (op == "move" ) 24782{ 24783return patch_operations::move; 24784} 24785if (op == "copy" ) 24786{ 24787return patch_operations::copy; 24788} 24789if (op == "test" ) 24790{ 24791return patch_operations::test; 24792} 24793 24794return patch_operations::invalid; 24795}; 24796 24797// wrapper for "add" operation; add value at ptr 24798const auto operation_add = [ & result]( json_pointer & ptr, const basic_json & val) 24799{ 24800// adding to the root of the target document means replacing it 24801if (ptr. empty ()) 24802{ 24803result = val; 24804return ; 24805} 24806 24807// make sure the top element of the pointer exists 24808json_pointer const top_pointer = ptr. top (); 24809if (top_pointer != ptr) 24810{ 24811result. at (top_pointer); 24812} 24813 24814// get reference to parent of JSON pointer ptr 24815const auto last_path = ptr. back (); 24816ptr. pop_back (); 24817// parent must exist when performing patch add per RFC6902 specs 24818basic_json & parent = result. at (ptr); 24819 24820switch (parent. m_data . m_type ) 24821{ 24822case value_t::null: 24823case value_t::object: 24824{ 24825// use operator[] to add value 24826parent[last_path] = val; 24827break ; 24828} 24829 24830case value_t::array: 24831{ 24832if (last_path == "-" ) 24833{ 24834// special case: append to back 24835parent. push_back (val); 24836} 24837else 24838{ 24839const auto idx = json_pointer:: template array_index < basic_json_t > (last_path); 24840if ( JSON_HEDLEY_UNLIKELY (idx > parent. size ())) 24841{ 24842// avoid undefined behavior 24843JSON_THROW (out_of_range:: create ( 401 , detail:: concat ( "array index " , std:: to_string (idx), " is out of range" ), & parent)); 24844} 24845 24846// default case: insert add offset 24847parent. insert (parent. begin () + static_cast < difference_type > (idx), val); 24848} 24849break ; 24850} 24851 24852// if there exists a parent it cannot be primitive 24853case value_t::string: // LCOV_EXCL_LINE 24854case value_t::boolean: // LCOV_EXCL_LINE 24855case value_t::number_integer: // LCOV_EXCL_LINE 24856case value_t::number_unsigned: // LCOV_EXCL_LINE 24857case value_t::number_float: // LCOV_EXCL_LINE 24858case value_t::binary: // LCOV_EXCL_LINE 24859case value_t::discarded: // LCOV_EXCL_LINE 24860default : // LCOV_EXCL_LINE 24861JSON_ASSERT (false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 24862} 24863}; 24864 24865// wrapper for "remove" operation; remove value at ptr 24866const auto operation_remove = [this, & result]( json_pointer & ptr) 24867{ 24868// get reference to parent of JSON pointer ptr 24869const auto last_path = ptr. back (); 24870ptr. pop_back (); 24871basic_json & parent = result. at (ptr); 24872 24873// remove child 24874if (parent. is_object ()) 24875{ 24876// perform range check 24877auto it = parent. find (last_path); 24878if ( JSON_HEDLEY_LIKELY (it != parent. end ())) 24879{ 24880parent. erase (it); 24881} 24882else 24883{ 24884JSON_THROW (out_of_range:: create ( 403 , detail:: concat ( "key '" , last_path, "' not found" ), this)); 24885} 24886} 24887else if (parent. is_array ()) 24888{ 24889// note erase performs range check 24890parent. erase (json_pointer:: template array_index < basic_json_t > (last_path)); 24891} 24892}; 24893 24894// type check: top level value must be an array 24895if ( JSON_HEDLEY_UNLIKELY (!json_patch. is_array ())) 24896{ 24897JSON_THROW (parse_error:: create ( 104 , 0 , "JSON patch must be an array of objects" , & json_patch)); 24898} 24899 24900// iterate and apply the operations 24901for ( const auto & val : json_patch) 24902{ 24903// wrapper to get a value for an operation 24904const auto get_value = [ & val]( const string_t & op, 24905const string_t & member, 24906bool string_type) -> basic_json & 24907{ 24908// find value 24909auto it = val. m_data . m_value . object -> find (member); 24910 24911// context-sensitive error message 24912const auto error_msg = (op == "op" ) ? "operation" : detail:: concat ( "operation '" , op, '\'' ); // NOLINT(bugprone-unused-local-non-trivial-variable) 24913 24914// check if desired value is present 24915if ( JSON_HEDLEY_UNLIKELY (it == val. m_data . m_value . object -> end ())) 24916{ 24917// NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24918JSON_THROW (parse_error:: create ( 105 , 0 , detail:: concat (error_msg, " must have member '" , member, "'" ), & val)); 24919} 24920 24921// check if result is of type string 24922if ( JSON_HEDLEY_UNLIKELY (string_type && !it -> second . is_string ())) 24923{ 24924// NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24925JSON_THROW (parse_error:: create ( 105 , 0 , detail:: concat (error_msg, " must have string member '" , member, "'" ), & val)); 24926} 24927 24928// no error: return value 24929return it -> second ; 24930}; 24931 24932// type check: every element of the array must be an object 24933if ( JSON_HEDLEY_UNLIKELY (!val. is_object ())) 24934{ 24935JSON_THROW (parse_error:: create ( 104 , 0 , "JSON patch must be an array of objects" , & val)); 24936} 24937 24938// collect mandatory members 24939const auto op = get_value ( "op" , "op" , true). template get < string_t > (); 24940const auto path = get_value (op, "path" , true). template get < string_t > (); 24941json_pointer ptr ( path ); 24942 24943switch ( get_op (op)) 24944{ 24945case patch_operations::add: 24946{ 24947operation_add (ptr, get_value ( "add" , "value" , false)); 24948break ; 24949} 24950 24951case patch_operations::remove: 24952{ 24953operation_remove (ptr); 24954break ; 24955} 24956 24957case patch_operations::replace: 24958{ 24959// the "path" location must exist - use at() 24960result. at (ptr) = get_value ( "replace" , "value" , false); 24961break ; 24962} 24963 24964case patch_operations::move: 24965{ 24966const auto from_path = get_value ( "move" , "from" , true). template get < string_t > (); 24967json_pointer from_ptr ( from_path ); 24968 24969// the "from" location must exist - use at() 24970basic_json const v = result. at (from_ptr); 24971 24972// The move operation is functionally identical to a 24973// "remove" operation on the "from" location, followed 24974// immediately by an "add" operation at the target 24975// location with the value that was just removed. 24976operation_remove (from_ptr); 24977operation_add (ptr, v); 24978break ; 24979} 24980 24981case patch_operations::copy: 24982{ 24983const auto from_path = get_value ( "copy" , "from" , true). template get < string_t > (); 24984const json_pointer from_ptr ( from_path ); 24985 24986// the "from" location must exist - use at() 24987basic_json const v = result. at (from_ptr); 24988 24989// The copy is functionally identical to an "add" 24990// operation at the target location using the value 24991// specified in the "from" member. 24992operation_add (ptr, v); 24993break ; 24994} 24995 24996case patch_operations::test: 24997{ 24998bool success = false; 24999JSON_TRY 25000{ 25001// check if "value" matches the one at "path" 25002// the "path" location must exist - use at() 25003success = (result. at (ptr) == get_value ( "test" , "value" , false)); 25004} 25005JSON_INTERNAL_CATCH (out_of_range & ) 25006{ 25007// ignore out of range errors: success remains false 25008} 25009 25010// throw an exception if test fails 25011if ( JSON_HEDLEY_UNLIKELY (!success)) 25012{ 25013JSON_THROW (other_error:: create ( 501 , detail:: concat ( "unsuccessful: " , val. dump ()), & val)); 25014} 25015 25016break ; 25017} 25018 25019case patch_operations::invalid: 25020default : 25021{ 25022// op must be "add", "remove", "replace", "move", "copy", or 25023// "test" 25024JSON_THROW (parse_error:: create ( 105 , 0 , detail:: concat ( "operation value '" , op, "' is invalid" ), & val)); 25025} 25026} 25027} 25028} 25029 25030/// @brief applies a JSON patch to a copy of the current object 25031/// @sa https://json.nlohmann.me/api/basic_json/patch/ 25032basic_json patch ( const basic_json & json_patch) const 25033{ 25034basic_json result = * this; 25035result. patch_inplace (json_patch); 25036return result; 25037} 25038 25039/// @brief creates a diff as a JSON patch 25040/// @sa https://json.nlohmann.me/api/basic_json/diff/ 25041JSON_HEDLEY_WARN_UNUSED_RESULT 25042static basic_json diff ( const basic_json & source, const basic_json & target, 25043const string_t & path = "" ) 25044{ 25045// the patch 25046basic_json result (value_t:: array ); 25047 25048// if the values are the same, return empty patch 25049if (source == target) 25050{ 25051return result; 25052} 25053 25054if (source. type () != target. type ()) 25055{ 25056// different types: replace value 25057result. push_back ( 25058{ 25059{ "op" , "replace" }, { "path" , path}, { "value" , target} 25060}); 25061return result; 25062} 25063 25064switch (source. type ()) 25065{ 25066case value_t::array: 25067{ 25068// first pass: traverse common elements 25069std:: size_t i = 0 ; 25070while (i < source. size () && i < target. size ()) 25071{ 25072// recursive call to compare array values at index i 25073auto temp_diff = diff (source[i], target[i], detail:: concat < string_t > (path, '/' , detail:: to_string < string_t > (i))); 25074result. insert (result. end (), temp_diff. begin (), temp_diff. end ()); 25075++ i; 25076} 25077 25078// We now reached the end of at least one array 25079// in a second pass, traverse the remaining elements 25080 25081// remove my remaining elements 25082const auto end_index = static_cast < difference_type > (result. size ()); 25083while (i < source. size ()) 25084{ 25085// add operations in reverse order to avoid invalid 25086// indices 25087result. insert (result. begin () + end_index, object ( 25088{ 25089{ "op" , "remove" }, 25090{ "path" , detail:: concat < string_t > (path, '/' , detail:: to_string < string_t > (i))} 25091})); 25092++ i; 25093} 25094 25095// add other remaining elements 25096while (i < target. size ()) 25097{ 25098result. push_back ( 25099{ 25100{ "op" , "add" }, 25101{ "path" , detail:: concat < string_t > (path, "/-" )}, 25102{ "value" , target[i]} 25103}); 25104++ i; 25105} 25106 25107break ; 25108} 25109 25110case value_t::object: 25111{ 25112// first pass: traverse this object's elements 25113for ( auto it = source. cbegin (); it != source. cend (); ++ it) 25114{ 25115// escape the key name to be used in a JSON patch 25116const auto path_key = detail:: concat < string_t > (path, '/' , detail:: escape (it. key ())); 25117 25118if (target. find (it. key ()) != target. end ()) 25119{ 25120// recursive call to compare object values at key it 25121auto temp_diff = diff (it. value (), target[it. key ()], path_key); 25122result. insert (result. end (), temp_diff. begin (), temp_diff. end ()); 25123} 25124else 25125{ 25126// found a key that is not in o -> remove it 25127result. push_back ( object ( 25128{ 25129{ "op" , "remove" }, { "path" , path_key} 25130})); 25131} 25132} 25133 25134// second pass: traverse other object's elements 25135for ( auto it = target. cbegin (); it != target. cend (); ++ it) 25136{ 25137if (source. find (it. key ()) == source. end ()) 25138{ 25139// found a key that is not in this -> add it 25140const auto path_key = detail:: concat < string_t > (path, '/' , detail:: escape (it. key ())); 25141result. push_back ( 25142{ 25143{ "op" , "add" }, { "path" , path_key}, 25144{ "value" , it. value ()} 25145}); 25146} 25147} 25148 25149break ; 25150} 25151 25152case value_t::null: 25153case value_t::string: 25154case value_t::boolean: 25155case value_t::number_integer: 25156case value_t::number_unsigned: 25157case value_t::number_float: 25158case value_t::binary: 25159case value_t::discarded: 25160default : 25161{ 25162// both primitive type: replace value 25163result. push_back ( 25164{ 25165{ "op" , "replace" }, { "path" , path}, { "value" , target} 25166}); 25167break ; 25168} 25169} 25170 25171return result; 25172} 25173/// @} 25174 25175//////////////////////////////// 25176// JSON Merge Patch functions // 25177//////////////////////////////// 25178 25179/// @name JSON Merge Patch functions 25180/// @{ 25181 25182/// @brief applies a JSON Merge Patch 25183/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ 25184void merge_patch ( const basic_json & apply_patch) 25185{ 25186if (apply_patch. is_object ()) 25187{ 25188if (! is_object ()) 25189{ 25190* this = object (); 25191} 25192for ( auto it = apply_patch. begin (); it != apply_patch. end (); ++ it) 25193{ 25194if (it. value (). is_null ()) 25195{ 25196erase (it. key ()); 25197} 25198else 25199{ 25200operator[]( it . key ()). merge_patch (it. value ()); 25201} 25202} 25203} 25204else 25205{ 25206* this = apply_patch; 25207} 25208} 25209 25210/// @} 25211}; 25212 25213/// @brief user-defined to_string function for JSON values 25214/// @sa https://json.nlohmann.me/api/basic_json/to_string/ 25215NLOHMANN_BASIC_JSON_TPL_DECLARATION 25216std::string to_string( const NLOHMANN_BASIC_JSON_TPL & j) 25217{ 25218return j. dump (); 25219} 25220 25221inline namespace literals 25222{ 25223inline namespace json_literals 25224{ 25225 25226/// @brief user-defined string literal for JSON values 25227/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ 25228JSON_HEDLEY_NON_NULL ( 1 ) 25229#if !defined( JSON_HEDLEY_GCC_VERSION ) || JSON_HEDLEY_GCC_VERSION_CHECK ( 4 , 9 , 0 ) 25230inline nlohmann:: json operator ""_json( const char * s, std:: size_t n) 25231#else 25232inline nlohmann:: json operator "" _json( const char * s, std:: size_t n) 25233#endif 25234{ 25235return nlohmann::json::parse(s, s + n); 25236} 25237 25238/// @brief user-defined string literal for JSON pointer 25239/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ 25240JSON_HEDLEY_NON_NULL ( 1 ) 25241#if !defined( JSON_HEDLEY_GCC_VERSION ) || JSON_HEDLEY_GCC_VERSION_CHECK ( 4 , 9 , 0 ) 25242inline nlohmann::json:: json_pointer operator ""_json_pointer( const char * s, std:: size_t n) 25243#else 25244inline nlohmann::json:: json_pointer operator "" _json_pointer( const char * s, std:: size_t n) 25245#endif 25246{ 25247return nlohmann::json::json_pointer(std:: string (s, n)); 25248} 25249 25250} // namespace json_literals 25251} // namespace literals 25252NLOHMANN_JSON_NAMESPACE_END 25253 25254/////////////////////// 25255// nonmember support // 25256/////////////////////// 25257 25258namespace std // NOLINT(cert-dcl58-cpp) 25259{ 25260 25261/// @brief hash value for JSON objects 25262/// @sa https://json.nlohmann.me/api/basic_json/std_hash/ 25263NLOHMANN_BASIC_JSON_TPL_DECLARATION 25264struct hash < nlohmann:: NLOHMANN_BASIC_JSON_TPL > // NOLINT(cert-dcl58-cpp) 25265{ 25266std:: size_t operator()( const nlohmann:: NLOHMANN_BASIC_JSON_TPL & j) const 25267{ 25268return nlohmann::detail::hash(j); 25269} 25270}; 25271 25272// specialization for std::less<value_t> 25273template <> 25274struct less < ::nlohmann::detail:: value_t > // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 25275{ 25276/*! 25277@brief compare two value_t enum values 25278@since version 3.0.0 25279*/ 25280bool operator()(::nlohmann::detail:: value_t lhs, 25281::nlohmann::detail:: value_t rhs) const noexcept 25282{ 25283#if JSON_HAS_THREE_WAY_COMPARISON 25284return std:: is_lt (lhs <=> rhs); // *NOPAD* 25285#else 25286return ::nlohmann::detail::operator < (lhs, rhs); 25287#endif 25288} 25289}; 25290 25291// C++20 prohibit function specialization in the std namespace. 25292#ifndef JSON_HAS_CPP_20 25293 25294/// @brief exchanges the values of two JSON objects 25295/// @sa https://json.nlohmann.me/api/basic_json/std_swap/ 25296NLOHMANN_BASIC_JSON_TPL_DECLARATION 25297inline void swap (nlohmann:: NLOHMANN_BASIC_JSON_TPL & j1, nlohmann:: NLOHMANN_BASIC_JSON_TPL & j2) noexcept ( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) 25298is_nothrow_move_constructible < nlohmann:: NLOHMANN_BASIC_JSON_TPL > ::value && // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 25299is_nothrow_move_assignable < nlohmann:: NLOHMANN_BASIC_JSON_TPL > ::value) 25300{ 25301j1. swap (j2); 25302} 25303 25304#endif 25305 25306} // namespace std 25307 25308#if JSON_USE_GLOBAL_UDLS 25309#if !defined( JSON_HEDLEY_GCC_VERSION ) || JSON_HEDLEY_GCC_VERSION_CHECK ( 4 , 9 , 0 ) 25310using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 25311using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 25312#else 25313using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 25314using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 25315#endif 25316#endif 25317 25318// #include <nlohmann/detail/macro_unscope.hpp> 25319// __ _____ _____ _____ 25320// __| | __| | | | JSON for Modern C++ 25321// | | |__ | | | | | | version 3.12.0 25322// |_____|_____|_____|_|___| https://github.com/nlohmann/json 25323// 25324// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 25325// SPDX-License-Identifier: MIT 25326 25327 25328 25329// restore clang diagnostic settings 25330#if defined(__clang__) 25331#pragma clang diagnostic pop 25332#endif 25333 25334// clean up 25335#undef JSON_ASSERT 25336#undef JSON_INTERNAL_CATCH 25337#undef JSON_THROW 25338#undef JSON_PRIVATE_UNLESS_TESTED 25339#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION 25340#undef NLOHMANN_BASIC_JSON_TPL 25341#undef JSON_EXPLICIT 25342#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL 25343#undef JSON_INLINE_VARIABLE 25344#undef JSON_NO_UNIQUE_ADDRESS 25345#undef JSON_DISABLE_ENUM_SERIALIZATION 25346#undef JSON_USE_GLOBAL_UDLS 25347 25348#ifndef JSON_TEST_KEEP_MACROS 25349#undef JSON_CATCH 25350#undef JSON_TRY 25351#undef JSON_HAS_CPP_11 25352#undef JSON_HAS_CPP_14 25353#undef JSON_HAS_CPP_17 25354#undef JSON_HAS_CPP_20 25355#undef JSON_HAS_CPP_23 25356#undef JSON_HAS_FILESYSTEM 25357#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 25358#undef JSON_HAS_THREE_WAY_COMPARISON 25359#undef JSON_HAS_RANGES 25360#undef JSON_HAS_STATIC_RTTI 25361#undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 25362#endif 25363 25364// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> 25365// __ _____ _____ _____ 25366// __| | __| | | | JSON for Modern C++ 25367// | | |__ | | | | | | version 3.12.0 25368// |_____|_____|_____|_|___| https://github.com/nlohmann/json 25369// 25370// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me> 25371// SPDX-License-Identifier: MIT 25372 25373 25374 25375#undef JSON_HEDLEY_ALWAYS_INLINE 25376#undef JSON_HEDLEY_ARM_VERSION 25377#undef JSON_HEDLEY_ARM_VERSION_CHECK 25378#undef JSON_HEDLEY_ARRAY_PARAM 25379#undef JSON_HEDLEY_ASSUME 25380#undef JSON_HEDLEY_BEGIN_C_DECLS 25381#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 25382#undef JSON_HEDLEY_CLANG_HAS_BUILTIN 25383#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 25384#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 25385#undef JSON_HEDLEY_CLANG_HAS_EXTENSION 25386#undef JSON_HEDLEY_CLANG_HAS_FEATURE 25387#undef JSON_HEDLEY_CLANG_HAS_WARNING 25388#undef JSON_HEDLEY_COMPCERT_VERSION 25389#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 25390#undef JSON_HEDLEY_CONCAT 25391#undef JSON_HEDLEY_CONCAT3 25392#undef JSON_HEDLEY_CONCAT3_EX 25393#undef JSON_HEDLEY_CONCAT_EX 25394#undef JSON_HEDLEY_CONST 25395#undef JSON_HEDLEY_CONSTEXPR 25396#undef JSON_HEDLEY_CONST_CAST 25397#undef JSON_HEDLEY_CPP_CAST 25398#undef JSON_HEDLEY_CRAY_VERSION 25399#undef JSON_HEDLEY_CRAY_VERSION_CHECK 25400#undef JSON_HEDLEY_C_DECL 25401#undef JSON_HEDLEY_DEPRECATED 25402#undef JSON_HEDLEY_DEPRECATED_FOR 25403#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 25404#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 25405#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 25406#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 25407#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 25408#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 25409#undef JSON_HEDLEY_DIAGNOSTIC_POP 25410#undef JSON_HEDLEY_DIAGNOSTIC_PUSH 25411#undef JSON_HEDLEY_DMC_VERSION 25412#undef JSON_HEDLEY_DMC_VERSION_CHECK 25413#undef JSON_HEDLEY_EMPTY_BASES 25414#undef JSON_HEDLEY_EMSCRIPTEN_VERSION 25415#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 25416#undef JSON_HEDLEY_END_C_DECLS 25417#undef JSON_HEDLEY_FLAGS 25418#undef JSON_HEDLEY_FLAGS_CAST 25419#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 25420#undef JSON_HEDLEY_GCC_HAS_BUILTIN 25421#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 25422#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 25423#undef JSON_HEDLEY_GCC_HAS_EXTENSION 25424#undef JSON_HEDLEY_GCC_HAS_FEATURE 25425#undef JSON_HEDLEY_GCC_HAS_WARNING 25426#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 25427#undef JSON_HEDLEY_GCC_VERSION 25428#undef JSON_HEDLEY_GCC_VERSION_CHECK 25429#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 25430#undef JSON_HEDLEY_GNUC_HAS_BUILTIN 25431#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 25432#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 25433#undef JSON_HEDLEY_GNUC_HAS_EXTENSION 25434#undef JSON_HEDLEY_GNUC_HAS_FEATURE 25435#undef JSON_HEDLEY_GNUC_HAS_WARNING 25436#undef JSON_HEDLEY_GNUC_VERSION 25437#undef JSON_HEDLEY_GNUC_VERSION_CHECK 25438#undef JSON_HEDLEY_HAS_ATTRIBUTE 25439#undef JSON_HEDLEY_HAS_BUILTIN 25440#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 25441#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 25442#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 25443#undef JSON_HEDLEY_HAS_EXTENSION 25444#undef JSON_HEDLEY_HAS_FEATURE 25445#undef JSON_HEDLEY_HAS_WARNING 25446#undef JSON_HEDLEY_IAR_VERSION 25447#undef JSON_HEDLEY_IAR_VERSION_CHECK 25448#undef JSON_HEDLEY_IBM_VERSION 25449#undef JSON_HEDLEY_IBM_VERSION_CHECK 25450#undef JSON_HEDLEY_IMPORT 25451#undef JSON_HEDLEY_INLINE 25452#undef JSON_HEDLEY_INTEL_CL_VERSION 25453#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 25454#undef JSON_HEDLEY_INTEL_VERSION 25455#undef JSON_HEDLEY_INTEL_VERSION_CHECK 25456#undef JSON_HEDLEY_IS_CONSTANT 25457#undef JSON_HEDLEY_IS_CONSTEXPR_ 25458#undef JSON_HEDLEY_LIKELY 25459#undef JSON_HEDLEY_MALLOC 25460#undef JSON_HEDLEY_MCST_LCC_VERSION 25461#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 25462#undef JSON_HEDLEY_MESSAGE 25463#undef JSON_HEDLEY_MSVC_VERSION 25464#undef JSON_HEDLEY_MSVC_VERSION_CHECK 25465#undef JSON_HEDLEY_NEVER_INLINE 25466#undef JSON_HEDLEY_NON_NULL 25467#undef JSON_HEDLEY_NO_ESCAPE 25468#undef JSON_HEDLEY_NO_RETURN 25469#undef JSON_HEDLEY_NO_THROW 25470#undef JSON_HEDLEY_NULL 25471#undef JSON_HEDLEY_PELLES_VERSION 25472#undef JSON_HEDLEY_PELLES_VERSION_CHECK 25473#undef JSON_HEDLEY_PGI_VERSION 25474#undef JSON_HEDLEY_PGI_VERSION_CHECK 25475#undef JSON_HEDLEY_PREDICT 25476#undef JSON_HEDLEY_PRINTF_FORMAT 25477#undef JSON_HEDLEY_PRIVATE 25478#undef JSON_HEDLEY_PUBLIC 25479#undef JSON_HEDLEY_PURE 25480#undef JSON_HEDLEY_REINTERPRET_CAST 25481#undef JSON_HEDLEY_REQUIRE 25482#undef JSON_HEDLEY_REQUIRE_CONSTEXPR 25483#undef JSON_HEDLEY_REQUIRE_MSG 25484#undef JSON_HEDLEY_RESTRICT 25485#undef JSON_HEDLEY_RETURNS_NON_NULL 25486#undef JSON_HEDLEY_SENTINEL 25487#undef JSON_HEDLEY_STATIC_ASSERT 25488#undef JSON_HEDLEY_STATIC_CAST 25489#undef JSON_HEDLEY_STRINGIFY 25490#undef JSON_HEDLEY_STRINGIFY_EX 25491#undef JSON_HEDLEY_SUNPRO_VERSION 25492#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 25493#undef JSON_HEDLEY_TINYC_VERSION 25494#undef JSON_HEDLEY_TINYC_VERSION_CHECK 25495#undef JSON_HEDLEY_TI_ARMCL_VERSION 25496#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 25497#undef JSON_HEDLEY_TI_CL2000_VERSION 25498#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 25499#undef JSON_HEDLEY_TI_CL430_VERSION 25500#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 25501#undef JSON_HEDLEY_TI_CL6X_VERSION 25502#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 25503#undef JSON_HEDLEY_TI_CL7X_VERSION 25504#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 25505#undef JSON_HEDLEY_TI_CLPRU_VERSION 25506#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 25507#undef JSON_HEDLEY_TI_VERSION 25508#undef JSON_HEDLEY_TI_VERSION_CHECK 25509#undef JSON_HEDLEY_UNAVAILABLE 25510#undef JSON_HEDLEY_UNLIKELY 25511#undef JSON_HEDLEY_UNPREDICTABLE 25512#undef JSON_HEDLEY_UNREACHABLE 25513#undef JSON_HEDLEY_UNREACHABLE_RETURN 25514#undef JSON_HEDLEY_VERSION 25515#undef JSON_HEDLEY_VERSION_DECODE_MAJOR 25516#undef JSON_HEDLEY_VERSION_DECODE_MINOR 25517#undef JSON_HEDLEY_VERSION_DECODE_REVISION 25518#undef JSON_HEDLEY_VERSION_ENCODE 25519#undef JSON_HEDLEY_WARNING 25520#undef JSON_HEDLEY_WARN_UNUSED_RESULT 25521#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 25522#undef JSON_HEDLEY_FALL_THROUGH 25523 25524 25525 25526#endif // INCLUDE_NLOHMANN_JSON_HPP_