json.hpp (909622B)
1 // __ _____ _____ _____ 2 // __| | __| | | | JSON for Modern C++ 3 // | | |__ | | | | | | version 3.11.2 4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5 // 6 // SPDX-FileCopyrightText: 2013-2022 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.11.2 38 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 39 // 40 // SPDX-FileCopyrightText: 2013-2022 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.11.2 51 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 52 // 53 // SPDX-FileCopyrightText: 2013-2022 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 != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 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 11 // NOLINT(modernize-macro-to-enum) 70 #define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) 71 72 #ifndef JSON_DIAGNOSTICS 73 #define JSON_DIAGNOSTICS 0 74 #endif 75 76 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 77 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 78 #endif 79 80 #if JSON_DIAGNOSTICS 81 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag 82 #else 83 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS 84 #endif 85 86 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 87 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp 88 #else 89 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON 90 #endif 91 92 #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION 93 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 94 #endif 95 96 // Construct the namespace ABI tags component 97 #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b 98 #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ 99 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) 100 101 #define NLOHMANN_JSON_ABI_TAGS \ 102 NLOHMANN_JSON_ABI_TAGS_CONCAT( \ 103 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ 104 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) 105 106 // Construct the namespace version component 107 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ 108 _v ## major ## _ ## minor ## _ ## patch 109 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ 110 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) 111 112 #if NLOHMANN_JSON_NAMESPACE_NO_VERSION 113 #define NLOHMANN_JSON_NAMESPACE_VERSION 114 #else 115 #define NLOHMANN_JSON_NAMESPACE_VERSION \ 116 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ 117 NLOHMANN_JSON_VERSION_MINOR, \ 118 NLOHMANN_JSON_VERSION_PATCH) 119 #endif 120 121 // Combine namespace components 122 #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b 123 #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ 124 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) 125 126 #ifndef NLOHMANN_JSON_NAMESPACE 127 #define NLOHMANN_JSON_NAMESPACE \ 128 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ 129 NLOHMANN_JSON_ABI_TAGS, \ 130 NLOHMANN_JSON_NAMESPACE_VERSION) 131 #endif 132 133 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN 134 #define NLOHMANN_JSON_NAMESPACE_BEGIN \ 135 namespace nlohmann \ 136 { \ 137 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ 138 NLOHMANN_JSON_ABI_TAGS, \ 139 NLOHMANN_JSON_NAMESPACE_VERSION) \ 140 { 141 #endif 142 143 #ifndef NLOHMANN_JSON_NAMESPACE_END 144 #define NLOHMANN_JSON_NAMESPACE_END \ 145 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ 146 } // namespace nlohmann 147 #endif 148 149 // #include <nlohmann/detail/conversions/from_json.hpp> 150 // __ _____ _____ _____ 151 // __| | __| | | | JSON for Modern C++ 152 // | | |__ | | | | | | version 3.11.2 153 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 154 // 155 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 156 // SPDX-License-Identifier: MIT 157 158 159 160 #include <algorithm> // transform 161 #include <array> // array 162 #include <forward_list> // forward_list 163 #include <iterator> // inserter, front_inserter, end 164 #include <map> // map 165 #include <string> // string 166 #include <tuple> // tuple, make_tuple 167 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible 168 #include <unordered_map> // unordered_map 169 #include <utility> // pair, declval 170 #include <valarray> // valarray 171 172 // #include <nlohmann/detail/exceptions.hpp> 173 // __ _____ _____ _____ 174 // __| | __| | | | JSON for Modern C++ 175 // | | |__ | | | | | | version 3.11.2 176 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 177 // 178 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 179 // SPDX-License-Identifier: MIT 180 181 182 183 #include <cstddef> // nullptr_t 184 #include <exception> // exception 185 #if JSON_DIAGNOSTICS 186 #include <numeric> // accumulate 187 #endif 188 #include <stdexcept> // runtime_error 189 #include <string> // to_string 190 #include <vector> // vector 191 192 // #include <nlohmann/detail/value_t.hpp> 193 // __ _____ _____ _____ 194 // __| | __| | | | JSON for Modern C++ 195 // | | |__ | | | | | | version 3.11.2 196 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 197 // 198 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 199 // SPDX-License-Identifier: MIT 200 201 202 203 #include <array> // array 204 #include <cstddef> // size_t 205 #include <cstdint> // uint8_t 206 #include <string> // string 207 208 // #include <nlohmann/detail/macro_scope.hpp> 209 // __ _____ _____ _____ 210 // __| | __| | | | JSON for Modern C++ 211 // | | |__ | | | | | | version 3.11.2 212 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 213 // 214 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 215 // SPDX-License-Identifier: MIT 216 217 218 219 #include <utility> // declval, pair 220 // #include <nlohmann/detail/meta/detected.hpp> 221 // __ _____ _____ _____ 222 // __| | __| | | | JSON for Modern C++ 223 // | | |__ | | | | | | version 3.11.2 224 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 225 // 226 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 227 // SPDX-License-Identifier: MIT 228 229 230 231 #include <type_traits> 232 233 // #include <nlohmann/detail/meta/void_t.hpp> 234 // __ _____ _____ _____ 235 // __| | __| | | | JSON for Modern C++ 236 // | | |__ | | | | | | version 3.11.2 237 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 238 // 239 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 240 // SPDX-License-Identifier: MIT 241 242 243 244 // #include <nlohmann/detail/abi_macros.hpp> 245 246 247 NLOHMANN_JSON_NAMESPACE_BEGIN 248 namespace detail 249 { 250 251 template<typename ...Ts> struct make_void 252 { 253 using type = void; 254 }; 255 template<typename ...Ts> using void_t = typename make_void<Ts...>::type; 256 257 } // namespace detail 258 NLOHMANN_JSON_NAMESPACE_END 259 260 261 NLOHMANN_JSON_NAMESPACE_BEGIN 262 namespace detail 263 { 264 265 // https://en.cppreference.com/w/cpp/experimental/is_detected 266 struct nonesuch 267 { 268 nonesuch() = delete; 269 ~nonesuch() = delete; 270 nonesuch(nonesuch const&) = delete; 271 nonesuch(nonesuch const&&) = delete; 272 void operator=(nonesuch const&) = delete; 273 void operator=(nonesuch&&) = delete; 274 }; 275 276 template<class Default, 277 class AlwaysVoid, 278 template<class...> class Op, 279 class... Args> 280 struct detector 281 { 282 using value_t = std::false_type; 283 using type = Default; 284 }; 285 286 template<class Default, template<class...> class Op, class... Args> 287 struct detector<Default, void_t<Op<Args...>>, Op, Args...> 288 { 289 using value_t = std::true_type; 290 using type = Op<Args...>; 291 }; 292 293 template<template<class...> class Op, class... Args> 294 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; 295 296 template<template<class...> class Op, class... Args> 297 struct is_detected_lazy : is_detected<Op, Args...> { }; 298 299 template<template<class...> class Op, class... Args> 300 using detected_t = typename detector<nonesuch, void, Op, Args...>::type; 301 302 template<class Default, template<class...> class Op, class... Args> 303 using detected_or = detector<Default, void, Op, Args...>; 304 305 template<class Default, template<class...> class Op, class... Args> 306 using detected_or_t = typename detected_or<Default, Op, Args...>::type; 307 308 template<class Expected, template<class...> class Op, class... Args> 309 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; 310 311 template<class To, template<class...> class Op, class... Args> 312 using is_detected_convertible = 313 std::is_convertible<detected_t<Op, Args...>, To>; 314 315 } // namespace detail 316 NLOHMANN_JSON_NAMESPACE_END 317 318 // #include <nlohmann/thirdparty/hedley/hedley.hpp> 319 320 321 // __ _____ _____ _____ 322 // __| | __| | | | JSON for Modern C++ 323 // | | |__ | | | | | | version 3.11.2 324 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 325 // 326 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 327 // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com> 328 // SPDX-License-Identifier: MIT 329 330 /* Hedley - https://nemequ.github.io/hedley 331 * Created by Evan Nemerson <evan@nemerson.com> 332 */ 333 334 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) 335 #if defined(JSON_HEDLEY_VERSION) 336 #undef JSON_HEDLEY_VERSION 337 #endif 338 #define JSON_HEDLEY_VERSION 15 339 340 #if defined(JSON_HEDLEY_STRINGIFY_EX) 341 #undef JSON_HEDLEY_STRINGIFY_EX 342 #endif 343 #define JSON_HEDLEY_STRINGIFY_EX(x) #x 344 345 #if defined(JSON_HEDLEY_STRINGIFY) 346 #undef JSON_HEDLEY_STRINGIFY 347 #endif 348 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) 349 350 #if defined(JSON_HEDLEY_CONCAT_EX) 351 #undef JSON_HEDLEY_CONCAT_EX 352 #endif 353 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b 354 355 #if defined(JSON_HEDLEY_CONCAT) 356 #undef JSON_HEDLEY_CONCAT 357 #endif 358 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) 359 360 #if defined(JSON_HEDLEY_CONCAT3_EX) 361 #undef JSON_HEDLEY_CONCAT3_EX 362 #endif 363 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c 364 365 #if defined(JSON_HEDLEY_CONCAT3) 366 #undef JSON_HEDLEY_CONCAT3 367 #endif 368 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) 369 370 #if defined(JSON_HEDLEY_VERSION_ENCODE) 371 #undef JSON_HEDLEY_VERSION_ENCODE 372 #endif 373 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) 374 375 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) 376 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR 377 #endif 378 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) 379 380 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) 381 #undef JSON_HEDLEY_VERSION_DECODE_MINOR 382 #endif 383 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) 384 385 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) 386 #undef JSON_HEDLEY_VERSION_DECODE_REVISION 387 #endif 388 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) 389 390 #if defined(JSON_HEDLEY_GNUC_VERSION) 391 #undef JSON_HEDLEY_GNUC_VERSION 392 #endif 393 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) 394 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 395 #elif defined(__GNUC__) 396 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) 397 #endif 398 399 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) 400 #undef JSON_HEDLEY_GNUC_VERSION_CHECK 401 #endif 402 #if defined(JSON_HEDLEY_GNUC_VERSION) 403 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 404 #else 405 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) 406 #endif 407 408 #if defined(JSON_HEDLEY_MSVC_VERSION) 409 #undef JSON_HEDLEY_MSVC_VERSION 410 #endif 411 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) 412 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) 413 #elif defined(_MSC_FULL_VER) && !defined(__ICL) 414 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) 415 #elif defined(_MSC_VER) && !defined(__ICL) 416 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) 417 #endif 418 419 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) 420 #undef JSON_HEDLEY_MSVC_VERSION_CHECK 421 #endif 422 #if !defined(JSON_HEDLEY_MSVC_VERSION) 423 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) 424 #elif defined(_MSC_VER) && (_MSC_VER >= 1400) 425 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) 426 #elif defined(_MSC_VER) && (_MSC_VER >= 1200) 427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) 428 #else 429 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) 430 #endif 431 432 #if defined(JSON_HEDLEY_INTEL_VERSION) 433 #undef JSON_HEDLEY_INTEL_VERSION 434 #endif 435 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) 436 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) 437 #elif defined(__INTEL_COMPILER) && !defined(__ICL) 438 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) 439 #endif 440 441 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) 442 #undef JSON_HEDLEY_INTEL_VERSION_CHECK 443 #endif 444 #if defined(JSON_HEDLEY_INTEL_VERSION) 445 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 446 #else 447 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) 448 #endif 449 450 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) 451 #undef JSON_HEDLEY_INTEL_CL_VERSION 452 #endif 453 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) 454 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) 455 #endif 456 457 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) 458 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 459 #endif 460 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) 461 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 462 #else 463 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) 464 #endif 465 466 #if defined(JSON_HEDLEY_PGI_VERSION) 467 #undef JSON_HEDLEY_PGI_VERSION 468 #endif 469 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) 470 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) 471 #endif 472 473 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK) 474 #undef JSON_HEDLEY_PGI_VERSION_CHECK 475 #endif 476 #if defined(JSON_HEDLEY_PGI_VERSION) 477 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 478 #else 479 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) 480 #endif 481 482 #if defined(JSON_HEDLEY_SUNPRO_VERSION) 483 #undef JSON_HEDLEY_SUNPRO_VERSION 484 #endif 485 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) 486 #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) 487 #elif defined(__SUNPRO_C) 488 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) 489 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) 490 #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) 491 #elif defined(__SUNPRO_CC) 492 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) 493 #endif 494 495 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) 496 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 497 #endif 498 #if defined(JSON_HEDLEY_SUNPRO_VERSION) 499 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 500 #else 501 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) 502 #endif 503 504 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) 505 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION 506 #endif 507 #if defined(__EMSCRIPTEN__) 508 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) 509 #endif 510 511 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) 512 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 513 #endif 514 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) 515 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 516 #else 517 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) 518 #endif 519 520 #if defined(JSON_HEDLEY_ARM_VERSION) 521 #undef JSON_HEDLEY_ARM_VERSION 522 #endif 523 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) 524 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) 525 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) 526 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) 527 #endif 528 529 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK) 530 #undef JSON_HEDLEY_ARM_VERSION_CHECK 531 #endif 532 #if defined(JSON_HEDLEY_ARM_VERSION) 533 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 534 #else 535 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) 536 #endif 537 538 #if defined(JSON_HEDLEY_IBM_VERSION) 539 #undef JSON_HEDLEY_IBM_VERSION 540 #endif 541 #if defined(__ibmxl__) 542 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) 543 #elif defined(__xlC__) && defined(__xlC_ver__) 544 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) 545 #elif defined(__xlC__) 546 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) 547 #endif 548 549 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK) 550 #undef JSON_HEDLEY_IBM_VERSION_CHECK 551 #endif 552 #if defined(JSON_HEDLEY_IBM_VERSION) 553 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 554 #else 555 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) 556 #endif 557 558 #if defined(JSON_HEDLEY_TI_VERSION) 559 #undef JSON_HEDLEY_TI_VERSION 560 #endif 561 #if \ 562 defined(__TI_COMPILER_VERSION__) && \ 563 ( \ 564 defined(__TMS470__) || defined(__TI_ARM__) || \ 565 defined(__MSP430__) || \ 566 defined(__TMS320C2000__) \ 567 ) 568 #if (__TI_COMPILER_VERSION__ >= 16000000) 569 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 570 #endif 571 #endif 572 573 #if defined(JSON_HEDLEY_TI_VERSION_CHECK) 574 #undef JSON_HEDLEY_TI_VERSION_CHECK 575 #endif 576 #if defined(JSON_HEDLEY_TI_VERSION) 577 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 578 #else 579 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) 580 #endif 581 582 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) 583 #undef JSON_HEDLEY_TI_CL2000_VERSION 584 #endif 585 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) 586 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 587 #endif 588 589 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) 590 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 591 #endif 592 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) 593 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 594 #else 595 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) 596 #endif 597 598 #if defined(JSON_HEDLEY_TI_CL430_VERSION) 599 #undef JSON_HEDLEY_TI_CL430_VERSION 600 #endif 601 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) 602 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 603 #endif 604 605 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) 606 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 607 #endif 608 #if defined(JSON_HEDLEY_TI_CL430_VERSION) 609 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 610 #else 611 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) 612 #endif 613 614 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) 615 #undef JSON_HEDLEY_TI_ARMCL_VERSION 616 #endif 617 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) 618 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 619 #endif 620 621 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) 622 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 623 #endif 624 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) 625 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 626 #else 627 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) 628 #endif 629 630 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) 631 #undef JSON_HEDLEY_TI_CL6X_VERSION 632 #endif 633 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) 634 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 635 #endif 636 637 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) 638 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 639 #endif 640 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) 641 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 642 #else 643 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) 644 #endif 645 646 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) 647 #undef JSON_HEDLEY_TI_CL7X_VERSION 648 #endif 649 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) 650 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 651 #endif 652 653 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) 654 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 655 #endif 656 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) 657 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 658 #else 659 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) 660 #endif 661 662 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) 663 #undef JSON_HEDLEY_TI_CLPRU_VERSION 664 #endif 665 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) 666 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 667 #endif 668 669 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) 670 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 671 #endif 672 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) 673 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 674 #else 675 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) 676 #endif 677 678 #if defined(JSON_HEDLEY_CRAY_VERSION) 679 #undef JSON_HEDLEY_CRAY_VERSION 680 #endif 681 #if defined(_CRAYC) 682 #if defined(_RELEASE_PATCHLEVEL) 683 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) 684 #else 685 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) 686 #endif 687 #endif 688 689 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) 690 #undef JSON_HEDLEY_CRAY_VERSION_CHECK 691 #endif 692 #if defined(JSON_HEDLEY_CRAY_VERSION) 693 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 694 #else 695 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) 696 #endif 697 698 #if defined(JSON_HEDLEY_IAR_VERSION) 699 #undef JSON_HEDLEY_IAR_VERSION 700 #endif 701 #if defined(__IAR_SYSTEMS_ICC__) 702 #if __VER__ > 1000 703 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) 704 #else 705 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) 706 #endif 707 #endif 708 709 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK) 710 #undef JSON_HEDLEY_IAR_VERSION_CHECK 711 #endif 712 #if defined(JSON_HEDLEY_IAR_VERSION) 713 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 714 #else 715 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) 716 #endif 717 718 #if defined(JSON_HEDLEY_TINYC_VERSION) 719 #undef JSON_HEDLEY_TINYC_VERSION 720 #endif 721 #if defined(__TINYC__) 722 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) 723 #endif 724 725 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) 726 #undef JSON_HEDLEY_TINYC_VERSION_CHECK 727 #endif 728 #if defined(JSON_HEDLEY_TINYC_VERSION) 729 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 730 #else 731 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) 732 #endif 733 734 #if defined(JSON_HEDLEY_DMC_VERSION) 735 #undef JSON_HEDLEY_DMC_VERSION 736 #endif 737 #if defined(__DMC__) 738 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) 739 #endif 740 741 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK) 742 #undef JSON_HEDLEY_DMC_VERSION_CHECK 743 #endif 744 #if defined(JSON_HEDLEY_DMC_VERSION) 745 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 746 #else 747 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) 748 #endif 749 750 #if defined(JSON_HEDLEY_COMPCERT_VERSION) 751 #undef JSON_HEDLEY_COMPCERT_VERSION 752 #endif 753 #if defined(__COMPCERT_VERSION__) 754 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) 755 #endif 756 757 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) 758 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 759 #endif 760 #if defined(JSON_HEDLEY_COMPCERT_VERSION) 761 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 762 #else 763 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) 764 #endif 765 766 #if defined(JSON_HEDLEY_PELLES_VERSION) 767 #undef JSON_HEDLEY_PELLES_VERSION 768 #endif 769 #if defined(__POCC__) 770 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) 771 #endif 772 773 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) 774 #undef JSON_HEDLEY_PELLES_VERSION_CHECK 775 #endif 776 #if defined(JSON_HEDLEY_PELLES_VERSION) 777 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 778 #else 779 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) 780 #endif 781 782 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) 783 #undef JSON_HEDLEY_MCST_LCC_VERSION 784 #endif 785 #if defined(__LCC__) && defined(__LCC_MINOR__) 786 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) 787 #endif 788 789 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) 790 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 791 #endif 792 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) 793 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 794 #else 795 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) 796 #endif 797 798 #if defined(JSON_HEDLEY_GCC_VERSION) 799 #undef JSON_HEDLEY_GCC_VERSION 800 #endif 801 #if \ 802 defined(JSON_HEDLEY_GNUC_VERSION) && \ 803 !defined(__clang__) && \ 804 !defined(JSON_HEDLEY_INTEL_VERSION) && \ 805 !defined(JSON_HEDLEY_PGI_VERSION) && \ 806 !defined(JSON_HEDLEY_ARM_VERSION) && \ 807 !defined(JSON_HEDLEY_CRAY_VERSION) && \ 808 !defined(JSON_HEDLEY_TI_VERSION) && \ 809 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ 810 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ 811 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ 812 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ 813 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ 814 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ 815 !defined(__COMPCERT__) && \ 816 !defined(JSON_HEDLEY_MCST_LCC_VERSION) 817 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION 818 #endif 819 820 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK) 821 #undef JSON_HEDLEY_GCC_VERSION_CHECK 822 #endif 823 #if defined(JSON_HEDLEY_GCC_VERSION) 824 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 825 #else 826 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) 827 #endif 828 829 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE) 830 #undef JSON_HEDLEY_HAS_ATTRIBUTE 831 #endif 832 #if \ 833 defined(__has_attribute) && \ 834 ( \ 835 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ 836 ) 837 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) 838 #else 839 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) 840 #endif 841 842 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) 843 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 844 #endif 845 #if defined(__has_attribute) 846 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 847 #else 848 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 849 #endif 850 851 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) 852 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 853 #endif 854 #if defined(__has_attribute) 855 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 856 #else 857 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 858 #endif 859 860 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) 861 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 862 #endif 863 #if \ 864 defined(__has_cpp_attribute) && \ 865 defined(__cplusplus) && \ 866 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) 867 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) 868 #else 869 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) 870 #endif 871 872 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) 873 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 874 #endif 875 #if !defined(__cplusplus) || !defined(__has_cpp_attribute) 876 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) 877 #elif \ 878 !defined(JSON_HEDLEY_PGI_VERSION) && \ 879 !defined(JSON_HEDLEY_IAR_VERSION) && \ 880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ 881 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) 882 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) 883 #else 884 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) 885 #endif 886 887 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) 888 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 889 #endif 890 #if defined(__has_cpp_attribute) && defined(__cplusplus) 891 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) 892 #else 893 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 894 #endif 895 896 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) 897 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 898 #endif 899 #if defined(__has_cpp_attribute) && defined(__cplusplus) 900 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) 901 #else 902 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 903 #endif 904 905 #if defined(JSON_HEDLEY_HAS_BUILTIN) 906 #undef JSON_HEDLEY_HAS_BUILTIN 907 #endif 908 #if defined(__has_builtin) 909 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) 910 #else 911 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) 912 #endif 913 914 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) 915 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN 916 #endif 917 #if defined(__has_builtin) 918 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) 919 #else 920 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 921 #endif 922 923 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) 924 #undef JSON_HEDLEY_GCC_HAS_BUILTIN 925 #endif 926 #if defined(__has_builtin) 927 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) 928 #else 929 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 930 #endif 931 932 #if defined(JSON_HEDLEY_HAS_FEATURE) 933 #undef JSON_HEDLEY_HAS_FEATURE 934 #endif 935 #if defined(__has_feature) 936 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) 937 #else 938 #define JSON_HEDLEY_HAS_FEATURE(feature) (0) 939 #endif 940 941 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) 942 #undef JSON_HEDLEY_GNUC_HAS_FEATURE 943 #endif 944 #if defined(__has_feature) 945 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) 946 #else 947 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 948 #endif 949 950 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE) 951 #undef JSON_HEDLEY_GCC_HAS_FEATURE 952 #endif 953 #if defined(__has_feature) 954 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) 955 #else 956 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 957 #endif 958 959 #if defined(JSON_HEDLEY_HAS_EXTENSION) 960 #undef JSON_HEDLEY_HAS_EXTENSION 961 #endif 962 #if defined(__has_extension) 963 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) 964 #else 965 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) 966 #endif 967 968 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) 969 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION 970 #endif 971 #if defined(__has_extension) 972 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) 973 #else 974 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 975 #endif 976 977 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) 978 #undef JSON_HEDLEY_GCC_HAS_EXTENSION 979 #endif 980 #if defined(__has_extension) 981 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) 982 #else 983 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 984 #endif 985 986 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) 987 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 988 #endif 989 #if defined(__has_declspec_attribute) 990 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) 991 #else 992 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) 993 #endif 994 995 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) 996 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 997 #endif 998 #if defined(__has_declspec_attribute) 999 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) 1000 #else 1001 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1002 #endif 1003 1004 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) 1005 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 1006 #endif 1007 #if defined(__has_declspec_attribute) 1008 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) 1009 #else 1010 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1011 #endif 1012 1013 #if defined(JSON_HEDLEY_HAS_WARNING) 1014 #undef JSON_HEDLEY_HAS_WARNING 1015 #endif 1016 #if defined(__has_warning) 1017 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) 1018 #else 1019 #define JSON_HEDLEY_HAS_WARNING(warning) (0) 1020 #endif 1021 1022 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING) 1023 #undef JSON_HEDLEY_GNUC_HAS_WARNING 1024 #endif 1025 #if defined(__has_warning) 1026 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) 1027 #else 1028 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1029 #endif 1030 1031 #if defined(JSON_HEDLEY_GCC_HAS_WARNING) 1032 #undef JSON_HEDLEY_GCC_HAS_WARNING 1033 #endif 1034 #if defined(__has_warning) 1035 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) 1036 #else 1037 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1038 #endif 1039 1040 #if \ 1041 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 1042 defined(__clang__) || \ 1043 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 1044 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1045 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 1046 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 1047 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1048 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1049 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 1050 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 1051 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 1052 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ 1053 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1054 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1055 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ 1056 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ 1057 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ 1058 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) 1059 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) 1060 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1061 #define JSON_HEDLEY_PRAGMA(value) __pragma(value) 1062 #else 1063 #define JSON_HEDLEY_PRAGMA(value) 1064 #endif 1065 1066 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) 1067 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH 1068 #endif 1069 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP) 1070 #undef JSON_HEDLEY_DIAGNOSTIC_POP 1071 #endif 1072 #if defined(__clang__) 1073 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") 1074 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") 1075 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1076 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1077 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1078 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) 1079 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") 1080 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") 1081 #elif \ 1082 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 1083 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1084 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) 1085 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) 1086 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) 1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") 1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") 1089 #elif \ 1090 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1091 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1092 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ 1093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 1094 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1095 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) 1096 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") 1097 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") 1098 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) 1099 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1100 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1101 #else 1102 #define JSON_HEDLEY_DIAGNOSTIC_PUSH 1103 #define JSON_HEDLEY_DIAGNOSTIC_POP 1104 #endif 1105 1106 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for 1107 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 1108 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) 1109 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 1110 #endif 1111 #if defined(__cplusplus) 1112 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") 1113 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") 1114 # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") 1115 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1116 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1117 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1118 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1119 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ 1120 xpr \ 1121 JSON_HEDLEY_DIAGNOSTIC_POP 1122 # else 1123 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1124 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1125 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1126 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1127 xpr \ 1128 JSON_HEDLEY_DIAGNOSTIC_POP 1129 # endif 1130 # else 1131 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1132 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1133 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1134 xpr \ 1135 JSON_HEDLEY_DIAGNOSTIC_POP 1136 # endif 1137 # endif 1138 #endif 1139 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) 1140 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x 1141 #endif 1142 1143 #if defined(JSON_HEDLEY_CONST_CAST) 1144 #undef JSON_HEDLEY_CONST_CAST 1145 #endif 1146 #if defined(__cplusplus) 1147 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr)) 1148 #elif \ 1149 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ 1150 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ 1151 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1152 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ 1153 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1154 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ 1155 ((T) (expr)); \ 1156 JSON_HEDLEY_DIAGNOSTIC_POP \ 1157 })) 1158 #else 1159 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) 1160 #endif 1161 1162 #if defined(JSON_HEDLEY_REINTERPRET_CAST) 1163 #undef JSON_HEDLEY_REINTERPRET_CAST 1164 #endif 1165 #if defined(__cplusplus) 1166 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr)) 1167 #else 1168 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) 1169 #endif 1170 1171 #if defined(JSON_HEDLEY_STATIC_CAST) 1172 #undef JSON_HEDLEY_STATIC_CAST 1173 #endif 1174 #if defined(__cplusplus) 1175 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr)) 1176 #else 1177 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) 1178 #endif 1179 1180 #if defined(JSON_HEDLEY_CPP_CAST) 1181 #undef JSON_HEDLEY_CPP_CAST 1182 #endif 1183 #if defined(__cplusplus) 1184 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") 1185 # define JSON_HEDLEY_CPP_CAST(T, expr) \ 1186 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1187 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ 1188 ((T) (expr)) \ 1189 JSON_HEDLEY_DIAGNOSTIC_POP 1190 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) 1191 # define JSON_HEDLEY_CPP_CAST(T, expr) \ 1192 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1193 _Pragma("diag_suppress=Pe137") \ 1194 JSON_HEDLEY_DIAGNOSTIC_POP 1195 # else 1196 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) 1197 # endif 1198 #else 1199 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr) 1200 #endif 1201 1202 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) 1203 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1204 #endif 1205 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") 1206 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") 1207 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1208 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") 1209 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) 1211 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) 1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") 1213 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1215 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) 1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1217 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) 1219 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1221 #elif \ 1222 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1223 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1224 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1225 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1226 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1227 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1228 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1229 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1230 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1231 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1232 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) 1233 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") 1234 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) 1235 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") 1236 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) 1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") 1238 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") 1240 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) 1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") 1242 #else 1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1244 #endif 1245 1246 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) 1247 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1248 #endif 1249 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") 1251 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") 1253 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) 1255 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") 1257 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) 1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") 1259 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) 1261 #elif \ 1262 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ 1263 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 1264 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1265 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) 1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1267 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) 1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1269 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") 1271 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") 1273 #else 1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1275 #endif 1276 1277 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) 1278 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1279 #endif 1280 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") 1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") 1282 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) 1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1284 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) 1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") 1286 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) 1288 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) 1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) 1290 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) 1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") 1292 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1294 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) 1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") 1296 #elif \ 1297 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 1298 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 1299 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) 1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") 1301 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") 1303 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1305 #else 1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1307 #endif 1308 1309 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) 1310 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1311 #endif 1312 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") 1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") 1314 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") 1316 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) 1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") 1318 #else 1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1320 #endif 1321 1322 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) 1323 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1324 #endif 1325 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function") 1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") 1327 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) 1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") 1329 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) 1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) 1331 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") 1333 #else 1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1335 #endif 1336 1337 #if defined(JSON_HEDLEY_DEPRECATED) 1338 #undef JSON_HEDLEY_DEPRECATED 1339 #endif 1340 #if defined(JSON_HEDLEY_DEPRECATED_FOR) 1341 #undef JSON_HEDLEY_DEPRECATED_FOR 1342 #endif 1343 #if \ 1344 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1345 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1346 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) 1347 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) 1348 #elif \ 1349 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 1350 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 1351 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1352 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 1353 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ 1354 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1355 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 1356 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ 1357 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 1358 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1359 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ 1360 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1361 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) 1362 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) 1363 #elif defined(__cplusplus) && (__cplusplus >= 201402L) 1364 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) 1365 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) 1366 #elif \ 1367 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ 1368 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1369 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1370 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1371 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1372 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1373 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1374 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1375 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1376 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1377 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1378 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1379 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1380 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1381 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1382 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1383 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) 1384 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) 1385 #elif \ 1386 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1387 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ 1388 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1389 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) 1390 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) 1391 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1392 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") 1393 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") 1394 #else 1395 #define JSON_HEDLEY_DEPRECATED(since) 1396 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) 1397 #endif 1398 1399 #if defined(JSON_HEDLEY_UNAVAILABLE) 1400 #undef JSON_HEDLEY_UNAVAILABLE 1401 #endif 1402 #if \ 1403 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ 1404 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ 1405 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1406 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1407 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) 1408 #else 1409 #define JSON_HEDLEY_UNAVAILABLE(available_since) 1410 #endif 1411 1412 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) 1413 #undef JSON_HEDLEY_WARN_UNUSED_RESULT 1414 #endif 1415 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) 1416 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 1417 #endif 1418 #if \ 1419 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ 1420 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 1421 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1422 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1423 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1424 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1425 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1426 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1427 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1428 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1429 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1430 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1431 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1432 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1433 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 1434 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1435 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1436 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) 1437 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) 1438 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) 1439 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) 1441 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) 1442 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1444 #elif defined(_Check_return_) /* SAL */ 1445 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ 1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ 1447 #else 1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT 1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) 1450 #endif 1451 1452 #if defined(JSON_HEDLEY_SENTINEL) 1453 #undef JSON_HEDLEY_SENTINEL 1454 #endif 1455 #if \ 1456 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ 1457 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1458 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1459 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 1460 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1461 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) 1462 #else 1463 #define JSON_HEDLEY_SENTINEL(position) 1464 #endif 1465 1466 #if defined(JSON_HEDLEY_NO_RETURN) 1467 #undef JSON_HEDLEY_NO_RETURN 1468 #endif 1469 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1470 #define JSON_HEDLEY_NO_RETURN __noreturn 1471 #elif \ 1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1473 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1474 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1475 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L 1476 #define JSON_HEDLEY_NO_RETURN _Noreturn 1477 #elif defined(__cplusplus) && (__cplusplus >= 201103L) 1478 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) 1479 #elif \ 1480 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ 1481 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ 1482 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1483 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1484 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1485 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1486 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1487 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1488 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1489 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1490 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1491 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1492 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1493 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1494 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1495 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1496 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1497 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1498 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1499 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") 1500 #elif \ 1501 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1502 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1503 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1504 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) 1505 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") 1506 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) 1507 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) 1508 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) 1509 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1510 #else 1511 #define JSON_HEDLEY_NO_RETURN 1512 #endif 1513 1514 #if defined(JSON_HEDLEY_NO_ESCAPE) 1515 #undef JSON_HEDLEY_NO_ESCAPE 1516 #endif 1517 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) 1518 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) 1519 #else 1520 #define JSON_HEDLEY_NO_ESCAPE 1521 #endif 1522 1523 #if defined(JSON_HEDLEY_UNREACHABLE) 1524 #undef JSON_HEDLEY_UNREACHABLE 1525 #endif 1526 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN) 1527 #undef JSON_HEDLEY_UNREACHABLE_RETURN 1528 #endif 1529 #if defined(JSON_HEDLEY_ASSUME) 1530 #undef JSON_HEDLEY_ASSUME 1531 #endif 1532 #if \ 1533 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1534 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1535 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1536 #define JSON_HEDLEY_ASSUME(expr) __assume(expr) 1537 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) 1538 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) 1539 #elif \ 1540 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1541 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) 1542 #if defined(__cplusplus) 1543 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) 1544 #else 1545 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) 1546 #endif 1547 #endif 1548 #if \ 1549 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ 1550 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 1551 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ 1552 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1553 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ 1554 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ 1555 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1556 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() 1557 #elif defined(JSON_HEDLEY_ASSUME) 1558 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) 1559 #endif 1560 #if !defined(JSON_HEDLEY_ASSUME) 1561 #if defined(JSON_HEDLEY_UNREACHABLE) 1562 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) 1563 #else 1564 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) 1565 #endif 1566 #endif 1567 #if defined(JSON_HEDLEY_UNREACHABLE) 1568 #if \ 1569 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1570 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) 1571 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) 1572 #else 1573 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() 1574 #endif 1575 #else 1576 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) 1577 #endif 1578 #if !defined(JSON_HEDLEY_UNREACHABLE) 1579 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) 1580 #endif 1581 1582 JSON_HEDLEY_DIAGNOSTIC_PUSH 1583 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic") 1584 #pragma clang diagnostic ignored "-Wpedantic" 1585 #endif 1586 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) 1587 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 1588 #endif 1589 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) 1590 #if defined(__clang__) 1591 #pragma clang diagnostic ignored "-Wvariadic-macros" 1592 #elif defined(JSON_HEDLEY_GCC_VERSION) 1593 #pragma GCC diagnostic ignored "-Wvariadic-macros" 1594 #endif 1595 #endif 1596 #if defined(JSON_HEDLEY_NON_NULL) 1597 #undef JSON_HEDLEY_NON_NULL 1598 #endif 1599 #if \ 1600 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ 1601 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 1602 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1603 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) 1604 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) 1605 #else 1606 #define JSON_HEDLEY_NON_NULL(...) 1607 #endif 1608 JSON_HEDLEY_DIAGNOSTIC_POP 1609 1610 #if defined(JSON_HEDLEY_PRINTF_FORMAT) 1611 #undef JSON_HEDLEY_PRINTF_FORMAT 1612 #endif 1613 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) 1614 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) 1615 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) 1616 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) 1617 #elif \ 1618 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ 1619 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1621 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 1622 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1623 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1624 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1625 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1626 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1627 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1628 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1629 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1630 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1631 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1632 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1633 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1634 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1635 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) 1636 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) 1637 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) 1638 #else 1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) 1640 #endif 1641 1642 #if defined(JSON_HEDLEY_CONSTEXPR) 1643 #undef JSON_HEDLEY_CONSTEXPR 1644 #endif 1645 #if defined(__cplusplus) 1646 #if __cplusplus >= 201103L 1647 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) 1648 #endif 1649 #endif 1650 #if !defined(JSON_HEDLEY_CONSTEXPR) 1651 #define JSON_HEDLEY_CONSTEXPR 1652 #endif 1653 1654 #if defined(JSON_HEDLEY_PREDICT) 1655 #undef JSON_HEDLEY_PREDICT 1656 #endif 1657 #if defined(JSON_HEDLEY_LIKELY) 1658 #undef JSON_HEDLEY_LIKELY 1659 #endif 1660 #if defined(JSON_HEDLEY_UNLIKELY) 1661 #undef JSON_HEDLEY_UNLIKELY 1662 #endif 1663 #if defined(JSON_HEDLEY_UNPREDICTABLE) 1664 #undef JSON_HEDLEY_UNPREDICTABLE 1665 #endif 1666 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) 1667 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) 1668 #endif 1669 #if \ 1670 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ 1671 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ 1672 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1673 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) 1674 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) 1675 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) 1676 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) 1677 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) 1678 #elif \ 1679 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 1680 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 1681 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1682 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 1683 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1684 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1685 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1686 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 1687 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 1688 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 1689 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 1690 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1691 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1692 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ 1693 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 1694 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1695 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \ 1696 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) 1697 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ 1698 (__extension__ ({ \ 1699 double hedley_probability_ = (probability); \ 1700 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ 1701 })) 1702 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ 1703 (__extension__ ({ \ 1704 double hedley_probability_ = (probability); \ 1705 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ 1706 })) 1707 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) 1708 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) 1709 #else 1710 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) 1711 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) 1712 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) 1713 # define JSON_HEDLEY_LIKELY(expr) (!!(expr)) 1714 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) 1715 #endif 1716 #if !defined(JSON_HEDLEY_UNPREDICTABLE) 1717 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) 1718 #endif 1719 1720 #if defined(JSON_HEDLEY_MALLOC) 1721 #undef JSON_HEDLEY_MALLOC 1722 #endif 1723 #if \ 1724 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ 1725 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1726 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1727 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1728 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1729 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 1730 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1731 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1732 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1733 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1734 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1735 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1736 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1737 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1738 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1739 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1740 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1741 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1742 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) 1743 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1744 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") 1745 #elif \ 1746 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1747 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1748 #define JSON_HEDLEY_MALLOC __declspec(restrict) 1749 #else 1750 #define JSON_HEDLEY_MALLOC 1751 #endif 1752 1753 #if defined(JSON_HEDLEY_PURE) 1754 #undef JSON_HEDLEY_PURE 1755 #endif 1756 #if \ 1757 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ 1758 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ 1759 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1760 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1761 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1762 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1763 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1764 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1765 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1766 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1767 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1768 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1769 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1770 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1771 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1772 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1773 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1774 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1775 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1776 # define JSON_HEDLEY_PURE __attribute__((__pure__)) 1777 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1778 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") 1779 #elif defined(__cplusplus) && \ 1780 ( \ 1781 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ 1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ 1784 ) 1785 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") 1786 #else 1787 # define JSON_HEDLEY_PURE 1788 #endif 1789 1790 #if defined(JSON_HEDLEY_CONST) 1791 #undef JSON_HEDLEY_CONST 1792 #endif 1793 #if \ 1794 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ 1795 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ 1796 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1797 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1798 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1799 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1800 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1801 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1802 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1803 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1804 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1805 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1806 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1807 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1808 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1809 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1810 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1811 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1812 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1813 #define JSON_HEDLEY_CONST __attribute__((__const__)) 1814 #elif \ 1815 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1816 #define JSON_HEDLEY_CONST _Pragma("no_side_effect") 1817 #else 1818 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE 1819 #endif 1820 1821 #if defined(JSON_HEDLEY_RESTRICT) 1822 #undef JSON_HEDLEY_RESTRICT 1823 #endif 1824 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) 1825 #define JSON_HEDLEY_RESTRICT restrict 1826 #elif \ 1827 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1828 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1829 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1830 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 1831 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1832 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1833 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1834 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1835 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ 1836 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 1837 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1838 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ 1839 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 1840 defined(__clang__) || \ 1841 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1842 #define JSON_HEDLEY_RESTRICT __restrict 1843 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) 1844 #define JSON_HEDLEY_RESTRICT _Restrict 1845 #else 1846 #define JSON_HEDLEY_RESTRICT 1847 #endif 1848 1849 #if defined(JSON_HEDLEY_INLINE) 1850 #undef JSON_HEDLEY_INLINE 1851 #endif 1852 #if \ 1853 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 1854 (defined(__cplusplus) && (__cplusplus >= 199711L)) 1855 #define JSON_HEDLEY_INLINE inline 1856 #elif \ 1857 defined(JSON_HEDLEY_GCC_VERSION) || \ 1858 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) 1859 #define JSON_HEDLEY_INLINE __inline__ 1860 #elif \ 1861 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 1862 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 1863 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1864 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ 1865 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 1866 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1867 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 1868 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1869 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1870 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1871 #define JSON_HEDLEY_INLINE __inline 1872 #else 1873 #define JSON_HEDLEY_INLINE 1874 #endif 1875 1876 #if defined(JSON_HEDLEY_ALWAYS_INLINE) 1877 #undef JSON_HEDLEY_ALWAYS_INLINE 1878 #endif 1879 #if \ 1880 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ 1881 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1882 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1883 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1884 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1885 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1886 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1887 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1888 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1889 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1890 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1891 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1892 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1893 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1894 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1895 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1896 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1897 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1898 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1899 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE 1900 #elif \ 1901 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 1902 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1903 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline 1904 #elif defined(__cplusplus) && \ 1905 ( \ 1906 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1907 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1908 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1909 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 1910 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1911 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ 1912 ) 1913 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") 1914 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1915 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") 1916 #else 1917 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE 1918 #endif 1919 1920 #if defined(JSON_HEDLEY_NEVER_INLINE) 1921 #undef JSON_HEDLEY_NEVER_INLINE 1922 #endif 1923 #if \ 1924 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ 1925 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1926 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1927 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1928 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1929 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1930 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1931 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1932 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1933 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1934 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1935 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1936 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1937 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1938 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1939 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1940 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1941 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1942 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1943 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) 1944 #elif \ 1945 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1946 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1947 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1948 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) 1949 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") 1950 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) 1951 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") 1952 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1953 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") 1954 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) 1955 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) 1956 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) 1957 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1958 #else 1959 #define JSON_HEDLEY_NEVER_INLINE 1960 #endif 1961 1962 #if defined(JSON_HEDLEY_PRIVATE) 1963 #undef JSON_HEDLEY_PRIVATE 1964 #endif 1965 #if defined(JSON_HEDLEY_PUBLIC) 1966 #undef JSON_HEDLEY_PUBLIC 1967 #endif 1968 #if defined(JSON_HEDLEY_IMPORT) 1969 #undef JSON_HEDLEY_IMPORT 1970 #endif 1971 #if defined(_WIN32) || defined(__CYGWIN__) 1972 # define JSON_HEDLEY_PRIVATE 1973 # define JSON_HEDLEY_PUBLIC __declspec(dllexport) 1974 # define JSON_HEDLEY_IMPORT __declspec(dllimport) 1975 #else 1976 # if \ 1977 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ 1978 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 1979 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1980 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1981 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1982 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 1983 ( \ 1984 defined(__TI_EABI__) && \ 1985 ( \ 1986 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1987 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ 1988 ) \ 1989 ) || \ 1990 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1991 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) 1992 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) 1993 # else 1994 # define JSON_HEDLEY_PRIVATE 1995 # define JSON_HEDLEY_PUBLIC 1996 # endif 1997 # define JSON_HEDLEY_IMPORT extern 1998 #endif 1999 2000 #if defined(JSON_HEDLEY_NO_THROW) 2001 #undef JSON_HEDLEY_NO_THROW 2002 #endif 2003 #if \ 2004 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ 2005 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 2006 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2007 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2008 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) 2009 #elif \ 2010 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ 2011 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 2012 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) 2013 #define JSON_HEDLEY_NO_THROW __declspec(nothrow) 2014 #else 2015 #define JSON_HEDLEY_NO_THROW 2016 #endif 2017 2018 #if defined(JSON_HEDLEY_FALL_THROUGH) 2019 #undef JSON_HEDLEY_FALL_THROUGH 2020 #endif 2021 #if \ 2022 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ 2023 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ 2024 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2025 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) 2026 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) 2027 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) 2028 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) 2029 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) 2030 #elif defined(__fallthrough) /* SAL */ 2031 #define JSON_HEDLEY_FALL_THROUGH __fallthrough 2032 #else 2033 #define JSON_HEDLEY_FALL_THROUGH 2034 #endif 2035 2036 #if defined(JSON_HEDLEY_RETURNS_NON_NULL) 2037 #undef JSON_HEDLEY_RETURNS_NON_NULL 2038 #endif 2039 #if \ 2040 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ 2041 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 2042 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2043 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) 2044 #elif defined(_Ret_notnull_) /* SAL */ 2045 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ 2046 #else 2047 #define JSON_HEDLEY_RETURNS_NON_NULL 2048 #endif 2049 2050 #if defined(JSON_HEDLEY_ARRAY_PARAM) 2051 #undef JSON_HEDLEY_ARRAY_PARAM 2052 #endif 2053 #if \ 2054 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ 2055 !defined(__STDC_NO_VLA__) && \ 2056 !defined(__cplusplus) && \ 2057 !defined(JSON_HEDLEY_PGI_VERSION) && \ 2058 !defined(JSON_HEDLEY_TINYC_VERSION) 2059 #define JSON_HEDLEY_ARRAY_PARAM(name) (name) 2060 #else 2061 #define JSON_HEDLEY_ARRAY_PARAM(name) 2062 #endif 2063 2064 #if defined(JSON_HEDLEY_IS_CONSTANT) 2065 #undef JSON_HEDLEY_IS_CONSTANT 2066 #endif 2067 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) 2068 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR 2069 #endif 2070 /* JSON_HEDLEY_IS_CONSTEXPR_ is for 2071 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 2072 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) 2073 #undef JSON_HEDLEY_IS_CONSTEXPR_ 2074 #endif 2075 #if \ 2076 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ 2077 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 2078 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2079 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ 2080 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 2081 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 2082 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 2083 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ 2084 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 2085 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2086 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) 2087 #endif 2088 #if !defined(__cplusplus) 2089 # if \ 2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ 2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2093 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 2094 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 2095 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 2096 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) 2097 #if defined(__INTPTR_TYPE__) 2098 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) 2099 #else 2100 #include <stdint.h> 2101 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) 2102 #endif 2103 # elif \ 2104 ( \ 2105 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ 2106 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ 2107 !defined(JSON_HEDLEY_PGI_VERSION) && \ 2108 !defined(JSON_HEDLEY_IAR_VERSION)) || \ 2109 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 2110 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 2111 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ 2112 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 2113 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) 2114 #if defined(__INTPTR_TYPE__) 2115 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) 2116 #else 2117 #include <stdint.h> 2118 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) 2119 #endif 2120 # elif \ 2121 defined(JSON_HEDLEY_GCC_VERSION) || \ 2122 defined(JSON_HEDLEY_INTEL_VERSION) || \ 2123 defined(JSON_HEDLEY_TINYC_VERSION) || \ 2124 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ 2125 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ 2126 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ 2127 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ 2128 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ 2129 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ 2130 defined(__clang__) 2131 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ 2132 sizeof(void) != \ 2133 sizeof(*( \ 2134 1 ? \ 2135 ((void*) ((expr) * 0L) ) : \ 2136 ((struct { char v[sizeof(void) * 2]; } *) 1) \ 2137 ) \ 2138 ) \ 2139 ) 2140 # endif 2141 #endif 2142 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) 2143 #if !defined(JSON_HEDLEY_IS_CONSTANT) 2144 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) 2145 #endif 2146 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) 2147 #else 2148 #if !defined(JSON_HEDLEY_IS_CONSTANT) 2149 #define JSON_HEDLEY_IS_CONSTANT(expr) (0) 2150 #endif 2151 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) 2152 #endif 2153 2154 #if defined(JSON_HEDLEY_BEGIN_C_DECLS) 2155 #undef JSON_HEDLEY_BEGIN_C_DECLS 2156 #endif 2157 #if defined(JSON_HEDLEY_END_C_DECLS) 2158 #undef JSON_HEDLEY_END_C_DECLS 2159 #endif 2160 #if defined(JSON_HEDLEY_C_DECL) 2161 #undef JSON_HEDLEY_C_DECL 2162 #endif 2163 #if defined(__cplusplus) 2164 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { 2165 #define JSON_HEDLEY_END_C_DECLS } 2166 #define JSON_HEDLEY_C_DECL extern "C" 2167 #else 2168 #define JSON_HEDLEY_BEGIN_C_DECLS 2169 #define JSON_HEDLEY_END_C_DECLS 2170 #define JSON_HEDLEY_C_DECL 2171 #endif 2172 2173 #if defined(JSON_HEDLEY_STATIC_ASSERT) 2174 #undef JSON_HEDLEY_STATIC_ASSERT 2175 #endif 2176 #if \ 2177 !defined(__cplusplus) && ( \ 2178 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ 2179 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 2180 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ 2181 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2182 defined(_Static_assert) \ 2183 ) 2184 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) 2185 #elif \ 2186 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 2187 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ 2188 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2189 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) 2190 #else 2191 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) 2192 #endif 2193 2194 #if defined(JSON_HEDLEY_NULL) 2195 #undef JSON_HEDLEY_NULL 2196 #endif 2197 #if defined(__cplusplus) 2198 #if __cplusplus >= 201103L 2199 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) 2200 #elif defined(NULL) 2201 #define JSON_HEDLEY_NULL NULL 2202 #else 2203 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) 2204 #endif 2205 #elif defined(NULL) 2206 #define JSON_HEDLEY_NULL NULL 2207 #else 2208 #define JSON_HEDLEY_NULL ((void*) 0) 2209 #endif 2210 2211 #if defined(JSON_HEDLEY_MESSAGE) 2212 #undef JSON_HEDLEY_MESSAGE 2213 #endif 2214 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 2215 # define JSON_HEDLEY_MESSAGE(msg) \ 2216 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2217 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2218 JSON_HEDLEY_PRAGMA(message msg) \ 2219 JSON_HEDLEY_DIAGNOSTIC_POP 2220 #elif \ 2221 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ 2222 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 2223 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) 2224 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) 2225 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) 2226 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 2227 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2228 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) 2229 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2230 #else 2231 # define JSON_HEDLEY_MESSAGE(msg) 2232 #endif 2233 2234 #if defined(JSON_HEDLEY_WARNING) 2235 #undef JSON_HEDLEY_WARNING 2236 #endif 2237 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 2238 # define JSON_HEDLEY_WARNING(msg) \ 2239 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2240 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2241 JSON_HEDLEY_PRAGMA(clang warning msg) \ 2242 JSON_HEDLEY_DIAGNOSTIC_POP 2243 #elif \ 2244 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ 2245 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 2246 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 2247 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) 2248 #elif \ 2249 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 2250 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2251 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2252 #else 2253 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) 2254 #endif 2255 2256 #if defined(JSON_HEDLEY_REQUIRE) 2257 #undef JSON_HEDLEY_REQUIRE 2258 #endif 2259 #if defined(JSON_HEDLEY_REQUIRE_MSG) 2260 #undef JSON_HEDLEY_REQUIRE_MSG 2261 #endif 2262 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) 2263 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") 2264 # define JSON_HEDLEY_REQUIRE(expr) \ 2265 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2266 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2267 __attribute__((diagnose_if(!(expr), #expr, "error"))) \ 2268 JSON_HEDLEY_DIAGNOSTIC_POP 2269 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ 2270 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2271 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2272 __attribute__((diagnose_if(!(expr), msg, "error"))) \ 2273 JSON_HEDLEY_DIAGNOSTIC_POP 2274 # else 2275 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) 2276 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) 2277 # endif 2278 #else 2279 # define JSON_HEDLEY_REQUIRE(expr) 2280 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) 2281 #endif 2282 2283 #if defined(JSON_HEDLEY_FLAGS) 2284 #undef JSON_HEDLEY_FLAGS 2285 #endif 2286 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) 2287 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) 2288 #else 2289 #define JSON_HEDLEY_FLAGS 2290 #endif 2291 2292 #if defined(JSON_HEDLEY_FLAGS_CAST) 2293 #undef JSON_HEDLEY_FLAGS_CAST 2294 #endif 2295 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) 2296 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ 2297 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2298 _Pragma("warning(disable:188)") \ 2299 ((T) (expr)); \ 2300 JSON_HEDLEY_DIAGNOSTIC_POP \ 2301 })) 2302 #else 2303 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) 2304 #endif 2305 2306 #if defined(JSON_HEDLEY_EMPTY_BASES) 2307 #undef JSON_HEDLEY_EMPTY_BASES 2308 #endif 2309 #if \ 2310 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ 2311 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2312 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) 2313 #else 2314 #define JSON_HEDLEY_EMPTY_BASES 2315 #endif 2316 2317 /* Remaining macros are deprecated. */ 2318 2319 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) 2320 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 2321 #endif 2322 #if defined(__clang__) 2323 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) 2324 #else 2325 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 2326 #endif 2327 2328 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) 2329 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 2330 #endif 2331 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 2332 2333 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) 2334 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 2335 #endif 2336 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) 2337 2338 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) 2339 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN 2340 #endif 2341 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) 2342 2343 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) 2344 #undef JSON_HEDLEY_CLANG_HAS_FEATURE 2345 #endif 2346 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) 2347 2348 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) 2349 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION 2350 #endif 2351 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) 2352 2353 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) 2354 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 2355 #endif 2356 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) 2357 2358 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING) 2359 #undef JSON_HEDLEY_CLANG_HAS_WARNING 2360 #endif 2361 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) 2362 2363 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ 2364 2365 2366 // This file contains all internal macro definitions (except those affecting ABI) 2367 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them 2368 2369 // #include <nlohmann/detail/abi_macros.hpp> 2370 2371 2372 // exclude unsupported compilers 2373 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) 2374 #if defined(__clang__) 2375 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 2376 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 2377 #endif 2378 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) 2379 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 2380 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 2381 #endif 2382 #endif 2383 #endif 2384 2385 // C++ language standard detection 2386 // if the user manually specified the used c++ version this is skipped 2387 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) 2388 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) 2389 #define JSON_HAS_CPP_20 2390 #define JSON_HAS_CPP_17 2391 #define JSON_HAS_CPP_14 2392 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 2393 #define JSON_HAS_CPP_17 2394 #define JSON_HAS_CPP_14 2395 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) 2396 #define JSON_HAS_CPP_14 2397 #endif 2398 // the cpp 11 flag is always specified because it is the minimal required version 2399 #define JSON_HAS_CPP_11 2400 #endif 2401 2402 #ifdef __has_include 2403 #if __has_include(<version>) 2404 #include <version> 2405 #endif 2406 #endif 2407 2408 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) 2409 #ifdef JSON_HAS_CPP_17 2410 #if defined(__cpp_lib_filesystem) 2411 #define JSON_HAS_FILESYSTEM 1 2412 #elif defined(__cpp_lib_experimental_filesystem) 2413 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2414 #elif !defined(__has_include) 2415 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2416 #elif __has_include(<filesystem>) 2417 #define JSON_HAS_FILESYSTEM 1 2418 #elif __has_include(<experimental/filesystem>) 2419 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2420 #endif 2421 2422 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ 2423 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 2424 #undef JSON_HAS_FILESYSTEM 2425 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2426 #endif 2427 2428 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support 2429 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 2430 #undef JSON_HAS_FILESYSTEM 2431 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2432 #endif 2433 2434 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support 2435 #if defined(__clang_major__) && __clang_major__ < 7 2436 #undef JSON_HAS_FILESYSTEM 2437 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2438 #endif 2439 2440 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support 2441 #if defined(_MSC_VER) && _MSC_VER < 1914 2442 #undef JSON_HAS_FILESYSTEM 2443 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2444 #endif 2445 2446 // no filesystem support before iOS 13 2447 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 2448 #undef JSON_HAS_FILESYSTEM 2449 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2450 #endif 2451 2452 // no filesystem support before macOS Catalina 2453 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 2454 #undef JSON_HAS_FILESYSTEM 2455 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2456 #endif 2457 #endif 2458 #endif 2459 2460 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2461 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 2462 #endif 2463 2464 #ifndef JSON_HAS_FILESYSTEM 2465 #define JSON_HAS_FILESYSTEM 0 2466 #endif 2467 2468 #ifndef JSON_HAS_THREE_WAY_COMPARISON 2469 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ 2470 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L 2471 #define JSON_HAS_THREE_WAY_COMPARISON 1 2472 #else 2473 #define JSON_HAS_THREE_WAY_COMPARISON 0 2474 #endif 2475 #endif 2476 2477 #ifndef JSON_HAS_RANGES 2478 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error 2479 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 2480 #define JSON_HAS_RANGES 0 2481 #elif defined(__cpp_lib_ranges) 2482 #define JSON_HAS_RANGES 1 2483 #else 2484 #define JSON_HAS_RANGES 0 2485 #endif 2486 #endif 2487 2488 #ifdef JSON_HAS_CPP_17 2489 #define JSON_INLINE_VARIABLE inline 2490 #else 2491 #define JSON_INLINE_VARIABLE 2492 #endif 2493 2494 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) 2495 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] 2496 #else 2497 #define JSON_NO_UNIQUE_ADDRESS 2498 #endif 2499 2500 // disable documentation warnings on clang 2501 #if defined(__clang__) 2502 #pragma clang diagnostic push 2503 #pragma clang diagnostic ignored "-Wdocumentation" 2504 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" 2505 #endif 2506 2507 // allow disabling exceptions 2508 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) 2509 #define JSON_THROW(exception) throw exception 2510 #define JSON_TRY try 2511 #define JSON_CATCH(exception) catch(exception) 2512 #define JSON_INTERNAL_CATCH(exception) catch(exception) 2513 #else 2514 #include <cstdlib> 2515 #define JSON_THROW(exception) std::abort() 2516 #define JSON_TRY if(true) 2517 #define JSON_CATCH(exception) if(false) 2518 #define JSON_INTERNAL_CATCH(exception) if(false) 2519 #endif 2520 2521 // override exception macros 2522 #if defined(JSON_THROW_USER) 2523 #undef JSON_THROW 2524 #define JSON_THROW JSON_THROW_USER 2525 #endif 2526 #if defined(JSON_TRY_USER) 2527 #undef JSON_TRY 2528 #define JSON_TRY JSON_TRY_USER 2529 #endif 2530 #if defined(JSON_CATCH_USER) 2531 #undef JSON_CATCH 2532 #define JSON_CATCH JSON_CATCH_USER 2533 #undef JSON_INTERNAL_CATCH 2534 #define JSON_INTERNAL_CATCH JSON_CATCH_USER 2535 #endif 2536 #if defined(JSON_INTERNAL_CATCH_USER) 2537 #undef JSON_INTERNAL_CATCH 2538 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER 2539 #endif 2540 2541 // allow overriding assert 2542 #if !defined(JSON_ASSERT) 2543 #include <cassert> // assert 2544 #define JSON_ASSERT(x) assert(x) 2545 #endif 2546 2547 // allow to access some private functions (needed by the test suite) 2548 #if defined(JSON_TESTS_PRIVATE) 2549 #define JSON_PRIVATE_UNLESS_TESTED public 2550 #else 2551 #define JSON_PRIVATE_UNLESS_TESTED private 2552 #endif 2553 2554 /*! 2555 @brief macro to briefly define a mapping between an enum and JSON 2556 @def NLOHMANN_JSON_SERIALIZE_ENUM 2557 @since version 3.4.0 2558 */ 2559 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ 2560 template<typename BasicJsonType> \ 2561 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ 2562 { \ 2563 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ 2564 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ 2565 auto it = std::find_if(std::begin(m), std::end(m), \ 2566 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ 2567 { \ 2568 return ej_pair.first == e; \ 2569 }); \ 2570 j = ((it != std::end(m)) ? it : std::begin(m))->second; \ 2571 } \ 2572 template<typename BasicJsonType> \ 2573 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ 2574 { \ 2575 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ 2576 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ 2577 auto it = std::find_if(std::begin(m), std::end(m), \ 2578 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ 2579 { \ 2580 return ej_pair.second == j; \ 2581 }); \ 2582 e = ((it != std::end(m)) ? it : std::begin(m))->first; \ 2583 } 2584 2585 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They 2586 // may be removed in the future once the class is split. 2587 2588 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ 2589 template<template<typename, typename, typename...> class ObjectType, \ 2590 template<typename, typename...> class ArrayType, \ 2591 class StringType, class BooleanType, class NumberIntegerType, \ 2592 class NumberUnsignedType, class NumberFloatType, \ 2593 template<typename> class AllocatorType, \ 2594 template<typename, typename = void> class JSONSerializer, \ 2595 class BinaryType, \ 2596 class CustomBaseClass> 2597 2598 #define NLOHMANN_BASIC_JSON_TPL \ 2599 basic_json<ObjectType, ArrayType, StringType, BooleanType, \ 2600 NumberIntegerType, NumberUnsignedType, NumberFloatType, \ 2601 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> 2602 2603 // Macros to simplify conversion from/to types 2604 2605 #define NLOHMANN_JSON_EXPAND( x ) x 2606 #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 2607 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ 2608 NLOHMANN_JSON_PASTE64, \ 2609 NLOHMANN_JSON_PASTE63, \ 2610 NLOHMANN_JSON_PASTE62, \ 2611 NLOHMANN_JSON_PASTE61, \ 2612 NLOHMANN_JSON_PASTE60, \ 2613 NLOHMANN_JSON_PASTE59, \ 2614 NLOHMANN_JSON_PASTE58, \ 2615 NLOHMANN_JSON_PASTE57, \ 2616 NLOHMANN_JSON_PASTE56, \ 2617 NLOHMANN_JSON_PASTE55, \ 2618 NLOHMANN_JSON_PASTE54, \ 2619 NLOHMANN_JSON_PASTE53, \ 2620 NLOHMANN_JSON_PASTE52, \ 2621 NLOHMANN_JSON_PASTE51, \ 2622 NLOHMANN_JSON_PASTE50, \ 2623 NLOHMANN_JSON_PASTE49, \ 2624 NLOHMANN_JSON_PASTE48, \ 2625 NLOHMANN_JSON_PASTE47, \ 2626 NLOHMANN_JSON_PASTE46, \ 2627 NLOHMANN_JSON_PASTE45, \ 2628 NLOHMANN_JSON_PASTE44, \ 2629 NLOHMANN_JSON_PASTE43, \ 2630 NLOHMANN_JSON_PASTE42, \ 2631 NLOHMANN_JSON_PASTE41, \ 2632 NLOHMANN_JSON_PASTE40, \ 2633 NLOHMANN_JSON_PASTE39, \ 2634 NLOHMANN_JSON_PASTE38, \ 2635 NLOHMANN_JSON_PASTE37, \ 2636 NLOHMANN_JSON_PASTE36, \ 2637 NLOHMANN_JSON_PASTE35, \ 2638 NLOHMANN_JSON_PASTE34, \ 2639 NLOHMANN_JSON_PASTE33, \ 2640 NLOHMANN_JSON_PASTE32, \ 2641 NLOHMANN_JSON_PASTE31, \ 2642 NLOHMANN_JSON_PASTE30, \ 2643 NLOHMANN_JSON_PASTE29, \ 2644 NLOHMANN_JSON_PASTE28, \ 2645 NLOHMANN_JSON_PASTE27, \ 2646 NLOHMANN_JSON_PASTE26, \ 2647 NLOHMANN_JSON_PASTE25, \ 2648 NLOHMANN_JSON_PASTE24, \ 2649 NLOHMANN_JSON_PASTE23, \ 2650 NLOHMANN_JSON_PASTE22, \ 2651 NLOHMANN_JSON_PASTE21, \ 2652 NLOHMANN_JSON_PASTE20, \ 2653 NLOHMANN_JSON_PASTE19, \ 2654 NLOHMANN_JSON_PASTE18, \ 2655 NLOHMANN_JSON_PASTE17, \ 2656 NLOHMANN_JSON_PASTE16, \ 2657 NLOHMANN_JSON_PASTE15, \ 2658 NLOHMANN_JSON_PASTE14, \ 2659 NLOHMANN_JSON_PASTE13, \ 2660 NLOHMANN_JSON_PASTE12, \ 2661 NLOHMANN_JSON_PASTE11, \ 2662 NLOHMANN_JSON_PASTE10, \ 2663 NLOHMANN_JSON_PASTE9, \ 2664 NLOHMANN_JSON_PASTE8, \ 2665 NLOHMANN_JSON_PASTE7, \ 2666 NLOHMANN_JSON_PASTE6, \ 2667 NLOHMANN_JSON_PASTE5, \ 2668 NLOHMANN_JSON_PASTE4, \ 2669 NLOHMANN_JSON_PASTE3, \ 2670 NLOHMANN_JSON_PASTE2, \ 2671 NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) 2672 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1) 2673 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) 2674 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) 2675 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) 2676 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) 2677 #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) 2678 #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) 2679 #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) 2680 #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) 2681 #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) 2682 #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) 2683 #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) 2684 #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) 2685 #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) 2686 #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) 2687 #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) 2688 #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) 2689 #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) 2690 #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) 2691 #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) 2692 #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) 2693 #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) 2694 #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) 2695 #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) 2696 #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) 2697 #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) 2698 #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) 2699 #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) 2700 #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) 2701 #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) 2702 #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) 2703 #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) 2704 #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) 2705 #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) 2706 #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) 2707 #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) 2708 #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) 2709 #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) 2710 #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) 2711 #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) 2712 #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) 2713 #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) 2714 #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) 2715 #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) 2716 #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) 2717 #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) 2718 #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) 2719 #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) 2720 #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) 2721 #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) 2722 #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) 2723 #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) 2724 #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) 2725 #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) 2726 #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) 2727 #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) 2728 #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) 2729 #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) 2730 #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) 2731 #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) 2732 #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) 2733 #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) 2734 #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) 2735 2736 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; 2737 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); 2738 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); 2739 2740 /*! 2741 @brief macro 2742 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE 2743 @since version 3.9.0 2744 */ 2745 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ 2746 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2747 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2748 2749 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ 2750 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2751 friend void from_json(const nlohmann::json& 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__)) } 2752 2753 /*! 2754 @brief macro 2755 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE 2756 @since version 3.9.0 2757 */ 2758 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ 2759 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2760 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2761 2762 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ 2763 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2764 inline void from_json(const nlohmann::json& 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__)) } 2765 2766 2767 // inspired from https://stackoverflow.com/a/26745591 2768 // allows to call any std function as if (e.g. with begin): 2769 // using std::begin; begin(x); 2770 // 2771 // it allows using the detected idiom to retrieve the return type 2772 // of such an expression 2773 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ 2774 namespace detail { \ 2775 using std::std_name; \ 2776 \ 2777 template<typename... T> \ 2778 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2779 } \ 2780 \ 2781 namespace detail2 { \ 2782 struct std_name##_tag \ 2783 { \ 2784 }; \ 2785 \ 2786 template<typename... T> \ 2787 std_name##_tag std_name(T&&...); \ 2788 \ 2789 template<typename... T> \ 2790 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2791 \ 2792 template<typename... T> \ 2793 struct would_call_std_##std_name \ 2794 { \ 2795 static constexpr auto const value = ::nlohmann::detail:: \ 2796 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \ 2797 }; \ 2798 } /* namespace detail2 */ \ 2799 \ 2800 template<typename... T> \ 2801 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \ 2802 { \ 2803 } 2804 2805 #ifndef JSON_USE_IMPLICIT_CONVERSIONS 2806 #define JSON_USE_IMPLICIT_CONVERSIONS 1 2807 #endif 2808 2809 #if JSON_USE_IMPLICIT_CONVERSIONS 2810 #define JSON_EXPLICIT 2811 #else 2812 #define JSON_EXPLICIT explicit 2813 #endif 2814 2815 #ifndef JSON_DISABLE_ENUM_SERIALIZATION 2816 #define JSON_DISABLE_ENUM_SERIALIZATION 0 2817 #endif 2818 2819 #ifndef JSON_USE_GLOBAL_UDLS 2820 #define JSON_USE_GLOBAL_UDLS 1 2821 #endif 2822 2823 #if JSON_HAS_THREE_WAY_COMPARISON 2824 #include <compare> // partial_ordering 2825 #endif 2826 2827 NLOHMANN_JSON_NAMESPACE_BEGIN 2828 namespace detail 2829 { 2830 2831 /////////////////////////// 2832 // JSON type enumeration // 2833 /////////////////////////// 2834 2835 /*! 2836 @brief the JSON type enumeration 2837 2838 This enumeration collects the different JSON types. It is internally used to 2839 distinguish the stored values, and the functions @ref basic_json::is_null(), 2840 @ref basic_json::is_object(), @ref basic_json::is_array(), 2841 @ref basic_json::is_string(), @ref basic_json::is_boolean(), 2842 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(), 2843 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), 2844 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and 2845 @ref basic_json::is_structured() rely on it. 2846 2847 @note There are three enumeration entries (number_integer, number_unsigned, and 2848 number_float), because the library distinguishes these three types for numbers: 2849 @ref basic_json::number_unsigned_t is used for unsigned integers, 2850 @ref basic_json::number_integer_t is used for signed integers, and 2851 @ref basic_json::number_float_t is used for floating-point numbers or to 2852 approximate integers which do not fit in the limits of their respective type. 2853 2854 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON 2855 value with the default value for a given type 2856 2857 @since version 1.0.0 2858 */ 2859 enum class value_t : std::uint8_t 2860 { 2861 null, ///< null value 2862 object, ///< object (unordered set of name/value pairs) 2863 array, ///< array (ordered collection of values) 2864 string, ///< string value 2865 boolean, ///< boolean value 2866 number_integer, ///< number value (signed integer) 2867 number_unsigned, ///< number value (unsigned integer) 2868 number_float, ///< number value (floating-point) 2869 binary, ///< binary array (ordered collection of bytes) 2870 discarded ///< discarded by the parser callback function 2871 }; 2872 2873 /*! 2874 @brief comparison operator for JSON types 2875 2876 Returns an ordering that is similar to Python: 2877 - order: null < boolean < number < object < array < string < binary 2878 - furthermore, each type is not smaller than itself 2879 - discarded values are not comparable 2880 - binary is represented as a b"" string in python and directly comparable to a 2881 string; however, making a binary array directly comparable with a string would 2882 be surprising behavior in a JSON file. 2883 2884 @since version 1.0.0 2885 */ 2886 #if JSON_HAS_THREE_WAY_COMPARISON 2887 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* 2888 #else 2889 inline bool operator<(const value_t lhs, const value_t rhs) noexcept 2890 #endif 2891 { 2892 static constexpr std::array<std::uint8_t, 9> order = {{ 2893 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, 2894 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, 2895 6 /* binary */ 2896 } 2897 }; 2898 2899 const auto l_index = static_cast<std::size_t>(lhs); 2900 const auto r_index = static_cast<std::size_t>(rhs); 2901 #if JSON_HAS_THREE_WAY_COMPARISON 2902 if (l_index < order.size() && r_index < order.size()) 2903 { 2904 return order[l_index] <=> order[r_index]; // *NOPAD* 2905 } 2906 return std::partial_ordering::unordered; 2907 #else 2908 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; 2909 #endif 2910 } 2911 2912 // GCC selects the built-in operator< over an operator rewritten from 2913 // a user-defined spaceship operator 2914 // Clang, MSVC, and ICC select the rewritten candidate 2915 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) 2916 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) 2917 inline bool operator<(const value_t lhs, const value_t rhs) noexcept 2918 { 2919 return std::is_lt(lhs <=> rhs); // *NOPAD* 2920 } 2921 #endif 2922 2923 } // namespace detail 2924 NLOHMANN_JSON_NAMESPACE_END 2925 2926 // #include <nlohmann/detail/string_escape.hpp> 2927 // __ _____ _____ _____ 2928 // __| | __| | | | JSON for Modern C++ 2929 // | | |__ | | | | | | version 3.11.2 2930 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 2931 // 2932 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 2933 // SPDX-License-Identifier: MIT 2934 2935 2936 2937 // #include <nlohmann/detail/abi_macros.hpp> 2938 2939 2940 NLOHMANN_JSON_NAMESPACE_BEGIN 2941 namespace detail 2942 { 2943 2944 /*! 2945 @brief replace all occurrences of a substring by another string 2946 2947 @param[in,out] s the string to manipulate; changed so that all 2948 occurrences of @a f are replaced with @a t 2949 @param[in] f the substring to replace with @a t 2950 @param[in] t the string to replace @a f 2951 2952 @pre The search string @a f must not be empty. **This precondition is 2953 enforced with an assertion.** 2954 2955 @since version 2.0.0 2956 */ 2957 template<typename StringType> 2958 inline void replace_substring(StringType& s, const StringType& f, 2959 const StringType& t) 2960 { 2961 JSON_ASSERT(!f.empty()); 2962 for (auto pos = s.find(f); // find first occurrence of f 2963 pos != StringType::npos; // make sure f was found 2964 s.replace(pos, f.size(), t), // replace with t, and 2965 pos = s.find(f, pos + t.size())) // find next occurrence of f 2966 {} 2967 } 2968 2969 /*! 2970 * @brief string escaping as described in RFC 6901 (Sect. 4) 2971 * @param[in] s string to escape 2972 * @return escaped string 2973 * 2974 * Note the order of escaping "~" to "~0" and "/" to "~1" is important. 2975 */ 2976 template<typename StringType> 2977 inline StringType escape(StringType s) 2978 { 2979 replace_substring(s, StringType{"~"}, StringType{"~0"}); 2980 replace_substring(s, StringType{"/"}, StringType{"~1"}); 2981 return s; 2982 } 2983 2984 /*! 2985 * @brief string unescaping as described in RFC 6901 (Sect. 4) 2986 * @param[in] s string to unescape 2987 * @return unescaped string 2988 * 2989 * Note the order of escaping "~1" to "/" and "~0" to "~" is important. 2990 */ 2991 template<typename StringType> 2992 static void unescape(StringType& s) 2993 { 2994 replace_substring(s, StringType{"~1"}, StringType{"/"}); 2995 replace_substring(s, StringType{"~0"}, StringType{"~"}); 2996 } 2997 2998 } // namespace detail 2999 NLOHMANN_JSON_NAMESPACE_END 3000 3001 // #include <nlohmann/detail/input/position_t.hpp> 3002 // __ _____ _____ _____ 3003 // __| | __| | | | JSON for Modern C++ 3004 // | | |__ | | | | | | version 3.11.2 3005 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3006 // 3007 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 3008 // SPDX-License-Identifier: MIT 3009 3010 3011 3012 #include <cstddef> // size_t 3013 3014 // #include <nlohmann/detail/abi_macros.hpp> 3015 3016 3017 NLOHMANN_JSON_NAMESPACE_BEGIN 3018 namespace detail 3019 { 3020 3021 /// struct to capture the start position of the current token 3022 struct position_t 3023 { 3024 /// the total number of characters read 3025 std::size_t chars_read_total = 0; 3026 /// the number of characters read in the current line 3027 std::size_t chars_read_current_line = 0; 3028 /// the number of lines read 3029 std::size_t lines_read = 0; 3030 3031 /// conversion to size_t to preserve SAX interface 3032 constexpr operator size_t() const 3033 { 3034 return chars_read_total; 3035 } 3036 }; 3037 3038 } // namespace detail 3039 NLOHMANN_JSON_NAMESPACE_END 3040 3041 // #include <nlohmann/detail/macro_scope.hpp> 3042 3043 // #include <nlohmann/detail/meta/cpp_future.hpp> 3044 // __ _____ _____ _____ 3045 // __| | __| | | | JSON for Modern C++ 3046 // | | |__ | | | | | | version 3.11.2 3047 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3048 // 3049 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 3050 // SPDX-FileCopyrightText: 2018 The Abseil Authors 3051 // SPDX-License-Identifier: MIT 3052 3053 3054 3055 #include <array> // array 3056 #include <cstddef> // size_t 3057 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type 3058 #include <utility> // index_sequence, make_index_sequence, index_sequence_for 3059 3060 // #include <nlohmann/detail/macro_scope.hpp> 3061 3062 3063 NLOHMANN_JSON_NAMESPACE_BEGIN 3064 namespace detail 3065 { 3066 3067 template<typename T> 3068 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; 3069 3070 #ifdef JSON_HAS_CPP_14 3071 3072 // the following utilities are natively available in C++14 3073 using std::enable_if_t; 3074 using std::index_sequence; 3075 using std::make_index_sequence; 3076 using std::index_sequence_for; 3077 3078 #else 3079 3080 // alias templates to reduce boilerplate 3081 template<bool B, typename T = void> 3082 using enable_if_t = typename std::enable_if<B, T>::type; 3083 3084 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h 3085 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. 3086 3087 //// START OF CODE FROM GOOGLE ABSEIL 3088 3089 // integer_sequence 3090 // 3091 // Class template representing a compile-time integer sequence. An instantiation 3092 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its 3093 // type through its template arguments (which is a common need when 3094 // working with C++11 variadic templates). `absl::integer_sequence` is designed 3095 // to be a drop-in replacement for C++14's `std::integer_sequence`. 3096 // 3097 // Example: 3098 // 3099 // template< class T, T... Ints > 3100 // void user_function(integer_sequence<T, Ints...>); 3101 // 3102 // int main() 3103 // { 3104 // // user_function's `T` will be deduced to `int` and `Ints...` 3105 // // will be deduced to `0, 1, 2, 3, 4`. 3106 // user_function(make_integer_sequence<int, 5>()); 3107 // } 3108 template <typename T, T... Ints> 3109 struct integer_sequence 3110 { 3111 using value_type = T; 3112 static constexpr std::size_t size() noexcept 3113 { 3114 return sizeof...(Ints); 3115 } 3116 }; 3117 3118 // index_sequence 3119 // 3120 // A helper template for an `integer_sequence` of `size_t`, 3121 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's 3122 // `std::index_sequence`. 3123 template <size_t... Ints> 3124 using index_sequence = integer_sequence<size_t, Ints...>; 3125 3126 namespace utility_internal 3127 { 3128 3129 template <typename Seq, size_t SeqSize, size_t Rem> 3130 struct Extend; 3131 3132 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. 3133 template <typename T, T... Ints, size_t SeqSize> 3134 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> 3135 { 3136 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; 3137 }; 3138 3139 template <typename T, T... Ints, size_t SeqSize> 3140 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> 3141 { 3142 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; 3143 }; 3144 3145 // Recursion helper for 'make_integer_sequence<T, N>'. 3146 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. 3147 template <typename T, size_t N> 3148 struct Gen 3149 { 3150 using type = 3151 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; 3152 }; 3153 3154 template <typename T> 3155 struct Gen<T, 0> 3156 { 3157 using type = integer_sequence<T>; 3158 }; 3159 3160 } // namespace utility_internal 3161 3162 // Compile-time sequences of integers 3163 3164 // make_integer_sequence 3165 // 3166 // This template alias is equivalent to 3167 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in 3168 // replacement for C++14's `std::make_integer_sequence`. 3169 template <typename T, T N> 3170 using make_integer_sequence = typename utility_internal::Gen<T, N>::type; 3171 3172 // make_index_sequence 3173 // 3174 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, 3175 // and is designed to be a drop-in replacement for C++14's 3176 // `std::make_index_sequence`. 3177 template <size_t N> 3178 using make_index_sequence = make_integer_sequence<size_t, N>; 3179 3180 // index_sequence_for 3181 // 3182 // Converts a typename pack into an index sequence of the same length, and 3183 // is designed to be a drop-in replacement for C++14's 3184 // `std::index_sequence_for()` 3185 template <typename... Ts> 3186 using index_sequence_for = make_index_sequence<sizeof...(Ts)>; 3187 3188 //// END OF CODE FROM GOOGLE ABSEIL 3189 3190 #endif 3191 3192 // dispatch utility (taken from ranges-v3) 3193 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {}; 3194 template<> struct priority_tag<0> {}; 3195 3196 // taken from ranges-v3 3197 template<typename T> 3198 struct static_const 3199 { 3200 static JSON_INLINE_VARIABLE constexpr T value{}; 3201 }; 3202 3203 #ifndef JSON_HAS_CPP_17 3204 template<typename T> 3205 constexpr T static_const<T>::value; 3206 #endif 3207 3208 template<typename T, typename... Args> 3209 inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args) 3210 { 3211 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}}; 3212 } 3213 3214 } // namespace detail 3215 NLOHMANN_JSON_NAMESPACE_END 3216 3217 // #include <nlohmann/detail/meta/type_traits.hpp> 3218 // __ _____ _____ _____ 3219 // __| | __| | | | JSON for Modern C++ 3220 // | | |__ | | | | | | version 3.11.2 3221 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3222 // 3223 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 3224 // SPDX-License-Identifier: MIT 3225 3226 3227 3228 #include <limits> // numeric_limits 3229 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type 3230 #include <utility> // declval 3231 #include <tuple> // tuple 3232 3233 // #include <nlohmann/detail/iterators/iterator_traits.hpp> 3234 // __ _____ _____ _____ 3235 // __| | __| | | | JSON for Modern C++ 3236 // | | |__ | | | | | | version 3.11.2 3237 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3238 // 3239 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 3240 // SPDX-License-Identifier: MIT 3241 3242 3243 3244 #include <iterator> // random_access_iterator_tag 3245 3246 // #include <nlohmann/detail/abi_macros.hpp> 3247 3248 // #include <nlohmann/detail/meta/void_t.hpp> 3249 3250 // #include <nlohmann/detail/meta/cpp_future.hpp> 3251 3252 3253 NLOHMANN_JSON_NAMESPACE_BEGIN 3254 namespace detail 3255 { 3256 3257 template<typename It, typename = void> 3258 struct iterator_types {}; 3259 3260 template<typename It> 3261 struct iterator_types < 3262 It, 3263 void_t<typename It::difference_type, typename It::value_type, typename It::pointer, 3264 typename It::reference, typename It::iterator_category >> 3265 { 3266 using difference_type = typename It::difference_type; 3267 using value_type = typename It::value_type; 3268 using pointer = typename It::pointer; 3269 using reference = typename It::reference; 3270 using iterator_category = typename It::iterator_category; 3271 }; 3272 3273 // This is required as some compilers implement std::iterator_traits in a way that 3274 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. 3275 template<typename T, typename = void> 3276 struct iterator_traits 3277 { 3278 }; 3279 3280 template<typename T> 3281 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >> 3282 : iterator_types<T> 3283 { 3284 }; 3285 3286 template<typename T> 3287 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> 3288 { 3289 using iterator_category = std::random_access_iterator_tag; 3290 using value_type = T; 3291 using difference_type = ptrdiff_t; 3292 using pointer = T*; 3293 using reference = T&; 3294 }; 3295 3296 } // namespace detail 3297 NLOHMANN_JSON_NAMESPACE_END 3298 3299 // #include <nlohmann/detail/macro_scope.hpp> 3300 3301 // #include <nlohmann/detail/meta/call_std/begin.hpp> 3302 // __ _____ _____ _____ 3303 // __| | __| | | | JSON for Modern C++ 3304 // | | |__ | | | | | | version 3.11.2 3305 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3306 // 3307 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 3308 // SPDX-License-Identifier: MIT 3309 3310 3311 3312 // #include <nlohmann/detail/macro_scope.hpp> 3313 3314 3315 NLOHMANN_JSON_NAMESPACE_BEGIN 3316 3317 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); 3318 3319 NLOHMANN_JSON_NAMESPACE_END 3320 3321 // #include <nlohmann/detail/meta/call_std/end.hpp> 3322 // __ _____ _____ _____ 3323 // __| | __| | | | JSON for Modern C++ 3324 // | | |__ | | | | | | version 3.11.2 3325 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3326 // 3327 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 3328 // SPDX-License-Identifier: MIT 3329 3330 3331 3332 // #include <nlohmann/detail/macro_scope.hpp> 3333 3334 3335 NLOHMANN_JSON_NAMESPACE_BEGIN 3336 3337 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); 3338 3339 NLOHMANN_JSON_NAMESPACE_END 3340 3341 // #include <nlohmann/detail/meta/cpp_future.hpp> 3342 3343 // #include <nlohmann/detail/meta/detected.hpp> 3344 3345 // #include <nlohmann/json_fwd.hpp> 3346 // __ _____ _____ _____ 3347 // __| | __| | | | JSON for Modern C++ 3348 // | | |__ | | | | | | version 3.11.2 3349 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3350 // 3351 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 3352 // SPDX-License-Identifier: MIT 3353 3354 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3355 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3356 3357 #include <cstdint> // int64_t, uint64_t 3358 #include <map> // map 3359 #include <memory> // allocator 3360 #include <string> // string 3361 #include <vector> // vector 3362 3363 // #include <nlohmann/detail/abi_macros.hpp> 3364 3365 3366 /*! 3367 @brief namespace for Niels Lohmann 3368 @see https://github.com/nlohmann 3369 @since version 1.0.0 3370 */ 3371 NLOHMANN_JSON_NAMESPACE_BEGIN 3372 3373 /*! 3374 @brief default JSONSerializer template argument 3375 3376 This serializer ignores the template arguments and uses ADL 3377 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) 3378 for serialization. 3379 */ 3380 template<typename T = void, typename SFINAE = void> 3381 struct adl_serializer; 3382 3383 /// a class to store JSON values 3384 /// @sa https://json.nlohmann.me/api/basic_json/ 3385 template<template<typename U, typename V, typename... Args> class ObjectType = 3386 std::map, 3387 template<typename U, typename... Args> class ArrayType = std::vector, 3388 class StringType = std::string, class BooleanType = bool, 3389 class NumberIntegerType = std::int64_t, 3390 class NumberUnsignedType = std::uint64_t, 3391 class NumberFloatType = double, 3392 template<typename U> class AllocatorType = std::allocator, 3393 template<typename T, typename SFINAE = void> class JSONSerializer = 3394 adl_serializer, 3395 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError 3396 class CustomBaseClass = void> 3397 class basic_json; 3398 3399 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 3400 /// @sa https://json.nlohmann.me/api/json_pointer/ 3401 template<typename RefStringType> 3402 class json_pointer; 3403 3404 /*! 3405 @brief default specialization 3406 @sa https://json.nlohmann.me/api/json/ 3407 */ 3408 using json = basic_json<>; 3409 3410 /// @brief a minimal map-like container that preserves insertion order 3411 /// @sa https://json.nlohmann.me/api/ordered_map/ 3412 template<class Key, class T, class IgnoredLess, class Allocator> 3413 struct ordered_map; 3414 3415 /// @brief specialization that maintains the insertion order of object keys 3416 /// @sa https://json.nlohmann.me/api/ordered_json/ 3417 using ordered_json = basic_json<nlohmann::ordered_map>; 3418 3419 NLOHMANN_JSON_NAMESPACE_END 3420 3421 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3422 3423 3424 NLOHMANN_JSON_NAMESPACE_BEGIN 3425 /*! 3426 @brief detail namespace with internal helper functions 3427 3428 This namespace collects functions that should not be exposed, 3429 implementations of some @ref basic_json methods, and meta-programming helpers. 3430 3431 @since version 2.1.0 3432 */ 3433 namespace detail 3434 { 3435 3436 ///////////// 3437 // helpers // 3438 ///////////// 3439 3440 // Note to maintainers: 3441 // 3442 // Every trait in this file expects a non CV-qualified type. 3443 // The only exceptions are in the 'aliases for detected' section 3444 // (i.e. those of the form: decltype(T::member_function(std::declval<T>()))) 3445 // 3446 // In this case, T has to be properly CV-qualified to constraint the function arguments 3447 // (e.g. to_json(BasicJsonType&, const T&)) 3448 3449 template<typename> struct is_basic_json : std::false_type {}; 3450 3451 NLOHMANN_BASIC_JSON_TPL_DECLARATION 3452 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {}; 3453 3454 // used by exceptions create() member functions 3455 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t 3456 // false_type otherwise 3457 template<typename BasicJsonContext> 3458 struct is_basic_json_context : 3459 std::integral_constant < bool, 3460 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value 3461 || std::is_same<BasicJsonContext, std::nullptr_t>::value > 3462 {}; 3463 3464 ////////////////////// 3465 // json_ref helpers // 3466 ////////////////////// 3467 3468 template<typename> 3469 class json_ref; 3470 3471 template<typename> 3472 struct is_json_ref : std::false_type {}; 3473 3474 template<typename T> 3475 struct is_json_ref<json_ref<T>> : std::true_type {}; 3476 3477 ////////////////////////// 3478 // aliases for detected // 3479 ////////////////////////// 3480 3481 template<typename T> 3482 using mapped_type_t = typename T::mapped_type; 3483 3484 template<typename T> 3485 using key_type_t = typename T::key_type; 3486 3487 template<typename T> 3488 using value_type_t = typename T::value_type; 3489 3490 template<typename T> 3491 using difference_type_t = typename T::difference_type; 3492 3493 template<typename T> 3494 using pointer_t = typename T::pointer; 3495 3496 template<typename T> 3497 using reference_t = typename T::reference; 3498 3499 template<typename T> 3500 using iterator_category_t = typename T::iterator_category; 3501 3502 template<typename T, typename... Args> 3503 using to_json_function = decltype(T::to_json(std::declval<Args>()...)); 3504 3505 template<typename T, typename... Args> 3506 using from_json_function = decltype(T::from_json(std::declval<Args>()...)); 3507 3508 template<typename T, typename U> 3509 using get_template_function = decltype(std::declval<T>().template get<U>()); 3510 3511 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists 3512 template<typename BasicJsonType, typename T, typename = void> 3513 struct has_from_json : std::false_type {}; 3514 3515 // trait checking if j.get<T> is valid 3516 // use this trait instead of std::is_constructible or std::is_convertible, 3517 // both rely on, or make use of implicit conversions, and thus fail when T 3518 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) 3519 template <typename BasicJsonType, typename T> 3520 struct is_getable 3521 { 3522 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value; 3523 }; 3524 3525 template<typename BasicJsonType, typename T> 3526 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3527 { 3528 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3529 3530 static constexpr bool value = 3531 is_detected_exact<void, from_json_function, serializer, 3532 const BasicJsonType&, T&>::value; 3533 }; 3534 3535 // This trait checks if JSONSerializer<T>::from_json(json const&) exists 3536 // this overload is used for non-default-constructible user-defined-types 3537 template<typename BasicJsonType, typename T, typename = void> 3538 struct has_non_default_from_json : std::false_type {}; 3539 3540 template<typename BasicJsonType, typename T> 3541 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3542 { 3543 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3544 3545 static constexpr bool value = 3546 is_detected_exact<T, from_json_function, serializer, 3547 const BasicJsonType&>::value; 3548 }; 3549 3550 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists 3551 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. 3552 template<typename BasicJsonType, typename T, typename = void> 3553 struct has_to_json : std::false_type {}; 3554 3555 template<typename BasicJsonType, typename T> 3556 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3557 { 3558 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3559 3560 static constexpr bool value = 3561 is_detected_exact<void, to_json_function, serializer, BasicJsonType&, 3562 T>::value; 3563 }; 3564 3565 template<typename T> 3566 using detect_key_compare = typename T::key_compare; 3567 3568 template<typename T> 3569 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {}; 3570 3571 // obtains the actual object key comparator 3572 template<typename BasicJsonType> 3573 struct actual_object_comparator 3574 { 3575 using object_t = typename BasicJsonType::object_t; 3576 using object_comparator_t = typename BasicJsonType::default_object_comparator_t; 3577 using type = typename std::conditional < has_key_compare<object_t>::value, 3578 typename object_t::key_compare, object_comparator_t>::type; 3579 }; 3580 3581 template<typename BasicJsonType> 3582 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type; 3583 3584 /////////////////// 3585 // is_ functions // 3586 /////////////////// 3587 3588 // https://en.cppreference.com/w/cpp/types/conjunction 3589 template<class...> struct conjunction : std::true_type { }; 3590 template<class B> struct conjunction<B> : B { }; 3591 template<class B, class... Bn> 3592 struct conjunction<B, Bn...> 3593 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {}; 3594 3595 // https://en.cppreference.com/w/cpp/types/negation 3596 template<class B> struct negation : std::integral_constant < bool, !B::value > { }; 3597 3598 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for 3599 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). 3600 // This causes compile errors in e.g. clang 3.5 or gcc 4.9. 3601 template <typename T> 3602 struct is_default_constructible : std::is_default_constructible<T> {}; 3603 3604 template <typename T1, typename T2> 3605 struct is_default_constructible<std::pair<T1, T2>> 3606 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; 3607 3608 template <typename T1, typename T2> 3609 struct is_default_constructible<const std::pair<T1, T2>> 3610 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; 3611 3612 template <typename... Ts> 3613 struct is_default_constructible<std::tuple<Ts...>> 3614 : conjunction<is_default_constructible<Ts>...> {}; 3615 3616 template <typename... Ts> 3617 struct is_default_constructible<const std::tuple<Ts...>> 3618 : conjunction<is_default_constructible<Ts>...> {}; 3619 3620 3621 template <typename T, typename... Args> 3622 struct is_constructible : std::is_constructible<T, Args...> {}; 3623 3624 template <typename T1, typename T2> 3625 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {}; 3626 3627 template <typename T1, typename T2> 3628 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {}; 3629 3630 template <typename... Ts> 3631 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {}; 3632 3633 template <typename... Ts> 3634 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {}; 3635 3636 3637 template<typename T, typename = void> 3638 struct is_iterator_traits : std::false_type {}; 3639 3640 template<typename T> 3641 struct is_iterator_traits<iterator_traits<T>> 3642 { 3643 private: 3644 using traits = iterator_traits<T>; 3645 3646 public: 3647 static constexpr auto value = 3648 is_detected<value_type_t, traits>::value && 3649 is_detected<difference_type_t, traits>::value && 3650 is_detected<pointer_t, traits>::value && 3651 is_detected<iterator_category_t, traits>::value && 3652 is_detected<reference_t, traits>::value; 3653 }; 3654 3655 template<typename T> 3656 struct is_range 3657 { 3658 private: 3659 using t_ref = typename std::add_lvalue_reference<T>::type; 3660 3661 using iterator = detected_t<result_of_begin, t_ref>; 3662 using sentinel = detected_t<result_of_end, t_ref>; 3663 3664 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator 3665 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for 3666 // but reimplementing these would be too much work, as a lot of other concepts are used underneath 3667 static constexpr auto is_iterator_begin = 3668 is_iterator_traits<iterator_traits<iterator>>::value; 3669 3670 public: 3671 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin; 3672 }; 3673 3674 template<typename R> 3675 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>; 3676 3677 template<typename T> 3678 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>; 3679 3680 // The following implementation of is_complete_type is taken from 3681 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ 3682 // and is written by Xiang Fan who agreed to using it in this library. 3683 3684 template<typename T, typename = void> 3685 struct is_complete_type : std::false_type {}; 3686 3687 template<typename T> 3688 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {}; 3689 3690 template<typename BasicJsonType, typename CompatibleObjectType, 3691 typename = void> 3692 struct is_compatible_object_type_impl : std::false_type {}; 3693 3694 template<typename BasicJsonType, typename CompatibleObjectType> 3695 struct is_compatible_object_type_impl < 3696 BasicJsonType, CompatibleObjectType, 3697 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&& 3698 is_detected<key_type_t, CompatibleObjectType>::value >> 3699 { 3700 using object_t = typename BasicJsonType::object_t; 3701 3702 // macOS's is_constructible does not play well with nonesuch... 3703 static constexpr bool value = 3704 is_constructible<typename object_t::key_type, 3705 typename CompatibleObjectType::key_type>::value && 3706 is_constructible<typename object_t::mapped_type, 3707 typename CompatibleObjectType::mapped_type>::value; 3708 }; 3709 3710 template<typename BasicJsonType, typename CompatibleObjectType> 3711 struct is_compatible_object_type 3712 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {}; 3713 3714 template<typename BasicJsonType, typename ConstructibleObjectType, 3715 typename = void> 3716 struct is_constructible_object_type_impl : std::false_type {}; 3717 3718 template<typename BasicJsonType, typename ConstructibleObjectType> 3719 struct is_constructible_object_type_impl < 3720 BasicJsonType, ConstructibleObjectType, 3721 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&& 3722 is_detected<key_type_t, ConstructibleObjectType>::value >> 3723 { 3724 using object_t = typename BasicJsonType::object_t; 3725 3726 static constexpr bool value = 3727 (is_default_constructible<ConstructibleObjectType>::value && 3728 (std::is_move_assignable<ConstructibleObjectType>::value || 3729 std::is_copy_assignable<ConstructibleObjectType>::value) && 3730 (is_constructible<typename ConstructibleObjectType::key_type, 3731 typename object_t::key_type>::value && 3732 std::is_same < 3733 typename object_t::mapped_type, 3734 typename ConstructibleObjectType::mapped_type >::value)) || 3735 (has_from_json<BasicJsonType, 3736 typename ConstructibleObjectType::mapped_type>::value || 3737 has_non_default_from_json < 3738 BasicJsonType, 3739 typename ConstructibleObjectType::mapped_type >::value); 3740 }; 3741 3742 template<typename BasicJsonType, typename ConstructibleObjectType> 3743 struct is_constructible_object_type 3744 : is_constructible_object_type_impl<BasicJsonType, 3745 ConstructibleObjectType> {}; 3746 3747 template<typename BasicJsonType, typename CompatibleStringType> 3748 struct is_compatible_string_type 3749 { 3750 static constexpr auto value = 3751 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value; 3752 }; 3753 3754 template<typename BasicJsonType, typename ConstructibleStringType> 3755 struct is_constructible_string_type 3756 { 3757 // launder type through decltype() to fix compilation failure on ICPC 3758 #ifdef __INTEL_COMPILER 3759 using laundered_type = decltype(std::declval<ConstructibleStringType>()); 3760 #else 3761 using laundered_type = ConstructibleStringType; 3762 #endif 3763 3764 static constexpr auto value = 3765 conjunction < 3766 is_constructible<laundered_type, typename BasicJsonType::string_t>, 3767 is_detected_exact<typename BasicJsonType::string_t::value_type, 3768 value_type_t, laundered_type >>::value; 3769 }; 3770 3771 template<typename BasicJsonType, typename CompatibleArrayType, typename = void> 3772 struct is_compatible_array_type_impl : std::false_type {}; 3773 3774 template<typename BasicJsonType, typename CompatibleArrayType> 3775 struct is_compatible_array_type_impl < 3776 BasicJsonType, CompatibleArrayType, 3777 enable_if_t < 3778 is_detected<iterator_t, CompatibleArrayType>::value&& 3779 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&& 3780 // special case for types like std::filesystem::path whose iterator's value_type are themselves 3781 // c.f. https://github.com/nlohmann/json/pull/3073 3782 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >> 3783 { 3784 static constexpr bool value = 3785 is_constructible<BasicJsonType, 3786 range_value_t<CompatibleArrayType>>::value; 3787 }; 3788 3789 template<typename BasicJsonType, typename CompatibleArrayType> 3790 struct is_compatible_array_type 3791 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {}; 3792 3793 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void> 3794 struct is_constructible_array_type_impl : std::false_type {}; 3795 3796 template<typename BasicJsonType, typename ConstructibleArrayType> 3797 struct is_constructible_array_type_impl < 3798 BasicJsonType, ConstructibleArrayType, 3799 enable_if_t<std::is_same<ConstructibleArrayType, 3800 typename BasicJsonType::value_type>::value >> 3801 : std::true_type {}; 3802 3803 template<typename BasicJsonType, typename ConstructibleArrayType> 3804 struct is_constructible_array_type_impl < 3805 BasicJsonType, ConstructibleArrayType, 3806 enable_if_t < !std::is_same<ConstructibleArrayType, 3807 typename BasicJsonType::value_type>::value&& 3808 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&& 3809 is_default_constructible<ConstructibleArrayType>::value&& 3810 (std::is_move_assignable<ConstructibleArrayType>::value || 3811 std::is_copy_assignable<ConstructibleArrayType>::value)&& 3812 is_detected<iterator_t, ConstructibleArrayType>::value&& 3813 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&& 3814 is_detected<range_value_t, ConstructibleArrayType>::value&& 3815 // special case for types like std::filesystem::path whose iterator's value_type are themselves 3816 // c.f. https://github.com/nlohmann/json/pull/3073 3817 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&& 3818 is_complete_type < 3819 detected_t<range_value_t, ConstructibleArrayType >>::value >> 3820 { 3821 using value_type = range_value_t<ConstructibleArrayType>; 3822 3823 static constexpr bool value = 3824 std::is_same<value_type, 3825 typename BasicJsonType::array_t::value_type>::value || 3826 has_from_json<BasicJsonType, 3827 value_type>::value || 3828 has_non_default_from_json < 3829 BasicJsonType, 3830 value_type >::value; 3831 }; 3832 3833 template<typename BasicJsonType, typename ConstructibleArrayType> 3834 struct is_constructible_array_type 3835 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {}; 3836 3837 template<typename RealIntegerType, typename CompatibleNumberIntegerType, 3838 typename = void> 3839 struct is_compatible_integer_type_impl : std::false_type {}; 3840 3841 template<typename RealIntegerType, typename CompatibleNumberIntegerType> 3842 struct is_compatible_integer_type_impl < 3843 RealIntegerType, CompatibleNumberIntegerType, 3844 enable_if_t < std::is_integral<RealIntegerType>::value&& 3845 std::is_integral<CompatibleNumberIntegerType>::value&& 3846 !std::is_same<bool, CompatibleNumberIntegerType>::value >> 3847 { 3848 // is there an assert somewhere on overflows? 3849 using RealLimits = std::numeric_limits<RealIntegerType>; 3850 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>; 3851 3852 static constexpr auto value = 3853 is_constructible<RealIntegerType, 3854 CompatibleNumberIntegerType>::value && 3855 CompatibleLimits::is_integer && 3856 RealLimits::is_signed == CompatibleLimits::is_signed; 3857 }; 3858 3859 template<typename RealIntegerType, typename CompatibleNumberIntegerType> 3860 struct is_compatible_integer_type 3861 : is_compatible_integer_type_impl<RealIntegerType, 3862 CompatibleNumberIntegerType> {}; 3863 3864 template<typename BasicJsonType, typename CompatibleType, typename = void> 3865 struct is_compatible_type_impl: std::false_type {}; 3866 3867 template<typename BasicJsonType, typename CompatibleType> 3868 struct is_compatible_type_impl < 3869 BasicJsonType, CompatibleType, 3870 enable_if_t<is_complete_type<CompatibleType>::value >> 3871 { 3872 static constexpr bool value = 3873 has_to_json<BasicJsonType, CompatibleType>::value; 3874 }; 3875 3876 template<typename BasicJsonType, typename CompatibleType> 3877 struct is_compatible_type 3878 : is_compatible_type_impl<BasicJsonType, CompatibleType> {}; 3879 3880 template<typename T1, typename T2> 3881 struct is_constructible_tuple : std::false_type {}; 3882 3883 template<typename T1, typename... Args> 3884 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {}; 3885 3886 template<typename BasicJsonType, typename T> 3887 struct is_json_iterator_of : std::false_type {}; 3888 3889 template<typename BasicJsonType> 3890 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {}; 3891 3892 template<typename BasicJsonType> 3893 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type 3894 {}; 3895 3896 // checks if a given type T is a template specialization of Primary 3897 template<template <typename...> class Primary, typename T> 3898 struct is_specialization_of : std::false_type {}; 3899 3900 template<template <typename...> class Primary, typename... Args> 3901 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {}; 3902 3903 template<typename T> 3904 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>; 3905 3906 // checks if A and B are comparable using Compare functor 3907 template<typename Compare, typename A, typename B, typename = void> 3908 struct is_comparable : std::false_type {}; 3909 3910 template<typename Compare, typename A, typename B> 3911 struct is_comparable<Compare, A, B, void_t< 3912 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())), 3913 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>())) 3914 >> : std::true_type {}; 3915 3916 template<typename T> 3917 using detect_is_transparent = typename T::is_transparent; 3918 3919 // type trait to check if KeyType can be used as object key (without a BasicJsonType) 3920 // see is_usable_as_basic_json_key_type below 3921 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, 3922 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> 3923 using is_usable_as_key_type = typename std::conditional < 3924 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value 3925 && !(ExcludeObjectKeyType && std::is_same<KeyType, 3926 ObjectKeyType>::value) 3927 && (!RequireTransparentComparator 3928 || is_detected <detect_is_transparent, Comparator>::value) 3929 && !is_json_pointer<KeyType>::value, 3930 std::true_type, 3931 std::false_type >::type; 3932 3933 // type trait to check if KeyType can be used as object key 3934 // true if: 3935 // - KeyType is comparable with BasicJsonType::object_t::key_type 3936 // - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type 3937 // - the comparator is transparent or RequireTransparentComparator is false 3938 // - KeyType is not a JSON iterator or json_pointer 3939 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, 3940 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> 3941 using is_usable_as_basic_json_key_type = typename std::conditional < 3942 is_usable_as_key_type<typename BasicJsonType::object_comparator_t, 3943 typename BasicJsonType::object_t::key_type, KeyTypeCVRef, 3944 RequireTransparentComparator, ExcludeObjectKeyType>::value 3945 && !is_json_iterator_of<BasicJsonType, KeyType>::value, 3946 std::true_type, 3947 std::false_type >::type; 3948 3949 template<typename ObjectType, typename KeyType> 3950 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>())); 3951 3952 // type trait to check if object_t has an erase() member functions accepting KeyType 3953 template<typename BasicJsonType, typename KeyType> 3954 using has_erase_with_key_type = typename std::conditional < 3955 is_detected < 3956 detect_erase_with_key_type, 3957 typename BasicJsonType::object_t, KeyType >::value, 3958 std::true_type, 3959 std::false_type >::type; 3960 3961 // a naive helper to check if a type is an ordered_map (exploits the fact that 3962 // ordered_map inherits capacity() from std::vector) 3963 template <typename T> 3964 struct is_ordered_map 3965 { 3966 using one = char; 3967 3968 struct two 3969 { 3970 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 3971 }; 3972 3973 template <typename C> static one test( decltype(&C::capacity) ) ; 3974 template <typename C> static two test(...); 3975 3976 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 3977 }; 3978 3979 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) 3980 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 > 3981 T conditional_static_cast(U value) 3982 { 3983 return static_cast<T>(value); 3984 } 3985 3986 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0> 3987 T conditional_static_cast(U value) 3988 { 3989 return value; 3990 } 3991 3992 template<typename... Types> 3993 using all_integral = conjunction<std::is_integral<Types>...>; 3994 3995 template<typename... Types> 3996 using all_signed = conjunction<std::is_signed<Types>...>; 3997 3998 template<typename... Types> 3999 using all_unsigned = conjunction<std::is_unsigned<Types>...>; 4000 4001 // there's a disjunction trait in another PR; replace when merged 4002 template<typename... Types> 4003 using same_sign = std::integral_constant < bool, 4004 all_signed<Types...>::value || all_unsigned<Types...>::value >; 4005 4006 template<typename OfType, typename T> 4007 using never_out_of_range = std::integral_constant < bool, 4008 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) 4009 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >; 4010 4011 template<typename OfType, typename T, 4012 bool OfTypeSigned = std::is_signed<OfType>::value, 4013 bool TSigned = std::is_signed<T>::value> 4014 struct value_in_range_of_impl2; 4015 4016 template<typename OfType, typename T> 4017 struct value_in_range_of_impl2<OfType, T, false, false> 4018 { 4019 static constexpr bool test(T val) 4020 { 4021 using CommonType = typename std::common_type<OfType, T>::type; 4022 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4023 } 4024 }; 4025 4026 template<typename OfType, typename T> 4027 struct value_in_range_of_impl2<OfType, T, true, false> 4028 { 4029 static constexpr bool test(T val) 4030 { 4031 using CommonType = typename std::common_type<OfType, T>::type; 4032 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4033 } 4034 }; 4035 4036 template<typename OfType, typename T> 4037 struct value_in_range_of_impl2<OfType, T, false, true> 4038 { 4039 static constexpr bool test(T val) 4040 { 4041 using CommonType = typename std::common_type<OfType, T>::type; 4042 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4043 } 4044 }; 4045 4046 4047 template<typename OfType, typename T> 4048 struct value_in_range_of_impl2<OfType, T, true, true> 4049 { 4050 static constexpr bool test(T val) 4051 { 4052 using CommonType = typename std::common_type<OfType, T>::type; 4053 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)()) 4054 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4055 } 4056 }; 4057 4058 template<typename OfType, typename T, 4059 bool NeverOutOfRange = never_out_of_range<OfType, T>::value, 4060 typename = detail::enable_if_t<all_integral<OfType, T>::value>> 4061 struct value_in_range_of_impl1; 4062 4063 template<typename OfType, typename T> 4064 struct value_in_range_of_impl1<OfType, T, false> 4065 { 4066 static constexpr bool test(T val) 4067 { 4068 return value_in_range_of_impl2<OfType, T>::test(val); 4069 } 4070 }; 4071 4072 template<typename OfType, typename T> 4073 struct value_in_range_of_impl1<OfType, T, true> 4074 { 4075 static constexpr bool test(T /*val*/) 4076 { 4077 return true; 4078 } 4079 }; 4080 4081 template<typename OfType, typename T> 4082 inline constexpr bool value_in_range_of(T val) 4083 { 4084 return value_in_range_of_impl1<OfType, T>::test(val); 4085 } 4086 4087 template<bool Value> 4088 using bool_constant = std::integral_constant<bool, Value>; 4089 4090 /////////////////////////////////////////////////////////////////////////////// 4091 // is_c_string 4092 /////////////////////////////////////////////////////////////////////////////// 4093 4094 namespace impl 4095 { 4096 4097 template<typename T> 4098 inline constexpr bool is_c_string() 4099 { 4100 using TUnExt = typename std::remove_extent<T>::type; 4101 using TUnCVExt = typename std::remove_cv<TUnExt>::type; 4102 using TUnPtr = typename std::remove_pointer<T>::type; 4103 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type; 4104 return 4105 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) 4106 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value); 4107 } 4108 4109 } // namespace impl 4110 4111 // checks whether T is a [cv] char */[cv] char[] C string 4112 template<typename T> 4113 struct is_c_string : bool_constant<impl::is_c_string<T>()> {}; 4114 4115 template<typename T> 4116 using is_c_string_uncvref = is_c_string<uncvref_t<T>>; 4117 4118 /////////////////////////////////////////////////////////////////////////////// 4119 // is_transparent 4120 /////////////////////////////////////////////////////////////////////////////// 4121 4122 namespace impl 4123 { 4124 4125 template<typename T> 4126 inline constexpr bool is_transparent() 4127 { 4128 return is_detected<detect_is_transparent, T>::value; 4129 } 4130 4131 } // namespace impl 4132 4133 // checks whether T has a member named is_transparent 4134 template<typename T> 4135 struct is_transparent : bool_constant<impl::is_transparent<T>()> {}; 4136 4137 /////////////////////////////////////////////////////////////////////////////// 4138 4139 } // namespace detail 4140 NLOHMANN_JSON_NAMESPACE_END 4141 4142 // #include <nlohmann/detail/string_concat.hpp> 4143 // __ _____ _____ _____ 4144 // __| | __| | | | JSON for Modern C++ 4145 // | | |__ | | | | | | version 3.11.2 4146 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4147 // 4148 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 4149 // SPDX-License-Identifier: MIT 4150 4151 4152 4153 #include <cstring> // strlen 4154 #include <string> // string 4155 #include <utility> // forward 4156 4157 // #include <nlohmann/detail/meta/cpp_future.hpp> 4158 4159 // #include <nlohmann/detail/meta/detected.hpp> 4160 4161 4162 NLOHMANN_JSON_NAMESPACE_BEGIN 4163 namespace detail 4164 { 4165 4166 inline std::size_t concat_length() 4167 { 4168 return 0; 4169 } 4170 4171 template<typename... Args> 4172 inline std::size_t concat_length(const char* cstr, const Args& ... rest); 4173 4174 template<typename StringType, typename... Args> 4175 inline std::size_t concat_length(const StringType& str, const Args& ... rest); 4176 4177 template<typename... Args> 4178 inline std::size_t concat_length(const char /*c*/, const Args& ... rest) 4179 { 4180 return 1 + concat_length(rest...); 4181 } 4182 4183 template<typename... Args> 4184 inline std::size_t concat_length(const char* cstr, const Args& ... rest) 4185 { 4186 // cppcheck-suppress ignoredReturnValue 4187 return ::strlen(cstr) + concat_length(rest...); 4188 } 4189 4190 template<typename StringType, typename... Args> 4191 inline std::size_t concat_length(const StringType& str, const Args& ... rest) 4192 { 4193 return str.size() + concat_length(rest...); 4194 } 4195 4196 template<typename OutStringType> 4197 inline void concat_into(OutStringType& /*out*/) 4198 {} 4199 4200 template<typename StringType, typename Arg> 4201 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ())); 4202 4203 template<typename StringType, typename Arg> 4204 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>; 4205 4206 template<typename StringType, typename Arg> 4207 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ()); 4208 4209 template<typename StringType, typename Arg> 4210 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>; 4211 4212 template<typename StringType, typename Arg> 4213 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end())); 4214 4215 template<typename StringType, typename Arg> 4216 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>; 4217 4218 template<typename StringType, typename Arg> 4219 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size())); 4220 4221 template<typename StringType, typename Arg> 4222 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>; 4223 4224 template < typename OutStringType, typename Arg, typename... Args, 4225 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4226 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 > 4227 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); 4228 4229 template < typename OutStringType, typename Arg, typename... Args, 4230 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4231 && !detect_string_can_append_op<OutStringType, Arg>::value 4232 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 > 4233 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); 4234 4235 template < typename OutStringType, typename Arg, typename... Args, 4236 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4237 && !detect_string_can_append_op<OutStringType, Arg>::value 4238 && !detect_string_can_append_iter<OutStringType, Arg>::value 4239 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 > 4240 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); 4241 4242 template<typename OutStringType, typename Arg, typename... Args, 4243 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0> 4244 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) 4245 { 4246 out.append(std::forward<Arg>(arg)); 4247 concat_into(out, std::forward<Args>(rest)...); 4248 } 4249 4250 template < typename OutStringType, typename Arg, typename... Args, 4251 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4252 && detect_string_can_append_op<OutStringType, Arg>::value, int > > 4253 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) 4254 { 4255 out += std::forward<Arg>(arg); 4256 concat_into(out, std::forward<Args>(rest)...); 4257 } 4258 4259 template < typename OutStringType, typename Arg, typename... Args, 4260 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4261 && !detect_string_can_append_op<OutStringType, Arg>::value 4262 && detect_string_can_append_iter<OutStringType, Arg>::value, int > > 4263 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) 4264 { 4265 out.append(arg.begin(), arg.end()); 4266 concat_into(out, std::forward<Args>(rest)...); 4267 } 4268 4269 template < typename OutStringType, typename Arg, typename... Args, 4270 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4271 && !detect_string_can_append_op<OutStringType, Arg>::value 4272 && !detect_string_can_append_iter<OutStringType, Arg>::value 4273 && detect_string_can_append_data<OutStringType, Arg>::value, int > > 4274 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) 4275 { 4276 out.append(arg.data(), arg.size()); 4277 concat_into(out, std::forward<Args>(rest)...); 4278 } 4279 4280 template<typename OutStringType = std::string, typename... Args> 4281 inline OutStringType concat(Args && ... args) 4282 { 4283 OutStringType str; 4284 str.reserve(concat_length(args...)); 4285 concat_into(str, std::forward<Args>(args)...); 4286 return str; 4287 } 4288 4289 } // namespace detail 4290 NLOHMANN_JSON_NAMESPACE_END 4291 4292 4293 4294 NLOHMANN_JSON_NAMESPACE_BEGIN 4295 namespace detail 4296 { 4297 4298 //////////////// 4299 // exceptions // 4300 //////////////// 4301 4302 /// @brief general exception of the @ref basic_json class 4303 /// @sa https://json.nlohmann.me/api/basic_json/exception/ 4304 class exception : public std::exception 4305 { 4306 public: 4307 /// returns the explanatory string 4308 const char* what() const noexcept override 4309 { 4310 return m.what(); 4311 } 4312 4313 /// the id of the exception 4314 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) 4315 4316 protected: 4317 JSON_HEDLEY_NON_NULL(3) 4318 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) 4319 4320 static std::string name(const std::string& ename, int id_) 4321 { 4322 return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); 4323 } 4324 4325 static std::string diagnostics(std::nullptr_t /*leaf_element*/) 4326 { 4327 return ""; 4328 } 4329 4330 template<typename BasicJsonType> 4331 static std::string diagnostics(const BasicJsonType* leaf_element) 4332 { 4333 #if JSON_DIAGNOSTICS 4334 std::vector<std::string> tokens; 4335 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) 4336 { 4337 switch (current->m_parent->type()) 4338 { 4339 case value_t::array: 4340 { 4341 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) 4342 { 4343 if (¤t->m_parent->m_value.array->operator[](i) == current) 4344 { 4345 tokens.emplace_back(std::to_string(i)); 4346 break; 4347 } 4348 } 4349 break; 4350 } 4351 4352 case value_t::object: 4353 { 4354 for (const auto& element : *current->m_parent->m_value.object) 4355 { 4356 if (&element.second == current) 4357 { 4358 tokens.emplace_back(element.first.c_str()); 4359 break; 4360 } 4361 } 4362 break; 4363 } 4364 4365 case value_t::null: // LCOV_EXCL_LINE 4366 case value_t::string: // LCOV_EXCL_LINE 4367 case value_t::boolean: // LCOV_EXCL_LINE 4368 case value_t::number_integer: // LCOV_EXCL_LINE 4369 case value_t::number_unsigned: // LCOV_EXCL_LINE 4370 case value_t::number_float: // LCOV_EXCL_LINE 4371 case value_t::binary: // LCOV_EXCL_LINE 4372 case value_t::discarded: // LCOV_EXCL_LINE 4373 default: // LCOV_EXCL_LINE 4374 break; // LCOV_EXCL_LINE 4375 } 4376 } 4377 4378 if (tokens.empty()) 4379 { 4380 return ""; 4381 } 4382 4383 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, 4384 [](const std::string & a, const std::string & b) 4385 { 4386 return concat(a, '/', detail::escape(b)); 4387 }); 4388 return concat('(', str, ") "); 4389 #else 4390 static_cast<void>(leaf_element); 4391 return ""; 4392 #endif 4393 } 4394 4395 private: 4396 /// an exception object as storage for error messages 4397 std::runtime_error m; 4398 }; 4399 4400 /// @brief exception indicating a parse error 4401 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/ 4402 class parse_error : public exception 4403 { 4404 public: 4405 /*! 4406 @brief create a parse error exception 4407 @param[in] id_ the id of the exception 4408 @param[in] pos the position where the error occurred (or with 4409 chars_read_total=0 if the position cannot be 4410 determined) 4411 @param[in] what_arg the explanatory string 4412 @return parse_error object 4413 */ 4414 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4415 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) 4416 { 4417 const std::string w = concat(exception::name("parse_error", id_), "parse error", 4418 position_string(pos), ": ", exception::diagnostics(context), what_arg); 4419 return {id_, pos.chars_read_total, w.c_str()}; 4420 } 4421 4422 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4423 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) 4424 { 4425 const std::string w = concat(exception::name("parse_error", id_), "parse error", 4426 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), 4427 ": ", exception::diagnostics(context), what_arg); 4428 return {id_, byte_, w.c_str()}; 4429 } 4430 4431 /*! 4432 @brief byte index of the parse error 4433 4434 The byte index of the last read character in the input file. 4435 4436 @note For an input with n bytes, 1 is the index of the first character and 4437 n+1 is the index of the terminating null byte or the end of file. 4438 This also holds true when reading a byte vector (CBOR or MessagePack). 4439 */ 4440 const std::size_t byte; 4441 4442 private: 4443 parse_error(int id_, std::size_t byte_, const char* what_arg) 4444 : exception(id_, what_arg), byte(byte_) {} 4445 4446 static std::string position_string(const position_t& pos) 4447 { 4448 return concat(" at line ", std::to_string(pos.lines_read + 1), 4449 ", column ", std::to_string(pos.chars_read_current_line)); 4450 } 4451 }; 4452 4453 /// @brief exception indicating errors with iterators 4454 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ 4455 class invalid_iterator : public exception 4456 { 4457 public: 4458 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4459 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) 4460 { 4461 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); 4462 return {id_, w.c_str()}; 4463 } 4464 4465 private: 4466 JSON_HEDLEY_NON_NULL(3) 4467 invalid_iterator(int id_, const char* what_arg) 4468 : exception(id_, what_arg) {} 4469 }; 4470 4471 /// @brief exception indicating executing a member function with a wrong type 4472 /// @sa https://json.nlohmann.me/api/basic_json/type_error/ 4473 class type_error : public exception 4474 { 4475 public: 4476 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4477 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) 4478 { 4479 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); 4480 return {id_, w.c_str()}; 4481 } 4482 4483 private: 4484 JSON_HEDLEY_NON_NULL(3) 4485 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 4486 }; 4487 4488 /// @brief exception indicating access out of the defined range 4489 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ 4490 class out_of_range : public exception 4491 { 4492 public: 4493 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4494 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) 4495 { 4496 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); 4497 return {id_, w.c_str()}; 4498 } 4499 4500 private: 4501 JSON_HEDLEY_NON_NULL(3) 4502 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} 4503 }; 4504 4505 /// @brief exception indicating other library errors 4506 /// @sa https://json.nlohmann.me/api/basic_json/other_error/ 4507 class other_error : public exception 4508 { 4509 public: 4510 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4511 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) 4512 { 4513 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); 4514 return {id_, w.c_str()}; 4515 } 4516 4517 private: 4518 JSON_HEDLEY_NON_NULL(3) 4519 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 4520 }; 4521 4522 } // namespace detail 4523 NLOHMANN_JSON_NAMESPACE_END 4524 4525 // #include <nlohmann/detail/macro_scope.hpp> 4526 4527 // #include <nlohmann/detail/meta/cpp_future.hpp> 4528 4529 // #include <nlohmann/detail/meta/identity_tag.hpp> 4530 // __ _____ _____ _____ 4531 // __| | __| | | | JSON for Modern C++ 4532 // | | |__ | | | | | | version 3.11.2 4533 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4534 // 4535 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 4536 // SPDX-License-Identifier: MIT 4537 4538 4539 4540 // #include <nlohmann/detail/abi_macros.hpp> 4541 4542 4543 NLOHMANN_JSON_NAMESPACE_BEGIN 4544 namespace detail 4545 { 4546 4547 // dispatching helper struct 4548 template <class T> struct identity_tag {}; 4549 4550 } // namespace detail 4551 NLOHMANN_JSON_NAMESPACE_END 4552 4553 // #include <nlohmann/detail/meta/std_fs.hpp> 4554 // __ _____ _____ _____ 4555 // __| | __| | | | JSON for Modern C++ 4556 // | | |__ | | | | | | version 3.11.2 4557 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4558 // 4559 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 4560 // SPDX-License-Identifier: MIT 4561 4562 4563 4564 // #include <nlohmann/detail/macro_scope.hpp> 4565 4566 4567 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM 4568 #include <experimental/filesystem> 4569 NLOHMANN_JSON_NAMESPACE_BEGIN 4570 namespace detail 4571 { 4572 namespace std_fs = std::experimental::filesystem; 4573 } // namespace detail 4574 NLOHMANN_JSON_NAMESPACE_END 4575 #elif JSON_HAS_FILESYSTEM 4576 #include <filesystem> 4577 NLOHMANN_JSON_NAMESPACE_BEGIN 4578 namespace detail 4579 { 4580 namespace std_fs = std::filesystem; 4581 } // namespace detail 4582 NLOHMANN_JSON_NAMESPACE_END 4583 #endif 4584 4585 // #include <nlohmann/detail/meta/type_traits.hpp> 4586 4587 // #include <nlohmann/detail/string_concat.hpp> 4588 4589 // #include <nlohmann/detail/value_t.hpp> 4590 4591 4592 NLOHMANN_JSON_NAMESPACE_BEGIN 4593 namespace detail 4594 { 4595 4596 template<typename BasicJsonType> 4597 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) 4598 { 4599 if (JSON_HEDLEY_UNLIKELY(!j.is_null())) 4600 { 4601 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); 4602 } 4603 n = nullptr; 4604 } 4605 4606 // overloads for basic_json template parameters 4607 template < typename BasicJsonType, typename ArithmeticType, 4608 enable_if_t < std::is_arithmetic<ArithmeticType>::value&& 4609 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, 4610 int > = 0 > 4611 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) 4612 { 4613 switch (static_cast<value_t>(j)) 4614 { 4615 case value_t::number_unsigned: 4616 { 4617 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); 4618 break; 4619 } 4620 case value_t::number_integer: 4621 { 4622 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); 4623 break; 4624 } 4625 case value_t::number_float: 4626 { 4627 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); 4628 break; 4629 } 4630 4631 case value_t::null: 4632 case value_t::object: 4633 case value_t::array: 4634 case value_t::string: 4635 case value_t::boolean: 4636 case value_t::binary: 4637 case value_t::discarded: 4638 default: 4639 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); 4640 } 4641 } 4642 4643 template<typename BasicJsonType> 4644 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) 4645 { 4646 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) 4647 { 4648 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); 4649 } 4650 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); 4651 } 4652 4653 template<typename BasicJsonType> 4654 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) 4655 { 4656 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 4657 { 4658 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 4659 } 4660 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 4661 } 4662 4663 template < 4664 typename BasicJsonType, typename StringType, 4665 enable_if_t < 4666 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value 4667 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value 4668 && !std::is_same<typename BasicJsonType::string_t, StringType>::value 4669 && !is_json_ref<StringType>::value, int > = 0 > 4670 inline void from_json(const BasicJsonType& j, StringType& s) 4671 { 4672 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 4673 { 4674 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 4675 } 4676 4677 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 4678 } 4679 4680 template<typename BasicJsonType> 4681 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) 4682 { 4683 get_arithmetic_value(j, val); 4684 } 4685 4686 template<typename BasicJsonType> 4687 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) 4688 { 4689 get_arithmetic_value(j, val); 4690 } 4691 4692 template<typename BasicJsonType> 4693 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) 4694 { 4695 get_arithmetic_value(j, val); 4696 } 4697 4698 #if !JSON_DISABLE_ENUM_SERIALIZATION 4699 template<typename BasicJsonType, typename EnumType, 4700 enable_if_t<std::is_enum<EnumType>::value, int> = 0> 4701 inline void from_json(const BasicJsonType& j, EnumType& e) 4702 { 4703 typename std::underlying_type<EnumType>::type val; 4704 get_arithmetic_value(j, val); 4705 e = static_cast<EnumType>(val); 4706 } 4707 #endif // JSON_DISABLE_ENUM_SERIALIZATION 4708 4709 // forward_list doesn't have an insert method 4710 template<typename BasicJsonType, typename T, typename Allocator, 4711 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> 4712 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) 4713 { 4714 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4715 { 4716 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4717 } 4718 l.clear(); 4719 std::transform(j.rbegin(), j.rend(), 4720 std::front_inserter(l), [](const BasicJsonType & i) 4721 { 4722 return i.template get<T>(); 4723 }); 4724 } 4725 4726 // valarray doesn't have an insert method 4727 template<typename BasicJsonType, typename T, 4728 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> 4729 inline void from_json(const BasicJsonType& j, std::valarray<T>& l) 4730 { 4731 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4732 { 4733 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4734 } 4735 l.resize(j.size()); 4736 std::transform(j.begin(), j.end(), std::begin(l), 4737 [](const BasicJsonType & elem) 4738 { 4739 return elem.template get<T>(); 4740 }); 4741 } 4742 4743 template<typename BasicJsonType, typename T, std::size_t N> 4744 auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4745 -> decltype(j.template get<T>(), void()) 4746 { 4747 for (std::size_t i = 0; i < N; ++i) 4748 { 4749 arr[i] = j.at(i).template get<T>(); 4750 } 4751 } 4752 4753 template<typename BasicJsonType> 4754 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) 4755 { 4756 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); 4757 } 4758 4759 template<typename BasicJsonType, typename T, std::size_t N> 4760 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, 4761 priority_tag<2> /*unused*/) 4762 -> decltype(j.template get<T>(), void()) 4763 { 4764 for (std::size_t i = 0; i < N; ++i) 4765 { 4766 arr[i] = j.at(i).template get<T>(); 4767 } 4768 } 4769 4770 template<typename BasicJsonType, typename ConstructibleArrayType, 4771 enable_if_t< 4772 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, 4773 int> = 0> 4774 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) 4775 -> decltype( 4776 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), 4777 j.template get<typename ConstructibleArrayType::value_type>(), 4778 void()) 4779 { 4780 using std::end; 4781 4782 ConstructibleArrayType ret; 4783 ret.reserve(j.size()); 4784 std::transform(j.begin(), j.end(), 4785 std::inserter(ret, end(ret)), [](const BasicJsonType & i) 4786 { 4787 // get<BasicJsonType>() returns *this, this won't call a from_json 4788 // method when value_type is BasicJsonType 4789 return i.template get<typename ConstructibleArrayType::value_type>(); 4790 }); 4791 arr = std::move(ret); 4792 } 4793 4794 template<typename BasicJsonType, typename ConstructibleArrayType, 4795 enable_if_t< 4796 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, 4797 int> = 0> 4798 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, 4799 priority_tag<0> /*unused*/) 4800 { 4801 using std::end; 4802 4803 ConstructibleArrayType ret; 4804 std::transform( 4805 j.begin(), j.end(), std::inserter(ret, end(ret)), 4806 [](const BasicJsonType & i) 4807 { 4808 // get<BasicJsonType>() returns *this, this won't call a from_json 4809 // method when value_type is BasicJsonType 4810 return i.template get<typename ConstructibleArrayType::value_type>(); 4811 }); 4812 arr = std::move(ret); 4813 } 4814 4815 template < typename BasicJsonType, typename ConstructibleArrayType, 4816 enable_if_t < 4817 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&& 4818 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&& 4819 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&& 4820 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&& 4821 !is_basic_json<ConstructibleArrayType>::value, 4822 int > = 0 > 4823 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) 4824 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), 4825 j.template get<typename ConstructibleArrayType::value_type>(), 4826 void()) 4827 { 4828 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4829 { 4830 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4831 } 4832 4833 from_json_array_impl(j, arr, priority_tag<3> {}); 4834 } 4835 4836 template < typename BasicJsonType, typename T, std::size_t... Idx > 4837 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j, 4838 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) 4839 { 4840 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } }; 4841 } 4842 4843 template < typename BasicJsonType, typename T, std::size_t N > 4844 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag) 4845 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) 4846 { 4847 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4848 { 4849 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4850 } 4851 4852 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}); 4853 } 4854 4855 template<typename BasicJsonType> 4856 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) 4857 { 4858 if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) 4859 { 4860 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); 4861 } 4862 4863 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); 4864 } 4865 4866 template<typename BasicJsonType, typename ConstructibleObjectType, 4867 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0> 4868 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) 4869 { 4870 if (JSON_HEDLEY_UNLIKELY(!j.is_object())) 4871 { 4872 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); 4873 } 4874 4875 ConstructibleObjectType ret; 4876 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); 4877 using value_type = typename ConstructibleObjectType::value_type; 4878 std::transform( 4879 inner_object->begin(), inner_object->end(), 4880 std::inserter(ret, ret.begin()), 4881 [](typename BasicJsonType::object_t::value_type const & p) 4882 { 4883 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); 4884 }); 4885 obj = std::move(ret); 4886 } 4887 4888 // overload for arithmetic types, not chosen for basic_json template arguments 4889 // (BooleanType, etc..); note: Is it really necessary to provide explicit 4890 // overloads for boolean_t etc. in case of a custom BooleanType which is not 4891 // an arithmetic type? 4892 template < typename BasicJsonType, typename ArithmeticType, 4893 enable_if_t < 4894 std::is_arithmetic<ArithmeticType>::value&& 4895 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&& 4896 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&& 4897 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&& 4898 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, 4899 int > = 0 > 4900 inline void from_json(const BasicJsonType& j, ArithmeticType& val) 4901 { 4902 switch (static_cast<value_t>(j)) 4903 { 4904 case value_t::number_unsigned: 4905 { 4906 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); 4907 break; 4908 } 4909 case value_t::number_integer: 4910 { 4911 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); 4912 break; 4913 } 4914 case value_t::number_float: 4915 { 4916 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); 4917 break; 4918 } 4919 case value_t::boolean: 4920 { 4921 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); 4922 break; 4923 } 4924 4925 case value_t::null: 4926 case value_t::object: 4927 case value_t::array: 4928 case value_t::string: 4929 case value_t::binary: 4930 case value_t::discarded: 4931 default: 4932 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); 4933 } 4934 } 4935 4936 template<typename BasicJsonType, typename... Args, std::size_t... Idx> 4937 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) 4938 { 4939 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); 4940 } 4941 4942 template < typename BasicJsonType, class A1, class A2 > 4943 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) 4944 { 4945 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(), 4946 std::forward<BasicJsonType>(j).at(1).template get<A2>()}; 4947 } 4948 4949 template<typename BasicJsonType, typename A1, typename A2> 4950 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) 4951 { 4952 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {}); 4953 } 4954 4955 template<typename BasicJsonType, typename... Args> 4956 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) 4957 { 4958 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); 4959 } 4960 4961 template<typename BasicJsonType, typename... Args> 4962 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) 4963 { 4964 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); 4965 } 4966 4967 template<typename BasicJsonType, typename TupleRelated> 4968 auto from_json(BasicJsonType&& j, TupleRelated&& t) 4969 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) 4970 { 4971 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4972 { 4973 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4974 } 4975 4976 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}); 4977 } 4978 4979 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, 4980 typename = enable_if_t < !std::is_constructible < 4981 typename BasicJsonType::string_t, Key >::value >> 4982 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) 4983 { 4984 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4985 { 4986 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4987 } 4988 m.clear(); 4989 for (const auto& p : j) 4990 { 4991 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) 4992 { 4993 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); 4994 } 4995 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); 4996 } 4997 } 4998 4999 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, 5000 typename = enable_if_t < !std::is_constructible < 5001 typename BasicJsonType::string_t, Key >::value >> 5002 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) 5003 { 5004 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 5005 { 5006 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 5007 } 5008 m.clear(); 5009 for (const auto& p : j) 5010 { 5011 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) 5012 { 5013 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); 5014 } 5015 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); 5016 } 5017 } 5018 5019 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 5020 template<typename BasicJsonType> 5021 inline void from_json(const BasicJsonType& j, std_fs::path& p) 5022 { 5023 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 5024 { 5025 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 5026 } 5027 p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 5028 } 5029 #endif 5030 5031 struct from_json_fn 5032 { 5033 template<typename BasicJsonType, typename T> 5034 auto operator()(const BasicJsonType& j, T&& val) const 5035 noexcept(noexcept(from_json(j, std::forward<T>(val)))) 5036 -> decltype(from_json(j, std::forward<T>(val))) 5037 { 5038 return from_json(j, std::forward<T>(val)); 5039 } 5040 }; 5041 5042 } // namespace detail 5043 5044 #ifndef JSON_HAS_CPP_17 5045 /// namespace to hold default `from_json` function 5046 /// to see why this is required: 5047 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 5048 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 5049 { 5050 #endif 5051 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) 5052 detail::static_const<detail::from_json_fn>::value; 5053 #ifndef JSON_HAS_CPP_17 5054 } // namespace 5055 #endif 5056 5057 NLOHMANN_JSON_NAMESPACE_END 5058 5059 // #include <nlohmann/detail/conversions/to_json.hpp> 5060 // __ _____ _____ _____ 5061 // __| | __| | | | JSON for Modern C++ 5062 // | | |__ | | | | | | version 3.11.2 5063 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5064 // 5065 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 5066 // SPDX-License-Identifier: MIT 5067 5068 5069 5070 #include <algorithm> // copy 5071 #include <iterator> // begin, end 5072 #include <string> // string 5073 #include <tuple> // tuple, get 5074 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type 5075 #include <utility> // move, forward, declval, pair 5076 #include <valarray> // valarray 5077 #include <vector> // vector 5078 5079 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> 5080 // __ _____ _____ _____ 5081 // __| | __| | | | JSON for Modern C++ 5082 // | | |__ | | | | | | version 3.11.2 5083 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5084 // 5085 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 5086 // SPDX-License-Identifier: MIT 5087 5088 5089 5090 #include <cstddef> // size_t 5091 #include <iterator> // input_iterator_tag 5092 #include <string> // string, to_string 5093 #include <tuple> // tuple_size, get, tuple_element 5094 #include <utility> // move 5095 5096 #if JSON_HAS_RANGES 5097 #include <ranges> // enable_borrowed_range 5098 #endif 5099 5100 // #include <nlohmann/detail/abi_macros.hpp> 5101 5102 // #include <nlohmann/detail/meta/type_traits.hpp> 5103 5104 // #include <nlohmann/detail/value_t.hpp> 5105 5106 5107 NLOHMANN_JSON_NAMESPACE_BEGIN 5108 namespace detail 5109 { 5110 5111 template<typename string_type> 5112 void int_to_string( string_type& target, std::size_t value ) 5113 { 5114 // For ADL 5115 using std::to_string; 5116 target = to_string(value); 5117 } 5118 template<typename IteratorType> class iteration_proxy_value 5119 { 5120 public: 5121 using difference_type = std::ptrdiff_t; 5122 using value_type = iteration_proxy_value; 5123 using pointer = value_type *; 5124 using reference = value_type &; 5125 using iterator_category = std::input_iterator_tag; 5126 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type; 5127 5128 private: 5129 /// the iterator 5130 IteratorType anchor{}; 5131 /// an index for arrays (used to create key names) 5132 std::size_t array_index = 0; 5133 /// last stringified array index 5134 mutable std::size_t array_index_last = 0; 5135 /// a string representation of the array index 5136 mutable string_type array_index_str = "0"; 5137 /// an empty string (to return a reference for primitive values) 5138 string_type empty_str{}; 5139 5140 public: 5141 explicit iteration_proxy_value() = default; 5142 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) 5143 noexcept(std::is_nothrow_move_constructible<IteratorType>::value 5144 && std::is_nothrow_default_constructible<string_type>::value) 5145 : anchor(std::move(it)) 5146 , array_index(array_index_) 5147 {} 5148 5149 iteration_proxy_value(iteration_proxy_value const&) = default; 5150 iteration_proxy_value& operator=(iteration_proxy_value const&) = default; 5151 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions 5152 iteration_proxy_value(iteration_proxy_value&&) 5153 noexcept(std::is_nothrow_move_constructible<IteratorType>::value 5154 && std::is_nothrow_move_constructible<string_type>::value) = default; 5155 iteration_proxy_value& operator=(iteration_proxy_value&&) 5156 noexcept(std::is_nothrow_move_assignable<IteratorType>::value 5157 && std::is_nothrow_move_assignable<string_type>::value) = default; 5158 ~iteration_proxy_value() = default; 5159 5160 /// dereference operator (needed for range-based for) 5161 const iteration_proxy_value& operator*() const 5162 { 5163 return *this; 5164 } 5165 5166 /// increment operator (needed for range-based for) 5167 iteration_proxy_value& operator++() 5168 { 5169 ++anchor; 5170 ++array_index; 5171 5172 return *this; 5173 } 5174 5175 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) 5176 { 5177 auto tmp = iteration_proxy_value(anchor, array_index); 5178 ++anchor; 5179 ++array_index; 5180 return tmp; 5181 } 5182 5183 /// equality operator (needed for InputIterator) 5184 bool operator==(const iteration_proxy_value& o) const 5185 { 5186 return anchor == o.anchor; 5187 } 5188 5189 /// inequality operator (needed for range-based for) 5190 bool operator!=(const iteration_proxy_value& o) const 5191 { 5192 return anchor != o.anchor; 5193 } 5194 5195 /// return key of the iterator 5196 const string_type& key() const 5197 { 5198 JSON_ASSERT(anchor.m_object != nullptr); 5199 5200 switch (anchor.m_object->type()) 5201 { 5202 // use integer array index as key 5203 case value_t::array: 5204 { 5205 if (array_index != array_index_last) 5206 { 5207 int_to_string( array_index_str, array_index ); 5208 array_index_last = array_index; 5209 } 5210 return array_index_str; 5211 } 5212 5213 // use key from the object 5214 case value_t::object: 5215 return anchor.key(); 5216 5217 // use an empty key for all primitive types 5218 case value_t::null: 5219 case value_t::string: 5220 case value_t::boolean: 5221 case value_t::number_integer: 5222 case value_t::number_unsigned: 5223 case value_t::number_float: 5224 case value_t::binary: 5225 case value_t::discarded: 5226 default: 5227 return empty_str; 5228 } 5229 } 5230 5231 /// return value of the iterator 5232 typename IteratorType::reference value() const 5233 { 5234 return anchor.value(); 5235 } 5236 }; 5237 5238 /// proxy class for the items() function 5239 template<typename IteratorType> class iteration_proxy 5240 { 5241 private: 5242 /// the container to iterate 5243 typename IteratorType::pointer container = nullptr; 5244 5245 public: 5246 explicit iteration_proxy() = default; 5247 5248 /// construct iteration proxy from a container 5249 explicit iteration_proxy(typename IteratorType::reference cont) noexcept 5250 : container(&cont) {} 5251 5252 iteration_proxy(iteration_proxy const&) = default; 5253 iteration_proxy& operator=(iteration_proxy const&) = default; 5254 iteration_proxy(iteration_proxy&&) noexcept = default; 5255 iteration_proxy& operator=(iteration_proxy&&) noexcept = default; 5256 ~iteration_proxy() = default; 5257 5258 /// return iterator begin (needed for range-based for) 5259 iteration_proxy_value<IteratorType> begin() const noexcept 5260 { 5261 return iteration_proxy_value<IteratorType>(container->begin()); 5262 } 5263 5264 /// return iterator end (needed for range-based for) 5265 iteration_proxy_value<IteratorType> end() const noexcept 5266 { 5267 return iteration_proxy_value<IteratorType>(container->end()); 5268 } 5269 }; 5270 5271 // Structured Bindings Support 5272 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5273 // And see https://github.com/nlohmann/json/pull/1391 5274 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0> 5275 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) 5276 { 5277 return i.key(); 5278 } 5279 // Structured Bindings Support 5280 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5281 // And see https://github.com/nlohmann/json/pull/1391 5282 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0> 5283 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) 5284 { 5285 return i.value(); 5286 } 5287 5288 } // namespace detail 5289 NLOHMANN_JSON_NAMESPACE_END 5290 5291 // The Addition to the STD Namespace is required to add 5292 // Structured Bindings Support to the iteration_proxy_value class 5293 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5294 // And see https://github.com/nlohmann/json/pull/1391 5295 namespace std 5296 { 5297 5298 #if defined(__clang__) 5299 // Fix: https://github.com/nlohmann/json/issues/1401 5300 #pragma clang diagnostic push 5301 #pragma clang diagnostic ignored "-Wmismatched-tags" 5302 #endif 5303 template<typename IteratorType> 5304 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp) 5305 : public std::integral_constant<std::size_t, 2> {}; 5306 5307 template<std::size_t N, typename IteratorType> 5308 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp) 5309 { 5310 public: 5311 using type = decltype( 5312 get<N>(std::declval < 5313 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ())); 5314 }; 5315 #if defined(__clang__) 5316 #pragma clang diagnostic pop 5317 #endif 5318 5319 } // namespace std 5320 5321 #if JSON_HAS_RANGES 5322 template <typename IteratorType> 5323 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true; 5324 #endif 5325 5326 // #include <nlohmann/detail/macro_scope.hpp> 5327 5328 // #include <nlohmann/detail/meta/cpp_future.hpp> 5329 5330 // #include <nlohmann/detail/meta/std_fs.hpp> 5331 5332 // #include <nlohmann/detail/meta/type_traits.hpp> 5333 5334 // #include <nlohmann/detail/value_t.hpp> 5335 5336 5337 NLOHMANN_JSON_NAMESPACE_BEGIN 5338 namespace detail 5339 { 5340 5341 ////////////////// 5342 // constructors // 5343 ////////////////// 5344 5345 /* 5346 * Note all external_constructor<>::construct functions need to call 5347 * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an 5348 * allocated value (e.g., a string). See bug issue 5349 * https://github.com/nlohmann/json/issues/2865 for more information. 5350 */ 5351 5352 template<value_t> struct external_constructor; 5353 5354 template<> 5355 struct external_constructor<value_t::boolean> 5356 { 5357 template<typename BasicJsonType> 5358 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept 5359 { 5360 j.m_value.destroy(j.m_type); 5361 j.m_type = value_t::boolean; 5362 j.m_value = b; 5363 j.assert_invariant(); 5364 } 5365 }; 5366 5367 template<> 5368 struct external_constructor<value_t::string> 5369 { 5370 template<typename BasicJsonType> 5371 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) 5372 { 5373 j.m_value.destroy(j.m_type); 5374 j.m_type = value_t::string; 5375 j.m_value = s; 5376 j.assert_invariant(); 5377 } 5378 5379 template<typename BasicJsonType> 5380 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) 5381 { 5382 j.m_value.destroy(j.m_type); 5383 j.m_type = value_t::string; 5384 j.m_value = std::move(s); 5385 j.assert_invariant(); 5386 } 5387 5388 template < typename BasicJsonType, typename CompatibleStringType, 5389 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, 5390 int > = 0 > 5391 static void construct(BasicJsonType& j, const CompatibleStringType& str) 5392 { 5393 j.m_value.destroy(j.m_type); 5394 j.m_type = value_t::string; 5395 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str); 5396 j.assert_invariant(); 5397 } 5398 }; 5399 5400 template<> 5401 struct external_constructor<value_t::binary> 5402 { 5403 template<typename BasicJsonType> 5404 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) 5405 { 5406 j.m_value.destroy(j.m_type); 5407 j.m_type = value_t::binary; 5408 j.m_value = typename BasicJsonType::binary_t(b); 5409 j.assert_invariant(); 5410 } 5411 5412 template<typename BasicJsonType> 5413 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) 5414 { 5415 j.m_value.destroy(j.m_type); 5416 j.m_type = value_t::binary; 5417 j.m_value = typename BasicJsonType::binary_t(std::move(b)); 5418 j.assert_invariant(); 5419 } 5420 }; 5421 5422 template<> 5423 struct external_constructor<value_t::number_float> 5424 { 5425 template<typename BasicJsonType> 5426 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept 5427 { 5428 j.m_value.destroy(j.m_type); 5429 j.m_type = value_t::number_float; 5430 j.m_value = val; 5431 j.assert_invariant(); 5432 } 5433 }; 5434 5435 template<> 5436 struct external_constructor<value_t::number_unsigned> 5437 { 5438 template<typename BasicJsonType> 5439 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept 5440 { 5441 j.m_value.destroy(j.m_type); 5442 j.m_type = value_t::number_unsigned; 5443 j.m_value = val; 5444 j.assert_invariant(); 5445 } 5446 }; 5447 5448 template<> 5449 struct external_constructor<value_t::number_integer> 5450 { 5451 template<typename BasicJsonType> 5452 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept 5453 { 5454 j.m_value.destroy(j.m_type); 5455 j.m_type = value_t::number_integer; 5456 j.m_value = val; 5457 j.assert_invariant(); 5458 } 5459 }; 5460 5461 template<> 5462 struct external_constructor<value_t::array> 5463 { 5464 template<typename BasicJsonType> 5465 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) 5466 { 5467 j.m_value.destroy(j.m_type); 5468 j.m_type = value_t::array; 5469 j.m_value = arr; 5470 j.set_parents(); 5471 j.assert_invariant(); 5472 } 5473 5474 template<typename BasicJsonType> 5475 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) 5476 { 5477 j.m_value.destroy(j.m_type); 5478 j.m_type = value_t::array; 5479 j.m_value = std::move(arr); 5480 j.set_parents(); 5481 j.assert_invariant(); 5482 } 5483 5484 template < typename BasicJsonType, typename CompatibleArrayType, 5485 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, 5486 int > = 0 > 5487 static void construct(BasicJsonType& j, const CompatibleArrayType& arr) 5488 { 5489 using std::begin; 5490 using std::end; 5491 5492 j.m_value.destroy(j.m_type); 5493 j.m_type = value_t::array; 5494 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); 5495 j.set_parents(); 5496 j.assert_invariant(); 5497 } 5498 5499 template<typename BasicJsonType> 5500 static void construct(BasicJsonType& j, const std::vector<bool>& arr) 5501 { 5502 j.m_value.destroy(j.m_type); 5503 j.m_type = value_t::array; 5504 j.m_value = value_t::array; 5505 j.m_value.array->reserve(arr.size()); 5506 for (const bool x : arr) 5507 { 5508 j.m_value.array->push_back(x); 5509 j.set_parent(j.m_value.array->back()); 5510 } 5511 j.assert_invariant(); 5512 } 5513 5514 template<typename BasicJsonType, typename T, 5515 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> 5516 static void construct(BasicJsonType& j, const std::valarray<T>& arr) 5517 { 5518 j.m_value.destroy(j.m_type); 5519 j.m_type = value_t::array; 5520 j.m_value = value_t::array; 5521 j.m_value.array->resize(arr.size()); 5522 if (arr.size() > 0) 5523 { 5524 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); 5525 } 5526 j.set_parents(); 5527 j.assert_invariant(); 5528 } 5529 }; 5530 5531 template<> 5532 struct external_constructor<value_t::object> 5533 { 5534 template<typename BasicJsonType> 5535 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) 5536 { 5537 j.m_value.destroy(j.m_type); 5538 j.m_type = value_t::object; 5539 j.m_value = obj; 5540 j.set_parents(); 5541 j.assert_invariant(); 5542 } 5543 5544 template<typename BasicJsonType> 5545 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) 5546 { 5547 j.m_value.destroy(j.m_type); 5548 j.m_type = value_t::object; 5549 j.m_value = std::move(obj); 5550 j.set_parents(); 5551 j.assert_invariant(); 5552 } 5553 5554 template < typename BasicJsonType, typename CompatibleObjectType, 5555 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 > 5556 static void construct(BasicJsonType& j, const CompatibleObjectType& obj) 5557 { 5558 using std::begin; 5559 using std::end; 5560 5561 j.m_value.destroy(j.m_type); 5562 j.m_type = value_t::object; 5563 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); 5564 j.set_parents(); 5565 j.assert_invariant(); 5566 } 5567 }; 5568 5569 ///////////// 5570 // to_json // 5571 ///////////// 5572 5573 template<typename BasicJsonType, typename T, 5574 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> 5575 inline void to_json(BasicJsonType& j, T b) noexcept 5576 { 5577 external_constructor<value_t::boolean>::construct(j, b); 5578 } 5579 5580 template < typename BasicJsonType, typename BoolRef, 5581 enable_if_t < 5582 ((std::is_same<std::vector<bool>::reference, BoolRef>::value 5583 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) 5584 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value 5585 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>, 5586 typename BasicJsonType::boolean_t >::value)) 5587 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 > 5588 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept 5589 { 5590 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b)); 5591 } 5592 5593 template<typename BasicJsonType, typename CompatibleString, 5594 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> 5595 inline void to_json(BasicJsonType& j, const CompatibleString& s) 5596 { 5597 external_constructor<value_t::string>::construct(j, s); 5598 } 5599 5600 template<typename BasicJsonType> 5601 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) 5602 { 5603 external_constructor<value_t::string>::construct(j, std::move(s)); 5604 } 5605 5606 template<typename BasicJsonType, typename FloatType, 5607 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> 5608 inline void to_json(BasicJsonType& j, FloatType val) noexcept 5609 { 5610 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); 5611 } 5612 5613 template<typename BasicJsonType, typename CompatibleNumberUnsignedType, 5614 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> 5615 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept 5616 { 5617 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); 5618 } 5619 5620 template<typename BasicJsonType, typename CompatibleNumberIntegerType, 5621 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> 5622 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept 5623 { 5624 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); 5625 } 5626 5627 #if !JSON_DISABLE_ENUM_SERIALIZATION 5628 template<typename BasicJsonType, typename EnumType, 5629 enable_if_t<std::is_enum<EnumType>::value, int> = 0> 5630 inline void to_json(BasicJsonType& j, EnumType e) noexcept 5631 { 5632 using underlying_type = typename std::underlying_type<EnumType>::type; 5633 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); 5634 } 5635 #endif // JSON_DISABLE_ENUM_SERIALIZATION 5636 5637 template<typename BasicJsonType> 5638 inline void to_json(BasicJsonType& j, const std::vector<bool>& e) 5639 { 5640 external_constructor<value_t::array>::construct(j, e); 5641 } 5642 5643 template < typename BasicJsonType, typename CompatibleArrayType, 5644 enable_if_t < is_compatible_array_type<BasicJsonType, 5645 CompatibleArrayType>::value&& 5646 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&& 5647 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&& 5648 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&& 5649 !is_basic_json<CompatibleArrayType>::value, 5650 int > = 0 > 5651 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) 5652 { 5653 external_constructor<value_t::array>::construct(j, arr); 5654 } 5655 5656 template<typename BasicJsonType> 5657 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) 5658 { 5659 external_constructor<value_t::binary>::construct(j, bin); 5660 } 5661 5662 template<typename BasicJsonType, typename T, 5663 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> 5664 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) 5665 { 5666 external_constructor<value_t::array>::construct(j, std::move(arr)); 5667 } 5668 5669 template<typename BasicJsonType> 5670 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) 5671 { 5672 external_constructor<value_t::array>::construct(j, std::move(arr)); 5673 } 5674 5675 template < typename BasicJsonType, typename CompatibleObjectType, 5676 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 > 5677 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) 5678 { 5679 external_constructor<value_t::object>::construct(j, obj); 5680 } 5681 5682 template<typename BasicJsonType> 5683 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) 5684 { 5685 external_constructor<value_t::object>::construct(j, std::move(obj)); 5686 } 5687 5688 template < 5689 typename BasicJsonType, typename T, std::size_t N, 5690 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t, 5691 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5692 int > = 0 > 5693 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5694 { 5695 external_constructor<value_t::array>::construct(j, arr); 5696 } 5697 5698 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 > 5699 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) 5700 { 5701 j = { p.first, p.second }; 5702 } 5703 5704 // for https://github.com/nlohmann/json/pull/1134 5705 template<typename BasicJsonType, typename T, 5706 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0> 5707 inline void to_json(BasicJsonType& j, const T& b) 5708 { 5709 j = { {b.key(), b.value()} }; 5710 } 5711 5712 template<typename BasicJsonType, typename Tuple, std::size_t... Idx> 5713 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) 5714 { 5715 j = { std::get<Idx>(t)... }; 5716 } 5717 5718 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> 5719 inline void to_json(BasicJsonType& j, const T& t) 5720 { 5721 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); 5722 } 5723 5724 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 5725 template<typename BasicJsonType> 5726 inline void to_json(BasicJsonType& j, const std_fs::path& p) 5727 { 5728 j = p.string(); 5729 } 5730 #endif 5731 5732 struct to_json_fn 5733 { 5734 template<typename BasicJsonType, typename T> 5735 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) 5736 -> decltype(to_json(j, std::forward<T>(val)), void()) 5737 { 5738 return to_json(j, std::forward<T>(val)); 5739 } 5740 }; 5741 } // namespace detail 5742 5743 #ifndef JSON_HAS_CPP_17 5744 /// namespace to hold default `to_json` function 5745 /// to see why this is required: 5746 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 5747 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 5748 { 5749 #endif 5750 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) 5751 detail::static_const<detail::to_json_fn>::value; 5752 #ifndef JSON_HAS_CPP_17 5753 } // namespace 5754 #endif 5755 5756 NLOHMANN_JSON_NAMESPACE_END 5757 5758 // #include <nlohmann/detail/meta/identity_tag.hpp> 5759 5760 5761 NLOHMANN_JSON_NAMESPACE_BEGIN 5762 5763 /// @sa https://json.nlohmann.me/api/adl_serializer/ 5764 template<typename ValueType, typename> 5765 struct adl_serializer 5766 { 5767 /// @brief convert a JSON value to any value type 5768 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 5769 template<typename BasicJsonType, typename TargetType = ValueType> 5770 static auto from_json(BasicJsonType && j, TargetType& val) noexcept( 5771 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) 5772 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()) 5773 { 5774 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val); 5775 } 5776 5777 /// @brief convert a JSON value to any value type 5778 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 5779 template<typename BasicJsonType, typename TargetType = ValueType> 5780 static auto from_json(BasicJsonType && j) noexcept( 5781 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))) 5782 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})) 5783 { 5784 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}); 5785 } 5786 5787 /// @brief convert any value type to a JSON value 5788 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ 5789 template<typename BasicJsonType, typename TargetType = ValueType> 5790 static auto to_json(BasicJsonType& j, TargetType && val) noexcept( 5791 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val)))) 5792 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void()) 5793 { 5794 ::nlohmann::to_json(j, std::forward<TargetType>(val)); 5795 } 5796 }; 5797 5798 NLOHMANN_JSON_NAMESPACE_END 5799 5800 // #include <nlohmann/byte_container_with_subtype.hpp> 5801 // __ _____ _____ _____ 5802 // __| | __| | | | JSON for Modern C++ 5803 // | | |__ | | | | | | version 3.11.2 5804 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5805 // 5806 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 5807 // SPDX-License-Identifier: MIT 5808 5809 5810 5811 #include <cstdint> // uint8_t, uint64_t 5812 #include <tuple> // tie 5813 #include <utility> // move 5814 5815 // #include <nlohmann/detail/abi_macros.hpp> 5816 5817 5818 NLOHMANN_JSON_NAMESPACE_BEGIN 5819 5820 /// @brief an internal type for a backed binary type 5821 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ 5822 template<typename BinaryType> 5823 class byte_container_with_subtype : public BinaryType 5824 { 5825 public: 5826 using container_type = BinaryType; 5827 using subtype_type = std::uint64_t; 5828 5829 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5830 byte_container_with_subtype() noexcept(noexcept(container_type())) 5831 : container_type() 5832 {} 5833 5834 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5835 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) 5836 : container_type(b) 5837 {} 5838 5839 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5840 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) 5841 : container_type(std::move(b)) 5842 {} 5843 5844 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5845 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) 5846 : container_type(b) 5847 , m_subtype(subtype_) 5848 , m_has_subtype(true) 5849 {} 5850 5851 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5852 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) 5853 : container_type(std::move(b)) 5854 , m_subtype(subtype_) 5855 , m_has_subtype(true) 5856 {} 5857 5858 bool operator==(const byte_container_with_subtype& rhs) const 5859 { 5860 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) == 5861 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype); 5862 } 5863 5864 bool operator!=(const byte_container_with_subtype& rhs) const 5865 { 5866 return !(rhs == *this); 5867 } 5868 5869 /// @brief sets the binary subtype 5870 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ 5871 void set_subtype(subtype_type subtype_) noexcept 5872 { 5873 m_subtype = subtype_; 5874 m_has_subtype = true; 5875 } 5876 5877 /// @brief return the binary subtype 5878 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ 5879 constexpr subtype_type subtype() const noexcept 5880 { 5881 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1); 5882 } 5883 5884 /// @brief return whether the value has a subtype 5885 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ 5886 constexpr bool has_subtype() const noexcept 5887 { 5888 return m_has_subtype; 5889 } 5890 5891 /// @brief clears the binary subtype 5892 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ 5893 void clear_subtype() noexcept 5894 { 5895 m_subtype = 0; 5896 m_has_subtype = false; 5897 } 5898 5899 private: 5900 subtype_type m_subtype = 0; 5901 bool m_has_subtype = false; 5902 }; 5903 5904 NLOHMANN_JSON_NAMESPACE_END 5905 5906 // #include <nlohmann/detail/conversions/from_json.hpp> 5907 5908 // #include <nlohmann/detail/conversions/to_json.hpp> 5909 5910 // #include <nlohmann/detail/exceptions.hpp> 5911 5912 // #include <nlohmann/detail/hash.hpp> 5913 // __ _____ _____ _____ 5914 // __| | __| | | | JSON for Modern C++ 5915 // | | |__ | | | | | | version 3.11.2 5916 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5917 // 5918 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 5919 // SPDX-License-Identifier: MIT 5920 5921 5922 5923 #include <cstdint> // uint8_t 5924 #include <cstddef> // size_t 5925 #include <functional> // hash 5926 5927 // #include <nlohmann/detail/abi_macros.hpp> 5928 5929 // #include <nlohmann/detail/value_t.hpp> 5930 5931 5932 NLOHMANN_JSON_NAMESPACE_BEGIN 5933 namespace detail 5934 { 5935 5936 // boost::hash_combine 5937 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept 5938 { 5939 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); 5940 return seed; 5941 } 5942 5943 /*! 5944 @brief hash a JSON value 5945 5946 The hash function tries to rely on std::hash where possible. Furthermore, the 5947 type of the JSON value is taken into account to have different hash values for 5948 null, 0, 0U, and false, etc. 5949 5950 @tparam BasicJsonType basic_json specialization 5951 @param j JSON value to hash 5952 @return hash value of j 5953 */ 5954 template<typename BasicJsonType> 5955 std::size_t hash(const BasicJsonType& j) 5956 { 5957 using string_t = typename BasicJsonType::string_t; 5958 using number_integer_t = typename BasicJsonType::number_integer_t; 5959 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 5960 using number_float_t = typename BasicJsonType::number_float_t; 5961 5962 const auto type = static_cast<std::size_t>(j.type()); 5963 switch (j.type()) 5964 { 5965 case BasicJsonType::value_t::null: 5966 case BasicJsonType::value_t::discarded: 5967 { 5968 return combine(type, 0); 5969 } 5970 5971 case BasicJsonType::value_t::object: 5972 { 5973 auto seed = combine(type, j.size()); 5974 for (const auto& element : j.items()) 5975 { 5976 const auto h = std::hash<string_t> {}(element.key()); 5977 seed = combine(seed, h); 5978 seed = combine(seed, hash(element.value())); 5979 } 5980 return seed; 5981 } 5982 5983 case BasicJsonType::value_t::array: 5984 { 5985 auto seed = combine(type, j.size()); 5986 for (const auto& element : j) 5987 { 5988 seed = combine(seed, hash(element)); 5989 } 5990 return seed; 5991 } 5992 5993 case BasicJsonType::value_t::string: 5994 { 5995 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>()); 5996 return combine(type, h); 5997 } 5998 5999 case BasicJsonType::value_t::boolean: 6000 { 6001 const auto h = std::hash<bool> {}(j.template get<bool>()); 6002 return combine(type, h); 6003 } 6004 6005 case BasicJsonType::value_t::number_integer: 6006 { 6007 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>()); 6008 return combine(type, h); 6009 } 6010 6011 case BasicJsonType::value_t::number_unsigned: 6012 { 6013 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>()); 6014 return combine(type, h); 6015 } 6016 6017 case BasicJsonType::value_t::number_float: 6018 { 6019 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>()); 6020 return combine(type, h); 6021 } 6022 6023 case BasicJsonType::value_t::binary: 6024 { 6025 auto seed = combine(type, j.get_binary().size()); 6026 const auto h = std::hash<bool> {}(j.get_binary().has_subtype()); 6027 seed = combine(seed, h); 6028 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype())); 6029 for (const auto byte : j.get_binary()) 6030 { 6031 seed = combine(seed, std::hash<std::uint8_t> {}(byte)); 6032 } 6033 return seed; 6034 } 6035 6036 default: // LCOV_EXCL_LINE 6037 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 6038 return 0; // LCOV_EXCL_LINE 6039 } 6040 } 6041 6042 } // namespace detail 6043 NLOHMANN_JSON_NAMESPACE_END 6044 6045 // #include <nlohmann/detail/input/binary_reader.hpp> 6046 // __ _____ _____ _____ 6047 // __| | __| | | | JSON for Modern C++ 6048 // | | |__ | | | | | | version 3.11.2 6049 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6050 // 6051 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 6052 // SPDX-License-Identifier: MIT 6053 6054 6055 6056 #include <algorithm> // generate_n 6057 #include <array> // array 6058 #include <cmath> // ldexp 6059 #include <cstddef> // size_t 6060 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 6061 #include <cstdio> // snprintf 6062 #include <cstring> // memcpy 6063 #include <iterator> // back_inserter 6064 #include <limits> // numeric_limits 6065 #include <string> // char_traits, string 6066 #include <utility> // make_pair, move 6067 #include <vector> // vector 6068 6069 // #include <nlohmann/detail/exceptions.hpp> 6070 6071 // #include <nlohmann/detail/input/input_adapters.hpp> 6072 // __ _____ _____ _____ 6073 // __| | __| | | | JSON for Modern C++ 6074 // | | |__ | | | | | | version 3.11.2 6075 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6076 // 6077 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 6078 // SPDX-License-Identifier: MIT 6079 6080 6081 6082 #include <array> // array 6083 #include <cstddef> // size_t 6084 #include <cstring> // strlen 6085 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next 6086 #include <memory> // shared_ptr, make_shared, addressof 6087 #include <numeric> // accumulate 6088 #include <string> // string, char_traits 6089 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer 6090 #include <utility> // pair, declval 6091 6092 #ifndef JSON_NO_IO 6093 #include <cstdio> // FILE * 6094 #include <istream> // istream 6095 #endif // JSON_NO_IO 6096 6097 // #include <nlohmann/detail/iterators/iterator_traits.hpp> 6098 6099 // #include <nlohmann/detail/macro_scope.hpp> 6100 6101 6102 NLOHMANN_JSON_NAMESPACE_BEGIN 6103 namespace detail 6104 { 6105 6106 /// the supported input formats 6107 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; 6108 6109 //////////////////// 6110 // input adapters // 6111 //////////////////// 6112 6113 #ifndef JSON_NO_IO 6114 /*! 6115 Input adapter for stdio file access. This adapter read only 1 byte and do not use any 6116 buffer. This adapter is a very low level adapter. 6117 */ 6118 class file_input_adapter 6119 { 6120 public: 6121 using char_type = char; 6122 6123 JSON_HEDLEY_NON_NULL(2) 6124 explicit file_input_adapter(std::FILE* f) noexcept 6125 : m_file(f) 6126 { 6127 JSON_ASSERT(m_file != nullptr); 6128 } 6129 6130 // make class move-only 6131 file_input_adapter(const file_input_adapter&) = delete; 6132 file_input_adapter(file_input_adapter&&) noexcept = default; 6133 file_input_adapter& operator=(const file_input_adapter&) = delete; 6134 file_input_adapter& operator=(file_input_adapter&&) = delete; 6135 ~file_input_adapter() = default; 6136 6137 std::char_traits<char>::int_type get_character() noexcept 6138 { 6139 return std::fgetc(m_file); 6140 } 6141 6142 private: 6143 /// the file pointer to read from 6144 std::FILE* m_file; 6145 }; 6146 6147 6148 /*! 6149 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at 6150 beginning of input. Does not support changing the underlying std::streambuf 6151 in mid-input. Maintains underlying std::istream and std::streambuf to support 6152 subsequent use of standard std::istream operations to process any input 6153 characters following those used in parsing the JSON input. Clears the 6154 std::istream flags; any input errors (e.g., EOF) will be detected by the first 6155 subsequent call for input from the std::istream. 6156 */ 6157 class input_stream_adapter 6158 { 6159 public: 6160 using char_type = char; 6161 6162 ~input_stream_adapter() 6163 { 6164 // clear stream flags; we use underlying streambuf I/O, do not 6165 // maintain ifstream flags, except eof 6166 if (is != nullptr) 6167 { 6168 is->clear(is->rdstate() & std::ios::eofbit); 6169 } 6170 } 6171 6172 explicit input_stream_adapter(std::istream& i) 6173 : is(&i), sb(i.rdbuf()) 6174 {} 6175 6176 // delete because of pointer members 6177 input_stream_adapter(const input_stream_adapter&) = delete; 6178 input_stream_adapter& operator=(input_stream_adapter&) = delete; 6179 input_stream_adapter& operator=(input_stream_adapter&&) = delete; 6180 6181 input_stream_adapter(input_stream_adapter&& rhs) noexcept 6182 : is(rhs.is), sb(rhs.sb) 6183 { 6184 rhs.is = nullptr; 6185 rhs.sb = nullptr; 6186 } 6187 6188 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to 6189 // ensure that std::char_traits<char>::eof() and the character 0xFF do not 6190 // end up as the same value, e.g. 0xFFFFFFFF. 6191 std::char_traits<char>::int_type get_character() 6192 { 6193 auto res = sb->sbumpc(); 6194 // set eof manually, as we don't use the istream interface. 6195 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) 6196 { 6197 is->clear(is->rdstate() | std::ios::eofbit); 6198 } 6199 return res; 6200 } 6201 6202 private: 6203 /// the associated input stream 6204 std::istream* is = nullptr; 6205 std::streambuf* sb = nullptr; 6206 }; 6207 #endif // JSON_NO_IO 6208 6209 // General-purpose iterator-based adapter. It might not be as fast as 6210 // theoretically possible for some containers, but it is extremely versatile. 6211 template<typename IteratorType> 6212 class iterator_input_adapter 6213 { 6214 public: 6215 using char_type = typename std::iterator_traits<IteratorType>::value_type; 6216 6217 iterator_input_adapter(IteratorType first, IteratorType last) 6218 : current(std::move(first)), end(std::move(last)) 6219 {} 6220 6221 typename std::char_traits<char_type>::int_type get_character() 6222 { 6223 if (JSON_HEDLEY_LIKELY(current != end)) 6224 { 6225 auto result = std::char_traits<char_type>::to_int_type(*current); 6226 std::advance(current, 1); 6227 return result; 6228 } 6229 6230 return std::char_traits<char_type>::eof(); 6231 } 6232 6233 private: 6234 IteratorType current; 6235 IteratorType end; 6236 6237 template<typename BaseInputAdapter, size_t T> 6238 friend struct wide_string_input_helper; 6239 6240 bool empty() const 6241 { 6242 return current == end; 6243 } 6244 }; 6245 6246 6247 template<typename BaseInputAdapter, size_t T> 6248 struct wide_string_input_helper; 6249 6250 template<typename BaseInputAdapter> 6251 struct wide_string_input_helper<BaseInputAdapter, 4> 6252 { 6253 // UTF-32 6254 static void fill_buffer(BaseInputAdapter& input, 6255 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, 6256 size_t& utf8_bytes_index, 6257 size_t& utf8_bytes_filled) 6258 { 6259 utf8_bytes_index = 0; 6260 6261 if (JSON_HEDLEY_UNLIKELY(input.empty())) 6262 { 6263 utf8_bytes[0] = std::char_traits<char>::eof(); 6264 utf8_bytes_filled = 1; 6265 } 6266 else 6267 { 6268 // get the current character 6269 const auto wc = input.get_character(); 6270 6271 // UTF-32 to UTF-8 encoding 6272 if (wc < 0x80) 6273 { 6274 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6275 utf8_bytes_filled = 1; 6276 } 6277 else if (wc <= 0x7FF) 6278 { 6279 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu)); 6280 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6281 utf8_bytes_filled = 2; 6282 } 6283 else if (wc <= 0xFFFF) 6284 { 6285 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu)); 6286 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6287 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6288 utf8_bytes_filled = 3; 6289 } 6290 else if (wc <= 0x10FFFF) 6291 { 6292 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u)); 6293 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu)); 6294 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6295 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6296 utf8_bytes_filled = 4; 6297 } 6298 else 6299 { 6300 // unknown character 6301 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6302 utf8_bytes_filled = 1; 6303 } 6304 } 6305 } 6306 }; 6307 6308 template<typename BaseInputAdapter> 6309 struct wide_string_input_helper<BaseInputAdapter, 2> 6310 { 6311 // UTF-16 6312 static void fill_buffer(BaseInputAdapter& input, 6313 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, 6314 size_t& utf8_bytes_index, 6315 size_t& utf8_bytes_filled) 6316 { 6317 utf8_bytes_index = 0; 6318 6319 if (JSON_HEDLEY_UNLIKELY(input.empty())) 6320 { 6321 utf8_bytes[0] = std::char_traits<char>::eof(); 6322 utf8_bytes_filled = 1; 6323 } 6324 else 6325 { 6326 // get the current character 6327 const auto wc = input.get_character(); 6328 6329 // UTF-16 to UTF-8 encoding 6330 if (wc < 0x80) 6331 { 6332 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6333 utf8_bytes_filled = 1; 6334 } 6335 else if (wc <= 0x7FF) 6336 { 6337 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u))); 6338 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6339 utf8_bytes_filled = 2; 6340 } 6341 else if (0xD800 > wc || wc >= 0xE000) 6342 { 6343 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u))); 6344 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6345 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6346 utf8_bytes_filled = 3; 6347 } 6348 else 6349 { 6350 if (JSON_HEDLEY_UNLIKELY(!input.empty())) 6351 { 6352 const auto wc2 = static_cast<unsigned int>(input.get_character()); 6353 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); 6354 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u)); 6355 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); 6356 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); 6357 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu)); 6358 utf8_bytes_filled = 4; 6359 } 6360 else 6361 { 6362 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6363 utf8_bytes_filled = 1; 6364 } 6365 } 6366 } 6367 } 6368 }; 6369 6370 // Wraps another input apdater to convert wide character types into individual bytes. 6371 template<typename BaseInputAdapter, typename WideCharType> 6372 class wide_string_input_adapter 6373 { 6374 public: 6375 using char_type = char; 6376 6377 wide_string_input_adapter(BaseInputAdapter base) 6378 : base_adapter(base) {} 6379 6380 typename std::char_traits<char>::int_type get_character() noexcept 6381 { 6382 // check if buffer needs to be filled 6383 if (utf8_bytes_index == utf8_bytes_filled) 6384 { 6385 fill_buffer<sizeof(WideCharType)>(); 6386 6387 JSON_ASSERT(utf8_bytes_filled > 0); 6388 JSON_ASSERT(utf8_bytes_index == 0); 6389 } 6390 6391 // use buffer 6392 JSON_ASSERT(utf8_bytes_filled > 0); 6393 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); 6394 return utf8_bytes[utf8_bytes_index++]; 6395 } 6396 6397 private: 6398 BaseInputAdapter base_adapter; 6399 6400 template<size_t T> 6401 void fill_buffer() 6402 { 6403 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); 6404 } 6405 6406 /// a buffer for UTF-8 bytes 6407 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; 6408 6409 /// index to the utf8_codes array for the next valid byte 6410 std::size_t utf8_bytes_index = 0; 6411 /// number of valid bytes in the utf8_codes array 6412 std::size_t utf8_bytes_filled = 0; 6413 }; 6414 6415 6416 template<typename IteratorType, typename Enable = void> 6417 struct iterator_input_adapter_factory 6418 { 6419 using iterator_type = IteratorType; 6420 using char_type = typename std::iterator_traits<iterator_type>::value_type; 6421 using adapter_type = iterator_input_adapter<iterator_type>; 6422 6423 static adapter_type create(IteratorType first, IteratorType last) 6424 { 6425 return adapter_type(std::move(first), std::move(last)); 6426 } 6427 }; 6428 6429 template<typename T> 6430 struct is_iterator_of_multibyte 6431 { 6432 using value_type = typename std::iterator_traits<T>::value_type; 6433 enum 6434 { 6435 value = sizeof(value_type) > 1 6436 }; 6437 }; 6438 6439 template<typename IteratorType> 6440 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> 6441 { 6442 using iterator_type = IteratorType; 6443 using char_type = typename std::iterator_traits<iterator_type>::value_type; 6444 using base_adapter_type = iterator_input_adapter<iterator_type>; 6445 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>; 6446 6447 static adapter_type create(IteratorType first, IteratorType last) 6448 { 6449 return adapter_type(base_adapter_type(std::move(first), std::move(last))); 6450 } 6451 }; 6452 6453 // General purpose iterator-based input 6454 template<typename IteratorType> 6455 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) 6456 { 6457 using factory_type = iterator_input_adapter_factory<IteratorType>; 6458 return factory_type::create(first, last); 6459 } 6460 6461 // Convenience shorthand from container to iterator 6462 // Enables ADL on begin(container) and end(container) 6463 // Encloses the using declarations in namespace for not to leak them to outside scope 6464 6465 namespace container_input_adapter_factory_impl 6466 { 6467 6468 using std::begin; 6469 using std::end; 6470 6471 template<typename ContainerType, typename Enable = void> 6472 struct container_input_adapter_factory {}; 6473 6474 template<typename ContainerType> 6475 struct container_input_adapter_factory< ContainerType, 6476 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> 6477 { 6478 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); 6479 6480 static adapter_type create(const ContainerType& container) 6481 { 6482 return input_adapter(begin(container), end(container)); 6483 } 6484 }; 6485 6486 } // namespace container_input_adapter_factory_impl 6487 6488 template<typename ContainerType> 6489 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container) 6490 { 6491 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); 6492 } 6493 6494 #ifndef JSON_NO_IO 6495 // Special cases with fast paths 6496 inline file_input_adapter input_adapter(std::FILE* file) 6497 { 6498 return file_input_adapter(file); 6499 } 6500 6501 inline input_stream_adapter input_adapter(std::istream& stream) 6502 { 6503 return input_stream_adapter(stream); 6504 } 6505 6506 inline input_stream_adapter input_adapter(std::istream&& stream) 6507 { 6508 return input_stream_adapter(stream); 6509 } 6510 #endif // JSON_NO_IO 6511 6512 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>())); 6513 6514 // Null-delimited strings, and the like. 6515 template < typename CharT, 6516 typename std::enable_if < 6517 std::is_pointer<CharT>::value&& 6518 !std::is_array<CharT>::value&& 6519 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& 6520 sizeof(typename std::remove_pointer<CharT>::type) == 1, 6521 int >::type = 0 > 6522 contiguous_bytes_input_adapter input_adapter(CharT b) 6523 { 6524 auto length = std::strlen(reinterpret_cast<const char*>(b)); 6525 const auto* ptr = reinterpret_cast<const char*>(b); 6526 return input_adapter(ptr, ptr + length); 6527 } 6528 6529 template<typename T, std::size_t N> 6530 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 6531 { 6532 return input_adapter(array, array + N); 6533 } 6534 6535 // This class only handles inputs of input_buffer_adapter type. 6536 // It's required so that expressions like {ptr, len} can be implicitly cast 6537 // to the correct adapter. 6538 class span_input_adapter 6539 { 6540 public: 6541 template < typename CharT, 6542 typename std::enable_if < 6543 std::is_pointer<CharT>::value&& 6544 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& 6545 sizeof(typename std::remove_pointer<CharT>::type) == 1, 6546 int >::type = 0 > 6547 span_input_adapter(CharT b, std::size_t l) 6548 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {} 6549 6550 template<class IteratorType, 6551 typename std::enable_if< 6552 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, 6553 int>::type = 0> 6554 span_input_adapter(IteratorType first, IteratorType last) 6555 : ia(input_adapter(first, last)) {} 6556 6557 contiguous_bytes_input_adapter&& get() 6558 { 6559 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) 6560 } 6561 6562 private: 6563 contiguous_bytes_input_adapter ia; 6564 }; 6565 6566 } // namespace detail 6567 NLOHMANN_JSON_NAMESPACE_END 6568 6569 // #include <nlohmann/detail/input/json_sax.hpp> 6570 // __ _____ _____ _____ 6571 // __| | __| | | | JSON for Modern C++ 6572 // | | |__ | | | | | | version 3.11.2 6573 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6574 // 6575 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 6576 // SPDX-License-Identifier: MIT 6577 6578 6579 6580 #include <cstddef> 6581 #include <string> // string 6582 #include <utility> // move 6583 #include <vector> // vector 6584 6585 // #include <nlohmann/detail/exceptions.hpp> 6586 6587 // #include <nlohmann/detail/macro_scope.hpp> 6588 6589 // #include <nlohmann/detail/string_concat.hpp> 6590 6591 6592 NLOHMANN_JSON_NAMESPACE_BEGIN 6593 6594 /*! 6595 @brief SAX interface 6596 6597 This class describes the SAX interface used by @ref nlohmann::json::sax_parse. 6598 Each function is called in different situations while the input is parsed. The 6599 boolean return value informs the parser whether to continue processing the 6600 input. 6601 */ 6602 template<typename BasicJsonType> 6603 struct json_sax 6604 { 6605 using number_integer_t = typename BasicJsonType::number_integer_t; 6606 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6607 using number_float_t = typename BasicJsonType::number_float_t; 6608 using string_t = typename BasicJsonType::string_t; 6609 using binary_t = typename BasicJsonType::binary_t; 6610 6611 /*! 6612 @brief a null value was read 6613 @return whether parsing should proceed 6614 */ 6615 virtual bool null() = 0; 6616 6617 /*! 6618 @brief a boolean value was read 6619 @param[in] val boolean value 6620 @return whether parsing should proceed 6621 */ 6622 virtual bool boolean(bool val) = 0; 6623 6624 /*! 6625 @brief an integer number was read 6626 @param[in] val integer value 6627 @return whether parsing should proceed 6628 */ 6629 virtual bool number_integer(number_integer_t val) = 0; 6630 6631 /*! 6632 @brief an unsigned integer number was read 6633 @param[in] val unsigned integer value 6634 @return whether parsing should proceed 6635 */ 6636 virtual bool number_unsigned(number_unsigned_t val) = 0; 6637 6638 /*! 6639 @brief a floating-point number was read 6640 @param[in] val floating-point value 6641 @param[in] s raw token value 6642 @return whether parsing should proceed 6643 */ 6644 virtual bool number_float(number_float_t val, const string_t& s) = 0; 6645 6646 /*! 6647 @brief a string value was read 6648 @param[in] val string value 6649 @return whether parsing should proceed 6650 @note It is safe to move the passed string value. 6651 */ 6652 virtual bool string(string_t& val) = 0; 6653 6654 /*! 6655 @brief a binary value was read 6656 @param[in] val binary value 6657 @return whether parsing should proceed 6658 @note It is safe to move the passed binary value. 6659 */ 6660 virtual bool binary(binary_t& val) = 0; 6661 6662 /*! 6663 @brief the beginning of an object was read 6664 @param[in] elements number of object elements or -1 if unknown 6665 @return whether parsing should proceed 6666 @note binary formats may report the number of elements 6667 */ 6668 virtual bool start_object(std::size_t elements) = 0; 6669 6670 /*! 6671 @brief an object key was read 6672 @param[in] val object key 6673 @return whether parsing should proceed 6674 @note It is safe to move the passed string. 6675 */ 6676 virtual bool key(string_t& val) = 0; 6677 6678 /*! 6679 @brief the end of an object was read 6680 @return whether parsing should proceed 6681 */ 6682 virtual bool end_object() = 0; 6683 6684 /*! 6685 @brief the beginning of an array was read 6686 @param[in] elements number of array elements or -1 if unknown 6687 @return whether parsing should proceed 6688 @note binary formats may report the number of elements 6689 */ 6690 virtual bool start_array(std::size_t elements) = 0; 6691 6692 /*! 6693 @brief the end of an array was read 6694 @return whether parsing should proceed 6695 */ 6696 virtual bool end_array() = 0; 6697 6698 /*! 6699 @brief a parse error occurred 6700 @param[in] position the position in the input where the error occurs 6701 @param[in] last_token the last read token 6702 @param[in] ex an exception object describing the error 6703 @return whether parsing should proceed (must return false) 6704 */ 6705 virtual bool parse_error(std::size_t position, 6706 const std::string& last_token, 6707 const detail::exception& ex) = 0; 6708 6709 json_sax() = default; 6710 json_sax(const json_sax&) = default; 6711 json_sax(json_sax&&) noexcept = default; 6712 json_sax& operator=(const json_sax&) = default; 6713 json_sax& operator=(json_sax&&) noexcept = default; 6714 virtual ~json_sax() = default; 6715 }; 6716 6717 6718 namespace detail 6719 { 6720 /*! 6721 @brief SAX implementation to create a JSON value from SAX events 6722 6723 This class implements the @ref json_sax interface and processes the SAX events 6724 to create a JSON value which makes it basically a DOM parser. The structure or 6725 hierarchy of the JSON value is managed by the stack `ref_stack` which contains 6726 a pointer to the respective array or object for each recursion depth. 6727 6728 After successful parsing, the value that is passed by reference to the 6729 constructor contains the parsed value. 6730 6731 @tparam BasicJsonType the JSON type 6732 */ 6733 template<typename BasicJsonType> 6734 class json_sax_dom_parser 6735 { 6736 public: 6737 using number_integer_t = typename BasicJsonType::number_integer_t; 6738 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6739 using number_float_t = typename BasicJsonType::number_float_t; 6740 using string_t = typename BasicJsonType::string_t; 6741 using binary_t = typename BasicJsonType::binary_t; 6742 6743 /*! 6744 @param[in,out] r reference to a JSON value that is manipulated while 6745 parsing 6746 @param[in] allow_exceptions_ whether parse errors yield exceptions 6747 */ 6748 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) 6749 : root(r), allow_exceptions(allow_exceptions_) 6750 {} 6751 6752 // make class move-only 6753 json_sax_dom_parser(const json_sax_dom_parser&) = delete; 6754 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6755 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; 6756 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6757 ~json_sax_dom_parser() = default; 6758 6759 bool null() 6760 { 6761 handle_value(nullptr); 6762 return true; 6763 } 6764 6765 bool boolean(bool val) 6766 { 6767 handle_value(val); 6768 return true; 6769 } 6770 6771 bool number_integer(number_integer_t val) 6772 { 6773 handle_value(val); 6774 return true; 6775 } 6776 6777 bool number_unsigned(number_unsigned_t val) 6778 { 6779 handle_value(val); 6780 return true; 6781 } 6782 6783 bool number_float(number_float_t val, const string_t& /*unused*/) 6784 { 6785 handle_value(val); 6786 return true; 6787 } 6788 6789 bool string(string_t& val) 6790 { 6791 handle_value(val); 6792 return true; 6793 } 6794 6795 bool binary(binary_t& val) 6796 { 6797 handle_value(std::move(val)); 6798 return true; 6799 } 6800 6801 bool start_object(std::size_t len) 6802 { 6803 ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); 6804 6805 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 6806 { 6807 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); 6808 } 6809 6810 return true; 6811 } 6812 6813 bool key(string_t& val) 6814 { 6815 JSON_ASSERT(!ref_stack.empty()); 6816 JSON_ASSERT(ref_stack.back()->is_object()); 6817 6818 // add null at given key and store the reference for later 6819 object_element = &(ref_stack.back()->m_value.object->operator[](val)); 6820 return true; 6821 } 6822 6823 bool end_object() 6824 { 6825 JSON_ASSERT(!ref_stack.empty()); 6826 JSON_ASSERT(ref_stack.back()->is_object()); 6827 6828 ref_stack.back()->set_parents(); 6829 ref_stack.pop_back(); 6830 return true; 6831 } 6832 6833 bool start_array(std::size_t len) 6834 { 6835 ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); 6836 6837 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 6838 { 6839 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); 6840 } 6841 6842 return true; 6843 } 6844 6845 bool end_array() 6846 { 6847 JSON_ASSERT(!ref_stack.empty()); 6848 JSON_ASSERT(ref_stack.back()->is_array()); 6849 6850 ref_stack.back()->set_parents(); 6851 ref_stack.pop_back(); 6852 return true; 6853 } 6854 6855 template<class Exception> 6856 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, 6857 const Exception& ex) 6858 { 6859 errored = true; 6860 static_cast<void>(ex); 6861 if (allow_exceptions) 6862 { 6863 JSON_THROW(ex); 6864 } 6865 return false; 6866 } 6867 6868 constexpr bool is_errored() const 6869 { 6870 return errored; 6871 } 6872 6873 private: 6874 /*! 6875 @invariant If the ref stack is empty, then the passed value will be the new 6876 root. 6877 @invariant If the ref stack contains a value, then it is an array or an 6878 object to which we can add elements 6879 */ 6880 template<typename Value> 6881 JSON_HEDLEY_RETURNS_NON_NULL 6882 BasicJsonType* handle_value(Value&& v) 6883 { 6884 if (ref_stack.empty()) 6885 { 6886 root = BasicJsonType(std::forward<Value>(v)); 6887 return &root; 6888 } 6889 6890 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); 6891 6892 if (ref_stack.back()->is_array()) 6893 { 6894 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v)); 6895 return &(ref_stack.back()->m_value.array->back()); 6896 } 6897 6898 JSON_ASSERT(ref_stack.back()->is_object()); 6899 JSON_ASSERT(object_element); 6900 *object_element = BasicJsonType(std::forward<Value>(v)); 6901 return object_element; 6902 } 6903 6904 /// the parsed JSON value 6905 BasicJsonType& root; 6906 /// stack to model hierarchy of values 6907 std::vector<BasicJsonType*> ref_stack {}; 6908 /// helper to hold the reference for the next object element 6909 BasicJsonType* object_element = nullptr; 6910 /// whether a syntax error occurred 6911 bool errored = false; 6912 /// whether to throw exceptions in case of errors 6913 const bool allow_exceptions = true; 6914 }; 6915 6916 template<typename BasicJsonType> 6917 class json_sax_dom_callback_parser 6918 { 6919 public: 6920 using number_integer_t = typename BasicJsonType::number_integer_t; 6921 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6922 using number_float_t = typename BasicJsonType::number_float_t; 6923 using string_t = typename BasicJsonType::string_t; 6924 using binary_t = typename BasicJsonType::binary_t; 6925 using parser_callback_t = typename BasicJsonType::parser_callback_t; 6926 using parse_event_t = typename BasicJsonType::parse_event_t; 6927 6928 json_sax_dom_callback_parser(BasicJsonType& r, 6929 const parser_callback_t cb, 6930 const bool allow_exceptions_ = true) 6931 : root(r), callback(cb), allow_exceptions(allow_exceptions_) 6932 { 6933 keep_stack.push_back(true); 6934 } 6935 6936 // make class move-only 6937 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; 6938 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6939 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; 6940 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6941 ~json_sax_dom_callback_parser() = default; 6942 6943 bool null() 6944 { 6945 handle_value(nullptr); 6946 return true; 6947 } 6948 6949 bool boolean(bool val) 6950 { 6951 handle_value(val); 6952 return true; 6953 } 6954 6955 bool number_integer(number_integer_t val) 6956 { 6957 handle_value(val); 6958 return true; 6959 } 6960 6961 bool number_unsigned(number_unsigned_t val) 6962 { 6963 handle_value(val); 6964 return true; 6965 } 6966 6967 bool number_float(number_float_t val, const string_t& /*unused*/) 6968 { 6969 handle_value(val); 6970 return true; 6971 } 6972 6973 bool string(string_t& val) 6974 { 6975 handle_value(val); 6976 return true; 6977 } 6978 6979 bool binary(binary_t& val) 6980 { 6981 handle_value(std::move(val)); 6982 return true; 6983 } 6984 6985 bool start_object(std::size_t len) 6986 { 6987 // check callback for object start 6988 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded); 6989 keep_stack.push_back(keep); 6990 6991 auto val = handle_value(BasicJsonType::value_t::object, true); 6992 ref_stack.push_back(val.second); 6993 6994 // check object limit 6995 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 6996 { 6997 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); 6998 } 6999 7000 return true; 7001 } 7002 7003 bool key(string_t& val) 7004 { 7005 BasicJsonType k = BasicJsonType(val); 7006 7007 // check callback for key 7008 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k); 7009 key_keep_stack.push_back(keep); 7010 7011 // add discarded value at given key and store the reference for later 7012 if (keep && ref_stack.back()) 7013 { 7014 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); 7015 } 7016 7017 return true; 7018 } 7019 7020 bool end_object() 7021 { 7022 if (ref_stack.back()) 7023 { 7024 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) 7025 { 7026 // discard object 7027 *ref_stack.back() = discarded; 7028 } 7029 else 7030 { 7031 ref_stack.back()->set_parents(); 7032 } 7033 } 7034 7035 JSON_ASSERT(!ref_stack.empty()); 7036 JSON_ASSERT(!keep_stack.empty()); 7037 ref_stack.pop_back(); 7038 keep_stack.pop_back(); 7039 7040 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) 7041 { 7042 // remove discarded value 7043 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) 7044 { 7045 if (it->is_discarded()) 7046 { 7047 ref_stack.back()->erase(it); 7048 break; 7049 } 7050 } 7051 } 7052 7053 return true; 7054 } 7055 7056 bool start_array(std::size_t len) 7057 { 7058 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded); 7059 keep_stack.push_back(keep); 7060 7061 auto val = handle_value(BasicJsonType::value_t::array, true); 7062 ref_stack.push_back(val.second); 7063 7064 // check array limit 7065 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 7066 { 7067 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); 7068 } 7069 7070 return true; 7071 } 7072 7073 bool end_array() 7074 { 7075 bool keep = true; 7076 7077 if (ref_stack.back()) 7078 { 7079 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); 7080 if (keep) 7081 { 7082 ref_stack.back()->set_parents(); 7083 } 7084 else 7085 { 7086 // discard array 7087 *ref_stack.back() = discarded; 7088 } 7089 } 7090 7091 JSON_ASSERT(!ref_stack.empty()); 7092 JSON_ASSERT(!keep_stack.empty()); 7093 ref_stack.pop_back(); 7094 keep_stack.pop_back(); 7095 7096 // remove discarded value 7097 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) 7098 { 7099 ref_stack.back()->m_value.array->pop_back(); 7100 } 7101 7102 return true; 7103 } 7104 7105 template<class Exception> 7106 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, 7107 const Exception& ex) 7108 { 7109 errored = true; 7110 static_cast<void>(ex); 7111 if (allow_exceptions) 7112 { 7113 JSON_THROW(ex); 7114 } 7115 return false; 7116 } 7117 7118 constexpr bool is_errored() const 7119 { 7120 return errored; 7121 } 7122 7123 private: 7124 /*! 7125 @param[in] v value to add to the JSON value we build during parsing 7126 @param[in] skip_callback whether we should skip calling the callback 7127 function; this is required after start_array() and 7128 start_object() SAX events, because otherwise we would call the 7129 callback function with an empty array or object, respectively. 7130 7131 @invariant If the ref stack is empty, then the passed value will be the new 7132 root. 7133 @invariant If the ref stack contains a value, then it is an array or an 7134 object to which we can add elements 7135 7136 @return pair of boolean (whether value should be kept) and pointer (to the 7137 passed value in the ref_stack hierarchy; nullptr if not kept) 7138 */ 7139 template<typename Value> 7140 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) 7141 { 7142 JSON_ASSERT(!keep_stack.empty()); 7143 7144 // do not handle this value if we know it would be added to a discarded 7145 // container 7146 if (!keep_stack.back()) 7147 { 7148 return {false, nullptr}; 7149 } 7150 7151 // create value 7152 auto value = BasicJsonType(std::forward<Value>(v)); 7153 7154 // check callback 7155 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); 7156 7157 // do not handle this value if we just learnt it shall be discarded 7158 if (!keep) 7159 { 7160 return {false, nullptr}; 7161 } 7162 7163 if (ref_stack.empty()) 7164 { 7165 root = std::move(value); 7166 return {true, &root}; 7167 } 7168 7169 // skip this value if we already decided to skip the parent 7170 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) 7171 if (!ref_stack.back()) 7172 { 7173 return {false, nullptr}; 7174 } 7175 7176 // we now only expect arrays and objects 7177 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); 7178 7179 // array 7180 if (ref_stack.back()->is_array()) 7181 { 7182 ref_stack.back()->m_value.array->emplace_back(std::move(value)); 7183 return {true, &(ref_stack.back()->m_value.array->back())}; 7184 } 7185 7186 // object 7187 JSON_ASSERT(ref_stack.back()->is_object()); 7188 // check if we should store an element for the current key 7189 JSON_ASSERT(!key_keep_stack.empty()); 7190 const bool store_element = key_keep_stack.back(); 7191 key_keep_stack.pop_back(); 7192 7193 if (!store_element) 7194 { 7195 return {false, nullptr}; 7196 } 7197 7198 JSON_ASSERT(object_element); 7199 *object_element = std::move(value); 7200 return {true, object_element}; 7201 } 7202 7203 /// the parsed JSON value 7204 BasicJsonType& root; 7205 /// stack to model hierarchy of values 7206 std::vector<BasicJsonType*> ref_stack {}; 7207 /// stack to manage which values to keep 7208 std::vector<bool> keep_stack {}; 7209 /// stack to manage which object keys to keep 7210 std::vector<bool> key_keep_stack {}; 7211 /// helper to hold the reference for the next object element 7212 BasicJsonType* object_element = nullptr; 7213 /// whether a syntax error occurred 7214 bool errored = false; 7215 /// callback function 7216 const parser_callback_t callback = nullptr; 7217 /// whether to throw exceptions in case of errors 7218 const bool allow_exceptions = true; 7219 /// a discarded value for the callback 7220 BasicJsonType discarded = BasicJsonType::value_t::discarded; 7221 }; 7222 7223 template<typename BasicJsonType> 7224 class json_sax_acceptor 7225 { 7226 public: 7227 using number_integer_t = typename BasicJsonType::number_integer_t; 7228 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7229 using number_float_t = typename BasicJsonType::number_float_t; 7230 using string_t = typename BasicJsonType::string_t; 7231 using binary_t = typename BasicJsonType::binary_t; 7232 7233 bool null() 7234 { 7235 return true; 7236 } 7237 7238 bool boolean(bool /*unused*/) 7239 { 7240 return true; 7241 } 7242 7243 bool number_integer(number_integer_t /*unused*/) 7244 { 7245 return true; 7246 } 7247 7248 bool number_unsigned(number_unsigned_t /*unused*/) 7249 { 7250 return true; 7251 } 7252 7253 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) 7254 { 7255 return true; 7256 } 7257 7258 bool string(string_t& /*unused*/) 7259 { 7260 return true; 7261 } 7262 7263 bool binary(binary_t& /*unused*/) 7264 { 7265 return true; 7266 } 7267 7268 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) 7269 { 7270 return true; 7271 } 7272 7273 bool key(string_t& /*unused*/) 7274 { 7275 return true; 7276 } 7277 7278 bool end_object() 7279 { 7280 return true; 7281 } 7282 7283 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) 7284 { 7285 return true; 7286 } 7287 7288 bool end_array() 7289 { 7290 return true; 7291 } 7292 7293 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) 7294 { 7295 return false; 7296 } 7297 }; 7298 7299 } // namespace detail 7300 NLOHMANN_JSON_NAMESPACE_END 7301 7302 // #include <nlohmann/detail/input/lexer.hpp> 7303 // __ _____ _____ _____ 7304 // __| | __| | | | JSON for Modern C++ 7305 // | | |__ | | | | | | version 3.11.2 7306 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 7307 // 7308 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 7309 // SPDX-License-Identifier: MIT 7310 7311 7312 7313 #include <array> // array 7314 #include <clocale> // localeconv 7315 #include <cstddef> // size_t 7316 #include <cstdio> // snprintf 7317 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull 7318 #include <initializer_list> // initializer_list 7319 #include <string> // char_traits, string 7320 #include <utility> // move 7321 #include <vector> // vector 7322 7323 // #include <nlohmann/detail/input/input_adapters.hpp> 7324 7325 // #include <nlohmann/detail/input/position_t.hpp> 7326 7327 // #include <nlohmann/detail/macro_scope.hpp> 7328 7329 7330 NLOHMANN_JSON_NAMESPACE_BEGIN 7331 namespace detail 7332 { 7333 7334 /////////// 7335 // lexer // 7336 /////////// 7337 7338 template<typename BasicJsonType> 7339 class lexer_base 7340 { 7341 public: 7342 /// token types for the parser 7343 enum class token_type 7344 { 7345 uninitialized, ///< indicating the scanner is uninitialized 7346 literal_true, ///< the `true` literal 7347 literal_false, ///< the `false` literal 7348 literal_null, ///< the `null` literal 7349 value_string, ///< a string -- use get_string() for actual value 7350 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value 7351 value_integer, ///< a signed integer -- use get_number_integer() for actual value 7352 value_float, ///< an floating point number -- use get_number_float() for actual value 7353 begin_array, ///< the character for array begin `[` 7354 begin_object, ///< the character for object begin `{` 7355 end_array, ///< the character for array end `]` 7356 end_object, ///< the character for object end `}` 7357 name_separator, ///< the name separator `:` 7358 value_separator, ///< the value separator `,` 7359 parse_error, ///< indicating a parse error 7360 end_of_input, ///< indicating the end of the input buffer 7361 literal_or_value ///< a literal or the begin of a value (only for diagnostics) 7362 }; 7363 7364 /// return name of values of type token_type (only used for errors) 7365 JSON_HEDLEY_RETURNS_NON_NULL 7366 JSON_HEDLEY_CONST 7367 static const char* token_type_name(const token_type t) noexcept 7368 { 7369 switch (t) 7370 { 7371 case token_type::uninitialized: 7372 return "<uninitialized>"; 7373 case token_type::literal_true: 7374 return "true literal"; 7375 case token_type::literal_false: 7376 return "false literal"; 7377 case token_type::literal_null: 7378 return "null literal"; 7379 case token_type::value_string: 7380 return "string literal"; 7381 case token_type::value_unsigned: 7382 case token_type::value_integer: 7383 case token_type::value_float: 7384 return "number literal"; 7385 case token_type::begin_array: 7386 return "'['"; 7387 case token_type::begin_object: 7388 return "'{'"; 7389 case token_type::end_array: 7390 return "']'"; 7391 case token_type::end_object: 7392 return "'}'"; 7393 case token_type::name_separator: 7394 return "':'"; 7395 case token_type::value_separator: 7396 return "','"; 7397 case token_type::parse_error: 7398 return "<parse error>"; 7399 case token_type::end_of_input: 7400 return "end of input"; 7401 case token_type::literal_or_value: 7402 return "'[', '{', or a literal"; 7403 // LCOV_EXCL_START 7404 default: // catch non-enum values 7405 return "unknown token"; 7406 // LCOV_EXCL_STOP 7407 } 7408 } 7409 }; 7410 /*! 7411 @brief lexical analysis 7412 7413 This class organizes the lexical analysis during JSON deserialization. 7414 */ 7415 template<typename BasicJsonType, typename InputAdapterType> 7416 class lexer : public lexer_base<BasicJsonType> 7417 { 7418 using number_integer_t = typename BasicJsonType::number_integer_t; 7419 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7420 using number_float_t = typename BasicJsonType::number_float_t; 7421 using string_t = typename BasicJsonType::string_t; 7422 using char_type = typename InputAdapterType::char_type; 7423 using char_int_type = typename std::char_traits<char_type>::int_type; 7424 7425 public: 7426 using token_type = typename lexer_base<BasicJsonType>::token_type; 7427 7428 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept 7429 : ia(std::move(adapter)) 7430 , ignore_comments(ignore_comments_) 7431 , decimal_point_char(static_cast<char_int_type>(get_decimal_point())) 7432 {} 7433 7434 // delete because of pointer members 7435 lexer(const lexer&) = delete; 7436 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7437 lexer& operator=(lexer&) = delete; 7438 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7439 ~lexer() = default; 7440 7441 private: 7442 ///////////////////// 7443 // locales 7444 ///////////////////// 7445 7446 /// return the locale-dependent decimal point 7447 JSON_HEDLEY_PURE 7448 static char get_decimal_point() noexcept 7449 { 7450 const auto* loc = localeconv(); 7451 JSON_ASSERT(loc != nullptr); 7452 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); 7453 } 7454 7455 ///////////////////// 7456 // scan functions 7457 ///////////////////// 7458 7459 /*! 7460 @brief get codepoint from 4 hex characters following `\u` 7461 7462 For input "\u c1 c2 c3 c4" the codepoint is: 7463 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 7464 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) 7465 7466 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' 7467 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The 7468 conversion is done by subtracting the offset (0x30, 0x37, and 0x57) 7469 between the ASCII value of the character and the desired integer value. 7470 7471 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or 7472 non-hex character) 7473 */ 7474 int get_codepoint() 7475 { 7476 // this function only makes sense after reading `\u` 7477 JSON_ASSERT(current == 'u'); 7478 int codepoint = 0; 7479 7480 const auto factors = { 12u, 8u, 4u, 0u }; 7481 for (const auto factor : factors) 7482 { 7483 get(); 7484 7485 if (current >= '0' && current <= '9') 7486 { 7487 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor); 7488 } 7489 else if (current >= 'A' && current <= 'F') 7490 { 7491 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor); 7492 } 7493 else if (current >= 'a' && current <= 'f') 7494 { 7495 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor); 7496 } 7497 else 7498 { 7499 return -1; 7500 } 7501 } 7502 7503 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); 7504 return codepoint; 7505 } 7506 7507 /*! 7508 @brief check if the next byte(s) are inside a given range 7509 7510 Adds the current byte and, for each passed range, reads a new byte and 7511 checks if it is inside the range. If a violation was detected, set up an 7512 error message and return false. Otherwise, return true. 7513 7514 @param[in] ranges list of integers; interpreted as list of pairs of 7515 inclusive lower and upper bound, respectively 7516 7517 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, 7518 1, 2, or 3 pairs. This precondition is enforced by an assertion. 7519 7520 @return true if and only if no range violation was detected 7521 */ 7522 bool next_byte_in_range(std::initializer_list<char_int_type> ranges) 7523 { 7524 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); 7525 add(current); 7526 7527 for (auto range = ranges.begin(); range != ranges.end(); ++range) 7528 { 7529 get(); 7530 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) 7531 { 7532 add(current); 7533 } 7534 else 7535 { 7536 error_message = "invalid string: ill-formed UTF-8 byte"; 7537 return false; 7538 } 7539 } 7540 7541 return true; 7542 } 7543 7544 /*! 7545 @brief scan a string literal 7546 7547 This function scans a string according to Sect. 7 of RFC 8259. While 7548 scanning, bytes are escaped and copied into buffer token_buffer. Then the 7549 function returns successfully, token_buffer is *not* null-terminated (as it 7550 may contain \0 bytes), and token_buffer.size() is the number of bytes in the 7551 string. 7552 7553 @return token_type::value_string if string could be successfully scanned, 7554 token_type::parse_error otherwise 7555 7556 @note In case of errors, variable error_message contains a textual 7557 description. 7558 */ 7559 token_type scan_string() 7560 { 7561 // reset token_buffer (ignore opening quote) 7562 reset(); 7563 7564 // we entered the function by reading an open quote 7565 JSON_ASSERT(current == '\"'); 7566 7567 while (true) 7568 { 7569 // get next character 7570 switch (get()) 7571 { 7572 // end of file while parsing string 7573 case std::char_traits<char_type>::eof(): 7574 { 7575 error_message = "invalid string: missing closing quote"; 7576 return token_type::parse_error; 7577 } 7578 7579 // closing quote 7580 case '\"': 7581 { 7582 return token_type::value_string; 7583 } 7584 7585 // escapes 7586 case '\\': 7587 { 7588 switch (get()) 7589 { 7590 // quotation mark 7591 case '\"': 7592 add('\"'); 7593 break; 7594 // reverse solidus 7595 case '\\': 7596 add('\\'); 7597 break; 7598 // solidus 7599 case '/': 7600 add('/'); 7601 break; 7602 // backspace 7603 case 'b': 7604 add('\b'); 7605 break; 7606 // form feed 7607 case 'f': 7608 add('\f'); 7609 break; 7610 // line feed 7611 case 'n': 7612 add('\n'); 7613 break; 7614 // carriage return 7615 case 'r': 7616 add('\r'); 7617 break; 7618 // tab 7619 case 't': 7620 add('\t'); 7621 break; 7622 7623 // unicode escapes 7624 case 'u': 7625 { 7626 const int codepoint1 = get_codepoint(); 7627 int codepoint = codepoint1; // start with codepoint1 7628 7629 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) 7630 { 7631 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; 7632 return token_type::parse_error; 7633 } 7634 7635 // check if code point is a high surrogate 7636 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) 7637 { 7638 // expect next \uxxxx entry 7639 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) 7640 { 7641 const int codepoint2 = get_codepoint(); 7642 7643 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) 7644 { 7645 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; 7646 return token_type::parse_error; 7647 } 7648 7649 // check if codepoint2 is a low surrogate 7650 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) 7651 { 7652 // overwrite codepoint 7653 codepoint = static_cast<int>( 7654 // high surrogate occupies the most significant 22 bits 7655 (static_cast<unsigned int>(codepoint1) << 10u) 7656 // low surrogate occupies the least significant 15 bits 7657 + static_cast<unsigned int>(codepoint2) 7658 // there is still the 0xD800, 0xDC00 and 0x10000 noise 7659 // in the result, so we have to subtract with: 7660 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 7661 - 0x35FDC00u); 7662 } 7663 else 7664 { 7665 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; 7666 return token_type::parse_error; 7667 } 7668 } 7669 else 7670 { 7671 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; 7672 return token_type::parse_error; 7673 } 7674 } 7675 else 7676 { 7677 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) 7678 { 7679 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; 7680 return token_type::parse_error; 7681 } 7682 } 7683 7684 // result of the above calculation yields a proper codepoint 7685 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); 7686 7687 // translate codepoint into bytes 7688 if (codepoint < 0x80) 7689 { 7690 // 1-byte characters: 0xxxxxxx (ASCII) 7691 add(static_cast<char_int_type>(codepoint)); 7692 } 7693 else if (codepoint <= 0x7FF) 7694 { 7695 // 2-byte characters: 110xxxxx 10xxxxxx 7696 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u))); 7697 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7698 } 7699 else if (codepoint <= 0xFFFF) 7700 { 7701 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx 7702 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u))); 7703 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); 7704 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7705 } 7706 else 7707 { 7708 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 7709 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u))); 7710 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu))); 7711 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); 7712 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7713 } 7714 7715 break; 7716 } 7717 7718 // other characters after escape 7719 default: 7720 error_message = "invalid string: forbidden character after backslash"; 7721 return token_type::parse_error; 7722 } 7723 7724 break; 7725 } 7726 7727 // invalid control characters 7728 case 0x00: 7729 { 7730 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; 7731 return token_type::parse_error; 7732 } 7733 7734 case 0x01: 7735 { 7736 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; 7737 return token_type::parse_error; 7738 } 7739 7740 case 0x02: 7741 { 7742 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; 7743 return token_type::parse_error; 7744 } 7745 7746 case 0x03: 7747 { 7748 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; 7749 return token_type::parse_error; 7750 } 7751 7752 case 0x04: 7753 { 7754 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; 7755 return token_type::parse_error; 7756 } 7757 7758 case 0x05: 7759 { 7760 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; 7761 return token_type::parse_error; 7762 } 7763 7764 case 0x06: 7765 { 7766 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; 7767 return token_type::parse_error; 7768 } 7769 7770 case 0x07: 7771 { 7772 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; 7773 return token_type::parse_error; 7774 } 7775 7776 case 0x08: 7777 { 7778 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; 7779 return token_type::parse_error; 7780 } 7781 7782 case 0x09: 7783 { 7784 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; 7785 return token_type::parse_error; 7786 } 7787 7788 case 0x0A: 7789 { 7790 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; 7791 return token_type::parse_error; 7792 } 7793 7794 case 0x0B: 7795 { 7796 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; 7797 return token_type::parse_error; 7798 } 7799 7800 case 0x0C: 7801 { 7802 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; 7803 return token_type::parse_error; 7804 } 7805 7806 case 0x0D: 7807 { 7808 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; 7809 return token_type::parse_error; 7810 } 7811 7812 case 0x0E: 7813 { 7814 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; 7815 return token_type::parse_error; 7816 } 7817 7818 case 0x0F: 7819 { 7820 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; 7821 return token_type::parse_error; 7822 } 7823 7824 case 0x10: 7825 { 7826 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; 7827 return token_type::parse_error; 7828 } 7829 7830 case 0x11: 7831 { 7832 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; 7833 return token_type::parse_error; 7834 } 7835 7836 case 0x12: 7837 { 7838 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; 7839 return token_type::parse_error; 7840 } 7841 7842 case 0x13: 7843 { 7844 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; 7845 return token_type::parse_error; 7846 } 7847 7848 case 0x14: 7849 { 7850 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; 7851 return token_type::parse_error; 7852 } 7853 7854 case 0x15: 7855 { 7856 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; 7857 return token_type::parse_error; 7858 } 7859 7860 case 0x16: 7861 { 7862 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; 7863 return token_type::parse_error; 7864 } 7865 7866 case 0x17: 7867 { 7868 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; 7869 return token_type::parse_error; 7870 } 7871 7872 case 0x18: 7873 { 7874 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; 7875 return token_type::parse_error; 7876 } 7877 7878 case 0x19: 7879 { 7880 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; 7881 return token_type::parse_error; 7882 } 7883 7884 case 0x1A: 7885 { 7886 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; 7887 return token_type::parse_error; 7888 } 7889 7890 case 0x1B: 7891 { 7892 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; 7893 return token_type::parse_error; 7894 } 7895 7896 case 0x1C: 7897 { 7898 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; 7899 return token_type::parse_error; 7900 } 7901 7902 case 0x1D: 7903 { 7904 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; 7905 return token_type::parse_error; 7906 } 7907 7908 case 0x1E: 7909 { 7910 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; 7911 return token_type::parse_error; 7912 } 7913 7914 case 0x1F: 7915 { 7916 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; 7917 return token_type::parse_error; 7918 } 7919 7920 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) 7921 case 0x20: 7922 case 0x21: 7923 case 0x23: 7924 case 0x24: 7925 case 0x25: 7926 case 0x26: 7927 case 0x27: 7928 case 0x28: 7929 case 0x29: 7930 case 0x2A: 7931 case 0x2B: 7932 case 0x2C: 7933 case 0x2D: 7934 case 0x2E: 7935 case 0x2F: 7936 case 0x30: 7937 case 0x31: 7938 case 0x32: 7939 case 0x33: 7940 case 0x34: 7941 case 0x35: 7942 case 0x36: 7943 case 0x37: 7944 case 0x38: 7945 case 0x39: 7946 case 0x3A: 7947 case 0x3B: 7948 case 0x3C: 7949 case 0x3D: 7950 case 0x3E: 7951 case 0x3F: 7952 case 0x40: 7953 case 0x41: 7954 case 0x42: 7955 case 0x43: 7956 case 0x44: 7957 case 0x45: 7958 case 0x46: 7959 case 0x47: 7960 case 0x48: 7961 case 0x49: 7962 case 0x4A: 7963 case 0x4B: 7964 case 0x4C: 7965 case 0x4D: 7966 case 0x4E: 7967 case 0x4F: 7968 case 0x50: 7969 case 0x51: 7970 case 0x52: 7971 case 0x53: 7972 case 0x54: 7973 case 0x55: 7974 case 0x56: 7975 case 0x57: 7976 case 0x58: 7977 case 0x59: 7978 case 0x5A: 7979 case 0x5B: 7980 case 0x5D: 7981 case 0x5E: 7982 case 0x5F: 7983 case 0x60: 7984 case 0x61: 7985 case 0x62: 7986 case 0x63: 7987 case 0x64: 7988 case 0x65: 7989 case 0x66: 7990 case 0x67: 7991 case 0x68: 7992 case 0x69: 7993 case 0x6A: 7994 case 0x6B: 7995 case 0x6C: 7996 case 0x6D: 7997 case 0x6E: 7998 case 0x6F: 7999 case 0x70: 8000 case 0x71: 8001 case 0x72: 8002 case 0x73: 8003 case 0x74: 8004 case 0x75: 8005 case 0x76: 8006 case 0x77: 8007 case 0x78: 8008 case 0x79: 8009 case 0x7A: 8010 case 0x7B: 8011 case 0x7C: 8012 case 0x7D: 8013 case 0x7E: 8014 case 0x7F: 8015 { 8016 add(current); 8017 break; 8018 } 8019 8020 // U+0080..U+07FF: bytes C2..DF 80..BF 8021 case 0xC2: 8022 case 0xC3: 8023 case 0xC4: 8024 case 0xC5: 8025 case 0xC6: 8026 case 0xC7: 8027 case 0xC8: 8028 case 0xC9: 8029 case 0xCA: 8030 case 0xCB: 8031 case 0xCC: 8032 case 0xCD: 8033 case 0xCE: 8034 case 0xCF: 8035 case 0xD0: 8036 case 0xD1: 8037 case 0xD2: 8038 case 0xD3: 8039 case 0xD4: 8040 case 0xD5: 8041 case 0xD6: 8042 case 0xD7: 8043 case 0xD8: 8044 case 0xD9: 8045 case 0xDA: 8046 case 0xDB: 8047 case 0xDC: 8048 case 0xDD: 8049 case 0xDE: 8050 case 0xDF: 8051 { 8052 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) 8053 { 8054 return token_type::parse_error; 8055 } 8056 break; 8057 } 8058 8059 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF 8060 case 0xE0: 8061 { 8062 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) 8063 { 8064 return token_type::parse_error; 8065 } 8066 break; 8067 } 8068 8069 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF 8070 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF 8071 case 0xE1: 8072 case 0xE2: 8073 case 0xE3: 8074 case 0xE4: 8075 case 0xE5: 8076 case 0xE6: 8077 case 0xE7: 8078 case 0xE8: 8079 case 0xE9: 8080 case 0xEA: 8081 case 0xEB: 8082 case 0xEC: 8083 case 0xEE: 8084 case 0xEF: 8085 { 8086 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) 8087 { 8088 return token_type::parse_error; 8089 } 8090 break; 8091 } 8092 8093 // U+D000..U+D7FF: bytes ED 80..9F 80..BF 8094 case 0xED: 8095 { 8096 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) 8097 { 8098 return token_type::parse_error; 8099 } 8100 break; 8101 } 8102 8103 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF 8104 case 0xF0: 8105 { 8106 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) 8107 { 8108 return token_type::parse_error; 8109 } 8110 break; 8111 } 8112 8113 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF 8114 case 0xF1: 8115 case 0xF2: 8116 case 0xF3: 8117 { 8118 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) 8119 { 8120 return token_type::parse_error; 8121 } 8122 break; 8123 } 8124 8125 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 8126 case 0xF4: 8127 { 8128 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) 8129 { 8130 return token_type::parse_error; 8131 } 8132 break; 8133 } 8134 8135 // remaining bytes (80..C1 and F5..FF) are ill-formed 8136 default: 8137 { 8138 error_message = "invalid string: ill-formed UTF-8 byte"; 8139 return token_type::parse_error; 8140 } 8141 } 8142 } 8143 } 8144 8145 /*! 8146 * @brief scan a comment 8147 * @return whether comment could be scanned successfully 8148 */ 8149 bool scan_comment() 8150 { 8151 switch (get()) 8152 { 8153 // single-line comments skip input until a newline or EOF is read 8154 case '/': 8155 { 8156 while (true) 8157 { 8158 switch (get()) 8159 { 8160 case '\n': 8161 case '\r': 8162 case std::char_traits<char_type>::eof(): 8163 case '\0': 8164 return true; 8165 8166 default: 8167 break; 8168 } 8169 } 8170 } 8171 8172 // multi-line comments skip input until */ is read 8173 case '*': 8174 { 8175 while (true) 8176 { 8177 switch (get()) 8178 { 8179 case std::char_traits<char_type>::eof(): 8180 case '\0': 8181 { 8182 error_message = "invalid comment; missing closing '*/'"; 8183 return false; 8184 } 8185 8186 case '*': 8187 { 8188 switch (get()) 8189 { 8190 case '/': 8191 return true; 8192 8193 default: 8194 { 8195 unget(); 8196 continue; 8197 } 8198 } 8199 } 8200 8201 default: 8202 continue; 8203 } 8204 } 8205 } 8206 8207 // unexpected character after reading '/' 8208 default: 8209 { 8210 error_message = "invalid comment; expecting '/' or '*' after '/'"; 8211 return false; 8212 } 8213 } 8214 } 8215 8216 JSON_HEDLEY_NON_NULL(2) 8217 static void strtof(float& f, const char* str, char** endptr) noexcept 8218 { 8219 f = std::strtof(str, endptr); 8220 } 8221 8222 JSON_HEDLEY_NON_NULL(2) 8223 static void strtof(double& f, const char* str, char** endptr) noexcept 8224 { 8225 f = std::strtod(str, endptr); 8226 } 8227 8228 JSON_HEDLEY_NON_NULL(2) 8229 static void strtof(long double& f, const char* str, char** endptr) noexcept 8230 { 8231 f = std::strtold(str, endptr); 8232 } 8233 8234 /*! 8235 @brief scan a number literal 8236 8237 This function scans a string according to Sect. 6 of RFC 8259. 8238 8239 The function is realized with a deterministic finite state machine derived 8240 from the grammar described in RFC 8259. Starting in state "init", the 8241 input is read and used to determined the next state. Only state "done" 8242 accepts the number. State "error" is a trap state to model errors. In the 8243 table below, "anything" means any character but the ones listed before. 8244 8245 state | 0 | 1-9 | e E | + | - | . | anything 8246 ---------|----------|----------|----------|---------|---------|----------|----------- 8247 init | zero | any1 | [error] | [error] | minus | [error] | [error] 8248 minus | zero | any1 | [error] | [error] | [error] | [error] | [error] 8249 zero | done | done | exponent | done | done | decimal1 | done 8250 any1 | any1 | any1 | exponent | done | done | decimal1 | done 8251 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] 8252 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done 8253 exponent | any2 | any2 | [error] | sign | sign | [error] | [error] 8254 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] 8255 any2 | any2 | any2 | done | done | done | done | done 8256 8257 The state machine is realized with one label per state (prefixed with 8258 "scan_number_") and `goto` statements between them. The state machine 8259 contains cycles, but any cycle can be left when EOF is read. Therefore, 8260 the function is guaranteed to terminate. 8261 8262 During scanning, the read bytes are stored in token_buffer. This string is 8263 then converted to a signed integer, an unsigned integer, or a 8264 floating-point number. 8265 8266 @return token_type::value_unsigned, token_type::value_integer, or 8267 token_type::value_float if number could be successfully scanned, 8268 token_type::parse_error otherwise 8269 8270 @note The scanner is independent of the current locale. Internally, the 8271 locale's decimal point is used instead of `.` to work with the 8272 locale-dependent converters. 8273 */ 8274 token_type scan_number() // lgtm [cpp/use-of-goto] 8275 { 8276 // reset token_buffer to store the number's bytes 8277 reset(); 8278 8279 // the type of the parsed number; initially set to unsigned; will be 8280 // changed if minus sign, decimal point or exponent is read 8281 token_type number_type = token_type::value_unsigned; 8282 8283 // state (init): we just found out we need to scan a number 8284 switch (current) 8285 { 8286 case '-': 8287 { 8288 add(current); 8289 goto scan_number_minus; 8290 } 8291 8292 case '0': 8293 { 8294 add(current); 8295 goto scan_number_zero; 8296 } 8297 8298 case '1': 8299 case '2': 8300 case '3': 8301 case '4': 8302 case '5': 8303 case '6': 8304 case '7': 8305 case '8': 8306 case '9': 8307 { 8308 add(current); 8309 goto scan_number_any1; 8310 } 8311 8312 // all other characters are rejected outside scan_number() 8313 default: // LCOV_EXCL_LINE 8314 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 8315 } 8316 8317 scan_number_minus: 8318 // state: we just parsed a leading minus sign 8319 number_type = token_type::value_integer; 8320 switch (get()) 8321 { 8322 case '0': 8323 { 8324 add(current); 8325 goto scan_number_zero; 8326 } 8327 8328 case '1': 8329 case '2': 8330 case '3': 8331 case '4': 8332 case '5': 8333 case '6': 8334 case '7': 8335 case '8': 8336 case '9': 8337 { 8338 add(current); 8339 goto scan_number_any1; 8340 } 8341 8342 default: 8343 { 8344 error_message = "invalid number; expected digit after '-'"; 8345 return token_type::parse_error; 8346 } 8347 } 8348 8349 scan_number_zero: 8350 // state: we just parse a zero (maybe with a leading minus sign) 8351 switch (get()) 8352 { 8353 case '.': 8354 { 8355 add(decimal_point_char); 8356 goto scan_number_decimal1; 8357 } 8358 8359 case 'e': 8360 case 'E': 8361 { 8362 add(current); 8363 goto scan_number_exponent; 8364 } 8365 8366 default: 8367 goto scan_number_done; 8368 } 8369 8370 scan_number_any1: 8371 // state: we just parsed a number 0-9 (maybe with a leading minus sign) 8372 switch (get()) 8373 { 8374 case '0': 8375 case '1': 8376 case '2': 8377 case '3': 8378 case '4': 8379 case '5': 8380 case '6': 8381 case '7': 8382 case '8': 8383 case '9': 8384 { 8385 add(current); 8386 goto scan_number_any1; 8387 } 8388 8389 case '.': 8390 { 8391 add(decimal_point_char); 8392 goto scan_number_decimal1; 8393 } 8394 8395 case 'e': 8396 case 'E': 8397 { 8398 add(current); 8399 goto scan_number_exponent; 8400 } 8401 8402 default: 8403 goto scan_number_done; 8404 } 8405 8406 scan_number_decimal1: 8407 // state: we just parsed a decimal point 8408 number_type = token_type::value_float; 8409 switch (get()) 8410 { 8411 case '0': 8412 case '1': 8413 case '2': 8414 case '3': 8415 case '4': 8416 case '5': 8417 case '6': 8418 case '7': 8419 case '8': 8420 case '9': 8421 { 8422 add(current); 8423 goto scan_number_decimal2; 8424 } 8425 8426 default: 8427 { 8428 error_message = "invalid number; expected digit after '.'"; 8429 return token_type::parse_error; 8430 } 8431 } 8432 8433 scan_number_decimal2: 8434 // we just parsed at least one number after a decimal point 8435 switch (get()) 8436 { 8437 case '0': 8438 case '1': 8439 case '2': 8440 case '3': 8441 case '4': 8442 case '5': 8443 case '6': 8444 case '7': 8445 case '8': 8446 case '9': 8447 { 8448 add(current); 8449 goto scan_number_decimal2; 8450 } 8451 8452 case 'e': 8453 case 'E': 8454 { 8455 add(current); 8456 goto scan_number_exponent; 8457 } 8458 8459 default: 8460 goto scan_number_done; 8461 } 8462 8463 scan_number_exponent: 8464 // we just parsed an exponent 8465 number_type = token_type::value_float; 8466 switch (get()) 8467 { 8468 case '+': 8469 case '-': 8470 { 8471 add(current); 8472 goto scan_number_sign; 8473 } 8474 8475 case '0': 8476 case '1': 8477 case '2': 8478 case '3': 8479 case '4': 8480 case '5': 8481 case '6': 8482 case '7': 8483 case '8': 8484 case '9': 8485 { 8486 add(current); 8487 goto scan_number_any2; 8488 } 8489 8490 default: 8491 { 8492 error_message = 8493 "invalid number; expected '+', '-', or digit after exponent"; 8494 return token_type::parse_error; 8495 } 8496 } 8497 8498 scan_number_sign: 8499 // we just parsed an exponent sign 8500 switch (get()) 8501 { 8502 case '0': 8503 case '1': 8504 case '2': 8505 case '3': 8506 case '4': 8507 case '5': 8508 case '6': 8509 case '7': 8510 case '8': 8511 case '9': 8512 { 8513 add(current); 8514 goto scan_number_any2; 8515 } 8516 8517 default: 8518 { 8519 error_message = "invalid number; expected digit after exponent sign"; 8520 return token_type::parse_error; 8521 } 8522 } 8523 8524 scan_number_any2: 8525 // we just parsed a number after the exponent or exponent sign 8526 switch (get()) 8527 { 8528 case '0': 8529 case '1': 8530 case '2': 8531 case '3': 8532 case '4': 8533 case '5': 8534 case '6': 8535 case '7': 8536 case '8': 8537 case '9': 8538 { 8539 add(current); 8540 goto scan_number_any2; 8541 } 8542 8543 default: 8544 goto scan_number_done; 8545 } 8546 8547 scan_number_done: 8548 // unget the character after the number (we only read it to know that 8549 // we are done scanning a number) 8550 unget(); 8551 8552 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8553 errno = 0; 8554 8555 // try to parse integers first and fall back to floats 8556 if (number_type == token_type::value_unsigned) 8557 { 8558 const auto x = std::strtoull(token_buffer.data(), &endptr, 10); 8559 8560 // we checked the number format before 8561 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8562 8563 if (errno == 0) 8564 { 8565 value_unsigned = static_cast<number_unsigned_t>(x); 8566 if (value_unsigned == x) 8567 { 8568 return token_type::value_unsigned; 8569 } 8570 } 8571 } 8572 else if (number_type == token_type::value_integer) 8573 { 8574 const auto x = std::strtoll(token_buffer.data(), &endptr, 10); 8575 8576 // we checked the number format before 8577 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8578 8579 if (errno == 0) 8580 { 8581 value_integer = static_cast<number_integer_t>(x); 8582 if (value_integer == x) 8583 { 8584 return token_type::value_integer; 8585 } 8586 } 8587 } 8588 8589 // this code is reached if we parse a floating-point number or if an 8590 // integer conversion above failed 8591 strtof(value_float, token_buffer.data(), &endptr); 8592 8593 // we checked the number format before 8594 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8595 8596 return token_type::value_float; 8597 } 8598 8599 /*! 8600 @param[in] literal_text the literal text to expect 8601 @param[in] length the length of the passed literal text 8602 @param[in] return_type the token type to return on success 8603 */ 8604 JSON_HEDLEY_NON_NULL(2) 8605 token_type scan_literal(const char_type* literal_text, const std::size_t length, 8606 token_type return_type) 8607 { 8608 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]); 8609 for (std::size_t i = 1; i < length; ++i) 8610 { 8611 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i])) 8612 { 8613 error_message = "invalid literal"; 8614 return token_type::parse_error; 8615 } 8616 } 8617 return return_type; 8618 } 8619 8620 ///////////////////// 8621 // input management 8622 ///////////////////// 8623 8624 /// reset token_buffer; current character is beginning of token 8625 void reset() noexcept 8626 { 8627 token_buffer.clear(); 8628 token_string.clear(); 8629 token_string.push_back(std::char_traits<char_type>::to_char_type(current)); 8630 } 8631 8632 /* 8633 @brief get next character from the input 8634 8635 This function provides the interface to the used input adapter. It does 8636 not throw in case the input reached EOF, but returns a 8637 `std::char_traits<char>::eof()` in that case. Stores the scanned characters 8638 for use in error messages. 8639 8640 @return character read from the input 8641 */ 8642 char_int_type get() 8643 { 8644 ++position.chars_read_total; 8645 ++position.chars_read_current_line; 8646 8647 if (next_unget) 8648 { 8649 // just reset the next_unget variable and work with current 8650 next_unget = false; 8651 } 8652 else 8653 { 8654 current = ia.get_character(); 8655 } 8656 8657 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof())) 8658 { 8659 token_string.push_back(std::char_traits<char_type>::to_char_type(current)); 8660 } 8661 8662 if (current == '\n') 8663 { 8664 ++position.lines_read; 8665 position.chars_read_current_line = 0; 8666 } 8667 8668 return current; 8669 } 8670 8671 /*! 8672 @brief unget current character (read it again on next get) 8673 8674 We implement unget by setting variable next_unget to true. The input is not 8675 changed - we just simulate ungetting by modifying chars_read_total, 8676 chars_read_current_line, and token_string. The next call to get() will 8677 behave as if the unget character is read again. 8678 */ 8679 void unget() 8680 { 8681 next_unget = true; 8682 8683 --position.chars_read_total; 8684 8685 // in case we "unget" a newline, we have to also decrement the lines_read 8686 if (position.chars_read_current_line == 0) 8687 { 8688 if (position.lines_read > 0) 8689 { 8690 --position.lines_read; 8691 } 8692 } 8693 else 8694 { 8695 --position.chars_read_current_line; 8696 } 8697 8698 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof())) 8699 { 8700 JSON_ASSERT(!token_string.empty()); 8701 token_string.pop_back(); 8702 } 8703 } 8704 8705 /// add a character to token_buffer 8706 void add(char_int_type c) 8707 { 8708 token_buffer.push_back(static_cast<typename string_t::value_type>(c)); 8709 } 8710 8711 public: 8712 ///////////////////// 8713 // value getters 8714 ///////////////////// 8715 8716 /// return integer value 8717 constexpr number_integer_t get_number_integer() const noexcept 8718 { 8719 return value_integer; 8720 } 8721 8722 /// return unsigned integer value 8723 constexpr number_unsigned_t get_number_unsigned() const noexcept 8724 { 8725 return value_unsigned; 8726 } 8727 8728 /// return floating-point value 8729 constexpr number_float_t get_number_float() const noexcept 8730 { 8731 return value_float; 8732 } 8733 8734 /// return current string value (implicitly resets the token; useful only once) 8735 string_t& get_string() 8736 { 8737 return token_buffer; 8738 } 8739 8740 ///////////////////// 8741 // diagnostics 8742 ///////////////////// 8743 8744 /// return position of last read token 8745 constexpr position_t get_position() const noexcept 8746 { 8747 return position; 8748 } 8749 8750 /// return the last read token (for errors only). Will never contain EOF 8751 /// (an arbitrary value that is not a valid char value, often -1), because 8752 /// 255 may legitimately occur. May contain NUL, which should be escaped. 8753 std::string get_token_string() const 8754 { 8755 // escape control characters 8756 std::string result; 8757 for (const auto c : token_string) 8758 { 8759 if (static_cast<unsigned char>(c) <= '\x1F') 8760 { 8761 // escape control characters 8762 std::array<char, 9> cs{{}}; 8763 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8764 result += cs.data(); 8765 } 8766 else 8767 { 8768 // add character as is 8769 result.push_back(static_cast<std::string::value_type>(c)); 8770 } 8771 } 8772 8773 return result; 8774 } 8775 8776 /// return syntax error message 8777 JSON_HEDLEY_RETURNS_NON_NULL 8778 constexpr const char* get_error_message() const noexcept 8779 { 8780 return error_message; 8781 } 8782 8783 ///////////////////// 8784 // actual scanner 8785 ///////////////////// 8786 8787 /*! 8788 @brief skip the UTF-8 byte order mark 8789 @return true iff there is no BOM or the correct BOM has been skipped 8790 */ 8791 bool skip_bom() 8792 { 8793 if (get() == 0xEF) 8794 { 8795 // check if we completely parse the BOM 8796 return get() == 0xBB && get() == 0xBF; 8797 } 8798 8799 // the first character is not the beginning of the BOM; unget it to 8800 // process is later 8801 unget(); 8802 return true; 8803 } 8804 8805 void skip_whitespace() 8806 { 8807 do 8808 { 8809 get(); 8810 } 8811 while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); 8812 } 8813 8814 token_type scan() 8815 { 8816 // initially, skip the BOM 8817 if (position.chars_read_total == 0 && !skip_bom()) 8818 { 8819 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; 8820 return token_type::parse_error; 8821 } 8822 8823 // read next character and ignore whitespace 8824 skip_whitespace(); 8825 8826 // ignore comments 8827 while (ignore_comments && current == '/') 8828 { 8829 if (!scan_comment()) 8830 { 8831 return token_type::parse_error; 8832 } 8833 8834 // skip following whitespace 8835 skip_whitespace(); 8836 } 8837 8838 switch (current) 8839 { 8840 // structural characters 8841 case '[': 8842 return token_type::begin_array; 8843 case ']': 8844 return token_type::end_array; 8845 case '{': 8846 return token_type::begin_object; 8847 case '}': 8848 return token_type::end_object; 8849 case ':': 8850 return token_type::name_separator; 8851 case ',': 8852 return token_type::value_separator; 8853 8854 // literals 8855 case 't': 8856 { 8857 std::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')}}; 8858 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); 8859 } 8860 case 'f': 8861 { 8862 std::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')}}; 8863 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); 8864 } 8865 case 'n': 8866 { 8867 std::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')}}; 8868 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); 8869 } 8870 8871 // string 8872 case '\"': 8873 return scan_string(); 8874 8875 // number 8876 case '-': 8877 case '0': 8878 case '1': 8879 case '2': 8880 case '3': 8881 case '4': 8882 case '5': 8883 case '6': 8884 case '7': 8885 case '8': 8886 case '9': 8887 return scan_number(); 8888 8889 // end of input (the null byte is needed when parsing from 8890 // string literals) 8891 case '\0': 8892 case std::char_traits<char_type>::eof(): 8893 return token_type::end_of_input; 8894 8895 // error 8896 default: 8897 error_message = "invalid literal"; 8898 return token_type::parse_error; 8899 } 8900 } 8901 8902 private: 8903 /// input adapter 8904 InputAdapterType ia; 8905 8906 /// whether comments should be ignored (true) or signaled as errors (false) 8907 const bool ignore_comments = false; 8908 8909 /// the current character 8910 char_int_type current = std::char_traits<char_type>::eof(); 8911 8912 /// whether the next get() call should just return current 8913 bool next_unget = false; 8914 8915 /// the start position of the current token 8916 position_t position {}; 8917 8918 /// raw input token string (for error messages) 8919 std::vector<char_type> token_string {}; 8920 8921 /// buffer for variable-length tokens (numbers, strings) 8922 string_t token_buffer {}; 8923 8924 /// a description of occurred lexer errors 8925 const char* error_message = ""; 8926 8927 // number values 8928 number_integer_t value_integer = 0; 8929 number_unsigned_t value_unsigned = 0; 8930 number_float_t value_float = 0; 8931 8932 /// the decimal point 8933 const char_int_type decimal_point_char = '.'; 8934 }; 8935 8936 } // namespace detail 8937 NLOHMANN_JSON_NAMESPACE_END 8938 8939 // #include <nlohmann/detail/macro_scope.hpp> 8940 8941 // #include <nlohmann/detail/meta/is_sax.hpp> 8942 // __ _____ _____ _____ 8943 // __| | __| | | | JSON for Modern C++ 8944 // | | |__ | | | | | | version 3.11.2 8945 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 8946 // 8947 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 8948 // SPDX-License-Identifier: MIT 8949 8950 8951 8952 #include <cstdint> // size_t 8953 #include <utility> // declval 8954 #include <string> // string 8955 8956 // #include <nlohmann/detail/abi_macros.hpp> 8957 8958 // #include <nlohmann/detail/meta/detected.hpp> 8959 8960 // #include <nlohmann/detail/meta/type_traits.hpp> 8961 8962 8963 NLOHMANN_JSON_NAMESPACE_BEGIN 8964 namespace detail 8965 { 8966 8967 template<typename T> 8968 using null_function_t = decltype(std::declval<T&>().null()); 8969 8970 template<typename T> 8971 using boolean_function_t = 8972 decltype(std::declval<T&>().boolean(std::declval<bool>())); 8973 8974 template<typename T, typename Integer> 8975 using number_integer_function_t = 8976 decltype(std::declval<T&>().number_integer(std::declval<Integer>())); 8977 8978 template<typename T, typename Unsigned> 8979 using number_unsigned_function_t = 8980 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>())); 8981 8982 template<typename T, typename Float, typename String> 8983 using number_float_function_t = decltype(std::declval<T&>().number_float( 8984 std::declval<Float>(), std::declval<const String&>())); 8985 8986 template<typename T, typename String> 8987 using string_function_t = 8988 decltype(std::declval<T&>().string(std::declval<String&>())); 8989 8990 template<typename T, typename Binary> 8991 using binary_function_t = 8992 decltype(std::declval<T&>().binary(std::declval<Binary&>())); 8993 8994 template<typename T> 8995 using start_object_function_t = 8996 decltype(std::declval<T&>().start_object(std::declval<std::size_t>())); 8997 8998 template<typename T, typename String> 8999 using key_function_t = 9000 decltype(std::declval<T&>().key(std::declval<String&>())); 9001 9002 template<typename T> 9003 using end_object_function_t = decltype(std::declval<T&>().end_object()); 9004 9005 template<typename T> 9006 using start_array_function_t = 9007 decltype(std::declval<T&>().start_array(std::declval<std::size_t>())); 9008 9009 template<typename T> 9010 using end_array_function_t = decltype(std::declval<T&>().end_array()); 9011 9012 template<typename T, typename Exception> 9013 using parse_error_function_t = decltype(std::declval<T&>().parse_error( 9014 std::declval<std::size_t>(), std::declval<const std::string&>(), 9015 std::declval<const Exception&>())); 9016 9017 template<typename SAX, typename BasicJsonType> 9018 struct is_sax 9019 { 9020 private: 9021 static_assert(is_basic_json<BasicJsonType>::value, 9022 "BasicJsonType must be of type basic_json<...>"); 9023 9024 using number_integer_t = typename BasicJsonType::number_integer_t; 9025 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9026 using number_float_t = typename BasicJsonType::number_float_t; 9027 using string_t = typename BasicJsonType::string_t; 9028 using binary_t = typename BasicJsonType::binary_t; 9029 using exception_t = typename BasicJsonType::exception; 9030 9031 public: 9032 static constexpr bool value = 9033 is_detected_exact<bool, null_function_t, SAX>::value && 9034 is_detected_exact<bool, boolean_function_t, SAX>::value && 9035 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value && 9036 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value && 9037 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value && 9038 is_detected_exact<bool, string_function_t, SAX, string_t>::value && 9039 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value && 9040 is_detected_exact<bool, start_object_function_t, SAX>::value && 9041 is_detected_exact<bool, key_function_t, SAX, string_t>::value && 9042 is_detected_exact<bool, end_object_function_t, SAX>::value && 9043 is_detected_exact<bool, start_array_function_t, SAX>::value && 9044 is_detected_exact<bool, end_array_function_t, SAX>::value && 9045 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value; 9046 }; 9047 9048 template<typename SAX, typename BasicJsonType> 9049 struct is_sax_static_asserts 9050 { 9051 private: 9052 static_assert(is_basic_json<BasicJsonType>::value, 9053 "BasicJsonType must be of type basic_json<...>"); 9054 9055 using number_integer_t = typename BasicJsonType::number_integer_t; 9056 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9057 using number_float_t = typename BasicJsonType::number_float_t; 9058 using string_t = typename BasicJsonType::string_t; 9059 using binary_t = typename BasicJsonType::binary_t; 9060 using exception_t = typename BasicJsonType::exception; 9061 9062 public: 9063 static_assert(is_detected_exact<bool, null_function_t, SAX>::value, 9064 "Missing/invalid function: bool null()"); 9065 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, 9066 "Missing/invalid function: bool boolean(bool)"); 9067 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, 9068 "Missing/invalid function: bool boolean(bool)"); 9069 static_assert( 9070 is_detected_exact<bool, number_integer_function_t, SAX, 9071 number_integer_t>::value, 9072 "Missing/invalid function: bool number_integer(number_integer_t)"); 9073 static_assert( 9074 is_detected_exact<bool, number_unsigned_function_t, SAX, 9075 number_unsigned_t>::value, 9076 "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); 9077 static_assert(is_detected_exact<bool, number_float_function_t, SAX, 9078 number_float_t, string_t>::value, 9079 "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); 9080 static_assert( 9081 is_detected_exact<bool, string_function_t, SAX, string_t>::value, 9082 "Missing/invalid function: bool string(string_t&)"); 9083 static_assert( 9084 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value, 9085 "Missing/invalid function: bool binary(binary_t&)"); 9086 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value, 9087 "Missing/invalid function: bool start_object(std::size_t)"); 9088 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value, 9089 "Missing/invalid function: bool key(string_t&)"); 9090 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value, 9091 "Missing/invalid function: bool end_object()"); 9092 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value, 9093 "Missing/invalid function: bool start_array(std::size_t)"); 9094 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value, 9095 "Missing/invalid function: bool end_array()"); 9096 static_assert( 9097 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value, 9098 "Missing/invalid function: bool parse_error(std::size_t, const " 9099 "std::string&, const exception&)"); 9100 }; 9101 9102 } // namespace detail 9103 NLOHMANN_JSON_NAMESPACE_END 9104 9105 // #include <nlohmann/detail/meta/type_traits.hpp> 9106 9107 // #include <nlohmann/detail/string_concat.hpp> 9108 9109 // #include <nlohmann/detail/value_t.hpp> 9110 9111 9112 NLOHMANN_JSON_NAMESPACE_BEGIN 9113 namespace detail 9114 { 9115 9116 /// how to treat CBOR tags 9117 enum class cbor_tag_handler_t 9118 { 9119 error, ///< throw a parse_error exception in case of a tag 9120 ignore, ///< ignore tags 9121 store ///< store tags as binary type 9122 }; 9123 9124 /*! 9125 @brief determine system byte order 9126 9127 @return true if and only if system's byte order is little endian 9128 9129 @note from https://stackoverflow.com/a/1001328/266378 9130 */ 9131 static inline bool little_endianness(int num = 1) noexcept 9132 { 9133 return *reinterpret_cast<char*>(&num) == 1; 9134 } 9135 9136 9137 /////////////////// 9138 // binary reader // 9139 /////////////////// 9140 9141 /*! 9142 @brief deserialization of CBOR, MessagePack, and UBJSON values 9143 */ 9144 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>> 9145 class binary_reader 9146 { 9147 using number_integer_t = typename BasicJsonType::number_integer_t; 9148 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9149 using number_float_t = typename BasicJsonType::number_float_t; 9150 using string_t = typename BasicJsonType::string_t; 9151 using binary_t = typename BasicJsonType::binary_t; 9152 using json_sax_t = SAX; 9153 using char_type = typename InputAdapterType::char_type; 9154 using char_int_type = typename std::char_traits<char_type>::int_type; 9155 9156 public: 9157 /*! 9158 @brief create a binary reader 9159 9160 @param[in] adapter input adapter to read from 9161 */ 9162 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) 9163 { 9164 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; 9165 } 9166 9167 // make class move-only 9168 binary_reader(const binary_reader&) = delete; 9169 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9170 binary_reader& operator=(const binary_reader&) = delete; 9171 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9172 ~binary_reader() = default; 9173 9174 /*! 9175 @param[in] format the binary format to parse 9176 @param[in] sax_ a SAX event processor 9177 @param[in] strict whether to expect the input to be consumed completed 9178 @param[in] tag_handler how to treat CBOR tags 9179 9180 @return whether parsing was successful 9181 */ 9182 JSON_HEDLEY_NON_NULL(3) 9183 bool sax_parse(const input_format_t format, 9184 json_sax_t* sax_, 9185 const bool strict = true, 9186 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 9187 { 9188 sax = sax_; 9189 bool result = false; 9190 9191 switch (format) 9192 { 9193 case input_format_t::bson: 9194 result = parse_bson_internal(); 9195 break; 9196 9197 case input_format_t::cbor: 9198 result = parse_cbor_internal(true, tag_handler); 9199 break; 9200 9201 case input_format_t::msgpack: 9202 result = parse_msgpack_internal(); 9203 break; 9204 9205 case input_format_t::ubjson: 9206 case input_format_t::bjdata: 9207 result = parse_ubjson_internal(); 9208 break; 9209 9210 case input_format_t::json: // LCOV_EXCL_LINE 9211 default: // LCOV_EXCL_LINE 9212 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 9213 } 9214 9215 // strict mode: next byte must be EOF 9216 if (result && strict) 9217 { 9218 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) 9219 { 9220 get_ignore_noop(); 9221 } 9222 else 9223 { 9224 get(); 9225 } 9226 9227 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof())) 9228 { 9229 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, 9230 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); 9231 } 9232 } 9233 9234 return result; 9235 } 9236 9237 private: 9238 ////////// 9239 // BSON // 9240 ////////// 9241 9242 /*! 9243 @brief Reads in a BSON-object and passes it to the SAX-parser. 9244 @return whether a valid BSON-value was passed to the SAX parser 9245 */ 9246 bool parse_bson_internal() 9247 { 9248 std::int32_t document_size{}; 9249 get_number<std::int32_t, true>(input_format_t::bson, document_size); 9250 9251 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 9252 { 9253 return false; 9254 } 9255 9256 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) 9257 { 9258 return false; 9259 } 9260 9261 return sax->end_object(); 9262 } 9263 9264 /*! 9265 @brief Parses a C-style string from the BSON input. 9266 @param[in,out] result A reference to the string variable where the read 9267 string is to be stored. 9268 @return `true` if the \x00-byte indicating the end of the string was 9269 encountered before the EOF; false` indicates an unexpected EOF. 9270 */ 9271 bool get_bson_cstr(string_t& result) 9272 { 9273 auto out = std::back_inserter(result); 9274 while (true) 9275 { 9276 get(); 9277 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) 9278 { 9279 return false; 9280 } 9281 if (current == 0x00) 9282 { 9283 return true; 9284 } 9285 *out++ = static_cast<typename string_t::value_type>(current); 9286 } 9287 } 9288 9289 /*! 9290 @brief Parses a zero-terminated string of length @a len from the BSON 9291 input. 9292 @param[in] len The length (including the zero-byte at the end) of the 9293 string to be read. 9294 @param[in,out] result A reference to the string variable where the read 9295 string is to be stored. 9296 @tparam NumberType The type of the length @a len 9297 @pre len >= 1 9298 @return `true` if the string was successfully parsed 9299 */ 9300 template<typename NumberType> 9301 bool get_bson_string(const NumberType len, string_t& result) 9302 { 9303 if (JSON_HEDLEY_UNLIKELY(len < 1)) 9304 { 9305 auto last_token = get_token_string(); 9306 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9307 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); 9308 } 9309 9310 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof(); 9311 } 9312 9313 /*! 9314 @brief Parses a byte array input of length @a len from the BSON input. 9315 @param[in] len The length of the byte array to be read. 9316 @param[in,out] result A reference to the binary variable where the read 9317 array is to be stored. 9318 @tparam NumberType The type of the length @a len 9319 @pre len >= 0 9320 @return `true` if the byte array was successfully parsed 9321 */ 9322 template<typename NumberType> 9323 bool get_bson_binary(const NumberType len, binary_t& result) 9324 { 9325 if (JSON_HEDLEY_UNLIKELY(len < 0)) 9326 { 9327 auto last_token = get_token_string(); 9328 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9329 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); 9330 } 9331 9332 // All BSON binary values have a subtype 9333 std::uint8_t subtype{}; 9334 get_number<std::uint8_t>(input_format_t::bson, subtype); 9335 result.set_subtype(subtype); 9336 9337 return get_binary(input_format_t::bson, len, result); 9338 } 9339 9340 /*! 9341 @brief Read a BSON document element of the given @a element_type. 9342 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html 9343 @param[in] element_type_parse_position The position in the input stream, 9344 where the `element_type` was read. 9345 @warning Not all BSON element types are supported yet. An unsupported 9346 @a element_type will give rise to a parse_error.114: 9347 Unsupported BSON record type 0x... 9348 @return whether a valid BSON-object/array was passed to the SAX parser 9349 */ 9350 bool parse_bson_element_internal(const char_int_type element_type, 9351 const std::size_t element_type_parse_position) 9352 { 9353 switch (element_type) 9354 { 9355 case 0x01: // double 9356 { 9357 double number{}; 9358 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), ""); 9359 } 9360 9361 case 0x02: // string 9362 { 9363 std::int32_t len{}; 9364 string_t value; 9365 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); 9366 } 9367 9368 case 0x03: // object 9369 { 9370 return parse_bson_internal(); 9371 } 9372 9373 case 0x04: // array 9374 { 9375 return parse_bson_array(); 9376 } 9377 9378 case 0x05: // binary 9379 { 9380 std::int32_t len{}; 9381 binary_t value; 9382 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); 9383 } 9384 9385 case 0x08: // boolean 9386 { 9387 return sax->boolean(get() != 0); 9388 } 9389 9390 case 0x0A: // null 9391 { 9392 return sax->null(); 9393 } 9394 9395 case 0x10: // int32 9396 { 9397 std::int32_t value{}; 9398 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value); 9399 } 9400 9401 case 0x12: // int64 9402 { 9403 std::int64_t value{}; 9404 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value); 9405 } 9406 9407 default: // anything else not supported (yet) 9408 { 9409 std::array<char, 3> cr{{}}; 9410 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 9411 const std::string cr_str{cr.data()}; 9412 return sax->parse_error(element_type_parse_position, cr_str, 9413 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); 9414 } 9415 } 9416 } 9417 9418 /*! 9419 @brief Read a BSON element list (as specified in the BSON-spec) 9420 9421 The same binary layout is used for objects and arrays, hence it must be 9422 indicated with the argument @a is_array which one is expected 9423 (true --> array, false --> object). 9424 9425 @param[in] is_array Determines if the element list being read is to be 9426 treated as an object (@a is_array == false), or as an 9427 array (@a is_array == true). 9428 @return whether a valid BSON-object/array was passed to the SAX parser 9429 */ 9430 bool parse_bson_element_list(const bool is_array) 9431 { 9432 string_t key; 9433 9434 while (auto element_type = get()) 9435 { 9436 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) 9437 { 9438 return false; 9439 } 9440 9441 const std::size_t element_type_parse_position = chars_read; 9442 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) 9443 { 9444 return false; 9445 } 9446 9447 if (!is_array && !sax->key(key)) 9448 { 9449 return false; 9450 } 9451 9452 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) 9453 { 9454 return false; 9455 } 9456 9457 // get_bson_cstr only appends 9458 key.clear(); 9459 } 9460 9461 return true; 9462 } 9463 9464 /*! 9465 @brief Reads an array from the BSON input and passes it to the SAX-parser. 9466 @return whether a valid BSON-array was passed to the SAX parser 9467 */ 9468 bool parse_bson_array() 9469 { 9470 std::int32_t document_size{}; 9471 get_number<std::int32_t, true>(input_format_t::bson, document_size); 9472 9473 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 9474 { 9475 return false; 9476 } 9477 9478 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) 9479 { 9480 return false; 9481 } 9482 9483 return sax->end_array(); 9484 } 9485 9486 ////////// 9487 // CBOR // 9488 ////////// 9489 9490 /*! 9491 @param[in] get_char whether a new character should be retrieved from the 9492 input (true) or whether the last read character should 9493 be considered instead (false) 9494 @param[in] tag_handler how CBOR tags should be treated 9495 9496 @return whether a valid CBOR value was passed to the SAX parser 9497 */ 9498 bool parse_cbor_internal(const bool get_char, 9499 const cbor_tag_handler_t tag_handler) 9500 { 9501 switch (get_char ? get() : current) 9502 { 9503 // EOF 9504 case std::char_traits<char_type>::eof(): 9505 return unexpect_eof(input_format_t::cbor, "value"); 9506 9507 // Integer 0x00..0x17 (0..23) 9508 case 0x00: 9509 case 0x01: 9510 case 0x02: 9511 case 0x03: 9512 case 0x04: 9513 case 0x05: 9514 case 0x06: 9515 case 0x07: 9516 case 0x08: 9517 case 0x09: 9518 case 0x0A: 9519 case 0x0B: 9520 case 0x0C: 9521 case 0x0D: 9522 case 0x0E: 9523 case 0x0F: 9524 case 0x10: 9525 case 0x11: 9526 case 0x12: 9527 case 0x13: 9528 case 0x14: 9529 case 0x15: 9530 case 0x16: 9531 case 0x17: 9532 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); 9533 9534 case 0x18: // Unsigned integer (one-byte uint8_t follows) 9535 { 9536 std::uint8_t number{}; 9537 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9538 } 9539 9540 case 0x19: // Unsigned integer (two-byte uint16_t follows) 9541 { 9542 std::uint16_t number{}; 9543 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9544 } 9545 9546 case 0x1A: // Unsigned integer (four-byte uint32_t follows) 9547 { 9548 std::uint32_t number{}; 9549 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9550 } 9551 9552 case 0x1B: // Unsigned integer (eight-byte uint64_t follows) 9553 { 9554 std::uint64_t number{}; 9555 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9556 } 9557 9558 // Negative integer -1-0x00..-1-0x17 (-1..-24) 9559 case 0x20: 9560 case 0x21: 9561 case 0x22: 9562 case 0x23: 9563 case 0x24: 9564 case 0x25: 9565 case 0x26: 9566 case 0x27: 9567 case 0x28: 9568 case 0x29: 9569 case 0x2A: 9570 case 0x2B: 9571 case 0x2C: 9572 case 0x2D: 9573 case 0x2E: 9574 case 0x2F: 9575 case 0x30: 9576 case 0x31: 9577 case 0x32: 9578 case 0x33: 9579 case 0x34: 9580 case 0x35: 9581 case 0x36: 9582 case 0x37: 9583 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current)); 9584 9585 case 0x38: // Negative integer (one-byte uint8_t follows) 9586 { 9587 std::uint8_t number{}; 9588 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9589 } 9590 9591 case 0x39: // Negative integer -1-n (two-byte uint16_t follows) 9592 { 9593 std::uint16_t number{}; 9594 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9595 } 9596 9597 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) 9598 { 9599 std::uint32_t number{}; 9600 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9601 } 9602 9603 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) 9604 { 9605 std::uint64_t number{}; 9606 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) 9607 - static_cast<number_integer_t>(number)); 9608 } 9609 9610 // Binary data (0x00..0x17 bytes follow) 9611 case 0x40: 9612 case 0x41: 9613 case 0x42: 9614 case 0x43: 9615 case 0x44: 9616 case 0x45: 9617 case 0x46: 9618 case 0x47: 9619 case 0x48: 9620 case 0x49: 9621 case 0x4A: 9622 case 0x4B: 9623 case 0x4C: 9624 case 0x4D: 9625 case 0x4E: 9626 case 0x4F: 9627 case 0x50: 9628 case 0x51: 9629 case 0x52: 9630 case 0x53: 9631 case 0x54: 9632 case 0x55: 9633 case 0x56: 9634 case 0x57: 9635 case 0x58: // Binary data (one-byte uint8_t for n follows) 9636 case 0x59: // Binary data (two-byte uint16_t for n follow) 9637 case 0x5A: // Binary data (four-byte uint32_t for n follow) 9638 case 0x5B: // Binary data (eight-byte uint64_t for n follow) 9639 case 0x5F: // Binary data (indefinite length) 9640 { 9641 binary_t b; 9642 return get_cbor_binary(b) && sax->binary(b); 9643 } 9644 9645 // UTF-8 string (0x00..0x17 bytes follow) 9646 case 0x60: 9647 case 0x61: 9648 case 0x62: 9649 case 0x63: 9650 case 0x64: 9651 case 0x65: 9652 case 0x66: 9653 case 0x67: 9654 case 0x68: 9655 case 0x69: 9656 case 0x6A: 9657 case 0x6B: 9658 case 0x6C: 9659 case 0x6D: 9660 case 0x6E: 9661 case 0x6F: 9662 case 0x70: 9663 case 0x71: 9664 case 0x72: 9665 case 0x73: 9666 case 0x74: 9667 case 0x75: 9668 case 0x76: 9669 case 0x77: 9670 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) 9671 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) 9672 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) 9673 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) 9674 case 0x7F: // UTF-8 string (indefinite length) 9675 { 9676 string_t s; 9677 return get_cbor_string(s) && sax->string(s); 9678 } 9679 9680 // array (0x00..0x17 data items follow) 9681 case 0x80: 9682 case 0x81: 9683 case 0x82: 9684 case 0x83: 9685 case 0x84: 9686 case 0x85: 9687 case 0x86: 9688 case 0x87: 9689 case 0x88: 9690 case 0x89: 9691 case 0x8A: 9692 case 0x8B: 9693 case 0x8C: 9694 case 0x8D: 9695 case 0x8E: 9696 case 0x8F: 9697 case 0x90: 9698 case 0x91: 9699 case 0x92: 9700 case 0x93: 9701 case 0x94: 9702 case 0x95: 9703 case 0x96: 9704 case 0x97: 9705 return get_cbor_array( 9706 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); 9707 9708 case 0x98: // array (one-byte uint8_t for n follows) 9709 { 9710 std::uint8_t len{}; 9711 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); 9712 } 9713 9714 case 0x99: // array (two-byte uint16_t for n follow) 9715 { 9716 std::uint16_t len{}; 9717 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); 9718 } 9719 9720 case 0x9A: // array (four-byte uint32_t for n follow) 9721 { 9722 std::uint32_t len{}; 9723 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); 9724 } 9725 9726 case 0x9B: // array (eight-byte uint64_t for n follow) 9727 { 9728 std::uint64_t len{}; 9729 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); 9730 } 9731 9732 case 0x9F: // array (indefinite length) 9733 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler); 9734 9735 // map (0x00..0x17 pairs of data items follow) 9736 case 0xA0: 9737 case 0xA1: 9738 case 0xA2: 9739 case 0xA3: 9740 case 0xA4: 9741 case 0xA5: 9742 case 0xA6: 9743 case 0xA7: 9744 case 0xA8: 9745 case 0xA9: 9746 case 0xAA: 9747 case 0xAB: 9748 case 0xAC: 9749 case 0xAD: 9750 case 0xAE: 9751 case 0xAF: 9752 case 0xB0: 9753 case 0xB1: 9754 case 0xB2: 9755 case 0xB3: 9756 case 0xB4: 9757 case 0xB5: 9758 case 0xB6: 9759 case 0xB7: 9760 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); 9761 9762 case 0xB8: // map (one-byte uint8_t for n follows) 9763 { 9764 std::uint8_t len{}; 9765 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); 9766 } 9767 9768 case 0xB9: // map (two-byte uint16_t for n follow) 9769 { 9770 std::uint16_t len{}; 9771 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); 9772 } 9773 9774 case 0xBA: // map (four-byte uint32_t for n follow) 9775 { 9776 std::uint32_t len{}; 9777 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); 9778 } 9779 9780 case 0xBB: // map (eight-byte uint64_t for n follow) 9781 { 9782 std::uint64_t len{}; 9783 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); 9784 } 9785 9786 case 0xBF: // map (indefinite length) 9787 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler); 9788 9789 case 0xC6: // tagged item 9790 case 0xC7: 9791 case 0xC8: 9792 case 0xC9: 9793 case 0xCA: 9794 case 0xCB: 9795 case 0xCC: 9796 case 0xCD: 9797 case 0xCE: 9798 case 0xCF: 9799 case 0xD0: 9800 case 0xD1: 9801 case 0xD2: 9802 case 0xD3: 9803 case 0xD4: 9804 case 0xD8: // tagged item (1 bytes follow) 9805 case 0xD9: // tagged item (2 bytes follow) 9806 case 0xDA: // tagged item (4 bytes follow) 9807 case 0xDB: // tagged item (8 bytes follow) 9808 { 9809 switch (tag_handler) 9810 { 9811 case cbor_tag_handler_t::error: 9812 { 9813 auto last_token = get_token_string(); 9814 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9815 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); 9816 } 9817 9818 case cbor_tag_handler_t::ignore: 9819 { 9820 // ignore binary subtype 9821 switch (current) 9822 { 9823 case 0xD8: 9824 { 9825 std::uint8_t subtype_to_ignore{}; 9826 get_number(input_format_t::cbor, subtype_to_ignore); 9827 break; 9828 } 9829 case 0xD9: 9830 { 9831 std::uint16_t subtype_to_ignore{}; 9832 get_number(input_format_t::cbor, subtype_to_ignore); 9833 break; 9834 } 9835 case 0xDA: 9836 { 9837 std::uint32_t subtype_to_ignore{}; 9838 get_number(input_format_t::cbor, subtype_to_ignore); 9839 break; 9840 } 9841 case 0xDB: 9842 { 9843 std::uint64_t subtype_to_ignore{}; 9844 get_number(input_format_t::cbor, subtype_to_ignore); 9845 break; 9846 } 9847 default: 9848 break; 9849 } 9850 return parse_cbor_internal(true, tag_handler); 9851 } 9852 9853 case cbor_tag_handler_t::store: 9854 { 9855 binary_t b; 9856 // use binary subtype and store in binary container 9857 switch (current) 9858 { 9859 case 0xD8: 9860 { 9861 std::uint8_t subtype{}; 9862 get_number(input_format_t::cbor, subtype); 9863 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9864 break; 9865 } 9866 case 0xD9: 9867 { 9868 std::uint16_t subtype{}; 9869 get_number(input_format_t::cbor, subtype); 9870 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9871 break; 9872 } 9873 case 0xDA: 9874 { 9875 std::uint32_t subtype{}; 9876 get_number(input_format_t::cbor, subtype); 9877 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9878 break; 9879 } 9880 case 0xDB: 9881 { 9882 std::uint64_t subtype{}; 9883 get_number(input_format_t::cbor, subtype); 9884 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9885 break; 9886 } 9887 default: 9888 return parse_cbor_internal(true, tag_handler); 9889 } 9890 get(); 9891 return get_cbor_binary(b) && sax->binary(b); 9892 } 9893 9894 default: // LCOV_EXCL_LINE 9895 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 9896 return false; // LCOV_EXCL_LINE 9897 } 9898 } 9899 9900 case 0xF4: // false 9901 return sax->boolean(false); 9902 9903 case 0xF5: // true 9904 return sax->boolean(true); 9905 9906 case 0xF6: // null 9907 return sax->null(); 9908 9909 case 0xF9: // Half-Precision Float (two-byte IEEE 754) 9910 { 9911 const auto byte1_raw = get(); 9912 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) 9913 { 9914 return false; 9915 } 9916 const auto byte2_raw = get(); 9917 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) 9918 { 9919 return false; 9920 } 9921 9922 const auto byte1 = static_cast<unsigned char>(byte1_raw); 9923 const auto byte2 = static_cast<unsigned char>(byte2_raw); 9924 9925 // code from RFC 7049, Appendix D, Figure 3: 9926 // As half-precision floating-point numbers were only added 9927 // to IEEE 754 in 2008, today's programming platforms often 9928 // still only have limited support for them. It is very 9929 // easy to include at least decoding support for them even 9930 // without such support. An example of a small decoder for 9931 // half-precision floating-point numbers in the C language 9932 // is shown in Fig. 3. 9933 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2); 9934 const double val = [&half] 9935 { 9936 const int exp = (half >> 10u) & 0x1Fu; 9937 const unsigned int mant = half & 0x3FFu; 9938 JSON_ASSERT(0 <= exp&& exp <= 32); 9939 JSON_ASSERT(mant <= 1024); 9940 switch (exp) 9941 { 9942 case 0: 9943 return std::ldexp(mant, -24); 9944 case 31: 9945 return (mant == 0) 9946 ? std::numeric_limits<double>::infinity() 9947 : std::numeric_limits<double>::quiet_NaN(); 9948 default: 9949 return std::ldexp(mant + 1024, exp - 25); 9950 } 9951 }(); 9952 return sax->number_float((half & 0x8000u) != 0 9953 ? static_cast<number_float_t>(-val) 9954 : static_cast<number_float_t>(val), ""); 9955 } 9956 9957 case 0xFA: // Single-Precision Float (four-byte IEEE 754) 9958 { 9959 float number{}; 9960 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); 9961 } 9962 9963 case 0xFB: // Double-Precision Float (eight-byte IEEE 754) 9964 { 9965 double number{}; 9966 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); 9967 } 9968 9969 default: // anything else (0xFF is handled inside the other types) 9970 { 9971 auto last_token = get_token_string(); 9972 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9973 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); 9974 } 9975 } 9976 } 9977 9978 /*! 9979 @brief reads a CBOR string 9980 9981 This function first reads starting bytes to determine the expected 9982 string length and then copies this number of bytes into a string. 9983 Additionally, CBOR's strings with indefinite lengths are supported. 9984 9985 @param[out] result created string 9986 9987 @return whether string creation completed 9988 */ 9989 bool get_cbor_string(string_t& result) 9990 { 9991 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) 9992 { 9993 return false; 9994 } 9995 9996 switch (current) 9997 { 9998 // UTF-8 string (0x00..0x17 bytes follow) 9999 case 0x60: 10000 case 0x61: 10001 case 0x62: 10002 case 0x63: 10003 case 0x64: 10004 case 0x65: 10005 case 0x66: 10006 case 0x67: 10007 case 0x68: 10008 case 0x69: 10009 case 0x6A: 10010 case 0x6B: 10011 case 0x6C: 10012 case 0x6D: 10013 case 0x6E: 10014 case 0x6F: 10015 case 0x70: 10016 case 0x71: 10017 case 0x72: 10018 case 0x73: 10019 case 0x74: 10020 case 0x75: 10021 case 0x76: 10022 case 0x77: 10023 { 10024 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); 10025 } 10026 10027 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) 10028 { 10029 std::uint8_t len{}; 10030 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10031 } 10032 10033 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) 10034 { 10035 std::uint16_t len{}; 10036 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10037 } 10038 10039 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) 10040 { 10041 std::uint32_t len{}; 10042 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10043 } 10044 10045 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) 10046 { 10047 std::uint64_t len{}; 10048 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10049 } 10050 10051 case 0x7F: // UTF-8 string (indefinite length) 10052 { 10053 while (get() != 0xFF) 10054 { 10055 string_t chunk; 10056 if (!get_cbor_string(chunk)) 10057 { 10058 return false; 10059 } 10060 result.append(chunk); 10061 } 10062 return true; 10063 } 10064 10065 default: 10066 { 10067 auto last_token = get_token_string(); 10068 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10069 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); 10070 } 10071 } 10072 } 10073 10074 /*! 10075 @brief reads a CBOR byte array 10076 10077 This function first reads starting bytes to determine the expected 10078 byte array length and then copies this number of bytes into the byte array. 10079 Additionally, CBOR's byte arrays with indefinite lengths are supported. 10080 10081 @param[out] result created byte array 10082 10083 @return whether byte array creation completed 10084 */ 10085 bool get_cbor_binary(binary_t& result) 10086 { 10087 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) 10088 { 10089 return false; 10090 } 10091 10092 switch (current) 10093 { 10094 // Binary data (0x00..0x17 bytes follow) 10095 case 0x40: 10096 case 0x41: 10097 case 0x42: 10098 case 0x43: 10099 case 0x44: 10100 case 0x45: 10101 case 0x46: 10102 case 0x47: 10103 case 0x48: 10104 case 0x49: 10105 case 0x4A: 10106 case 0x4B: 10107 case 0x4C: 10108 case 0x4D: 10109 case 0x4E: 10110 case 0x4F: 10111 case 0x50: 10112 case 0x51: 10113 case 0x52: 10114 case 0x53: 10115 case 0x54: 10116 case 0x55: 10117 case 0x56: 10118 case 0x57: 10119 { 10120 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); 10121 } 10122 10123 case 0x58: // Binary data (one-byte uint8_t for n follows) 10124 { 10125 std::uint8_t len{}; 10126 return get_number(input_format_t::cbor, len) && 10127 get_binary(input_format_t::cbor, len, result); 10128 } 10129 10130 case 0x59: // Binary data (two-byte uint16_t for n follow) 10131 { 10132 std::uint16_t len{}; 10133 return get_number(input_format_t::cbor, len) && 10134 get_binary(input_format_t::cbor, len, result); 10135 } 10136 10137 case 0x5A: // Binary data (four-byte uint32_t for n follow) 10138 { 10139 std::uint32_t len{}; 10140 return get_number(input_format_t::cbor, len) && 10141 get_binary(input_format_t::cbor, len, result); 10142 } 10143 10144 case 0x5B: // Binary data (eight-byte uint64_t for n follow) 10145 { 10146 std::uint64_t len{}; 10147 return get_number(input_format_t::cbor, len) && 10148 get_binary(input_format_t::cbor, len, result); 10149 } 10150 10151 case 0x5F: // Binary data (indefinite length) 10152 { 10153 while (get() != 0xFF) 10154 { 10155 binary_t chunk; 10156 if (!get_cbor_binary(chunk)) 10157 { 10158 return false; 10159 } 10160 result.insert(result.end(), chunk.begin(), chunk.end()); 10161 } 10162 return true; 10163 } 10164 10165 default: 10166 { 10167 auto last_token = get_token_string(); 10168 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10169 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); 10170 } 10171 } 10172 } 10173 10174 /*! 10175 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an 10176 array of indefinite size 10177 @param[in] tag_handler how CBOR tags should be treated 10178 @return whether array creation completed 10179 */ 10180 bool get_cbor_array(const std::size_t len, 10181 const cbor_tag_handler_t tag_handler) 10182 { 10183 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) 10184 { 10185 return false; 10186 } 10187 10188 if (len != static_cast<std::size_t>(-1)) 10189 { 10190 for (std::size_t i = 0; i < len; ++i) 10191 { 10192 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10193 { 10194 return false; 10195 } 10196 } 10197 } 10198 else 10199 { 10200 while (get() != 0xFF) 10201 { 10202 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) 10203 { 10204 return false; 10205 } 10206 } 10207 } 10208 10209 return sax->end_array(); 10210 } 10211 10212 /*! 10213 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an 10214 object of indefinite size 10215 @param[in] tag_handler how CBOR tags should be treated 10216 @return whether object creation completed 10217 */ 10218 bool get_cbor_object(const std::size_t len, 10219 const cbor_tag_handler_t tag_handler) 10220 { 10221 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) 10222 { 10223 return false; 10224 } 10225 10226 if (len != 0) 10227 { 10228 string_t key; 10229 if (len != static_cast<std::size_t>(-1)) 10230 { 10231 for (std::size_t i = 0; i < len; ++i) 10232 { 10233 get(); 10234 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) 10235 { 10236 return false; 10237 } 10238 10239 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10240 { 10241 return false; 10242 } 10243 key.clear(); 10244 } 10245 } 10246 else 10247 { 10248 while (get() != 0xFF) 10249 { 10250 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) 10251 { 10252 return false; 10253 } 10254 10255 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10256 { 10257 return false; 10258 } 10259 key.clear(); 10260 } 10261 } 10262 } 10263 10264 return sax->end_object(); 10265 } 10266 10267 ///////////// 10268 // MsgPack // 10269 ///////////// 10270 10271 /*! 10272 @return whether a valid MessagePack value was passed to the SAX parser 10273 */ 10274 bool parse_msgpack_internal() 10275 { 10276 switch (get()) 10277 { 10278 // EOF 10279 case std::char_traits<char_type>::eof(): 10280 return unexpect_eof(input_format_t::msgpack, "value"); 10281 10282 // positive fixint 10283 case 0x00: 10284 case 0x01: 10285 case 0x02: 10286 case 0x03: 10287 case 0x04: 10288 case 0x05: 10289 case 0x06: 10290 case 0x07: 10291 case 0x08: 10292 case 0x09: 10293 case 0x0A: 10294 case 0x0B: 10295 case 0x0C: 10296 case 0x0D: 10297 case 0x0E: 10298 case 0x0F: 10299 case 0x10: 10300 case 0x11: 10301 case 0x12: 10302 case 0x13: 10303 case 0x14: 10304 case 0x15: 10305 case 0x16: 10306 case 0x17: 10307 case 0x18: 10308 case 0x19: 10309 case 0x1A: 10310 case 0x1B: 10311 case 0x1C: 10312 case 0x1D: 10313 case 0x1E: 10314 case 0x1F: 10315 case 0x20: 10316 case 0x21: 10317 case 0x22: 10318 case 0x23: 10319 case 0x24: 10320 case 0x25: 10321 case 0x26: 10322 case 0x27: 10323 case 0x28: 10324 case 0x29: 10325 case 0x2A: 10326 case 0x2B: 10327 case 0x2C: 10328 case 0x2D: 10329 case 0x2E: 10330 case 0x2F: 10331 case 0x30: 10332 case 0x31: 10333 case 0x32: 10334 case 0x33: 10335 case 0x34: 10336 case 0x35: 10337 case 0x36: 10338 case 0x37: 10339 case 0x38: 10340 case 0x39: 10341 case 0x3A: 10342 case 0x3B: 10343 case 0x3C: 10344 case 0x3D: 10345 case 0x3E: 10346 case 0x3F: 10347 case 0x40: 10348 case 0x41: 10349 case 0x42: 10350 case 0x43: 10351 case 0x44: 10352 case 0x45: 10353 case 0x46: 10354 case 0x47: 10355 case 0x48: 10356 case 0x49: 10357 case 0x4A: 10358 case 0x4B: 10359 case 0x4C: 10360 case 0x4D: 10361 case 0x4E: 10362 case 0x4F: 10363 case 0x50: 10364 case 0x51: 10365 case 0x52: 10366 case 0x53: 10367 case 0x54: 10368 case 0x55: 10369 case 0x56: 10370 case 0x57: 10371 case 0x58: 10372 case 0x59: 10373 case 0x5A: 10374 case 0x5B: 10375 case 0x5C: 10376 case 0x5D: 10377 case 0x5E: 10378 case 0x5F: 10379 case 0x60: 10380 case 0x61: 10381 case 0x62: 10382 case 0x63: 10383 case 0x64: 10384 case 0x65: 10385 case 0x66: 10386 case 0x67: 10387 case 0x68: 10388 case 0x69: 10389 case 0x6A: 10390 case 0x6B: 10391 case 0x6C: 10392 case 0x6D: 10393 case 0x6E: 10394 case 0x6F: 10395 case 0x70: 10396 case 0x71: 10397 case 0x72: 10398 case 0x73: 10399 case 0x74: 10400 case 0x75: 10401 case 0x76: 10402 case 0x77: 10403 case 0x78: 10404 case 0x79: 10405 case 0x7A: 10406 case 0x7B: 10407 case 0x7C: 10408 case 0x7D: 10409 case 0x7E: 10410 case 0x7F: 10411 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); 10412 10413 // fixmap 10414 case 0x80: 10415 case 0x81: 10416 case 0x82: 10417 case 0x83: 10418 case 0x84: 10419 case 0x85: 10420 case 0x86: 10421 case 0x87: 10422 case 0x88: 10423 case 0x89: 10424 case 0x8A: 10425 case 0x8B: 10426 case 0x8C: 10427 case 0x8D: 10428 case 0x8E: 10429 case 0x8F: 10430 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); 10431 10432 // fixarray 10433 case 0x90: 10434 case 0x91: 10435 case 0x92: 10436 case 0x93: 10437 case 0x94: 10438 case 0x95: 10439 case 0x96: 10440 case 0x97: 10441 case 0x98: 10442 case 0x99: 10443 case 0x9A: 10444 case 0x9B: 10445 case 0x9C: 10446 case 0x9D: 10447 case 0x9E: 10448 case 0x9F: 10449 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); 10450 10451 // fixstr 10452 case 0xA0: 10453 case 0xA1: 10454 case 0xA2: 10455 case 0xA3: 10456 case 0xA4: 10457 case 0xA5: 10458 case 0xA6: 10459 case 0xA7: 10460 case 0xA8: 10461 case 0xA9: 10462 case 0xAA: 10463 case 0xAB: 10464 case 0xAC: 10465 case 0xAD: 10466 case 0xAE: 10467 case 0xAF: 10468 case 0xB0: 10469 case 0xB1: 10470 case 0xB2: 10471 case 0xB3: 10472 case 0xB4: 10473 case 0xB5: 10474 case 0xB6: 10475 case 0xB7: 10476 case 0xB8: 10477 case 0xB9: 10478 case 0xBA: 10479 case 0xBB: 10480 case 0xBC: 10481 case 0xBD: 10482 case 0xBE: 10483 case 0xBF: 10484 case 0xD9: // str 8 10485 case 0xDA: // str 16 10486 case 0xDB: // str 32 10487 { 10488 string_t s; 10489 return get_msgpack_string(s) && sax->string(s); 10490 } 10491 10492 case 0xC0: // nil 10493 return sax->null(); 10494 10495 case 0xC2: // false 10496 return sax->boolean(false); 10497 10498 case 0xC3: // true 10499 return sax->boolean(true); 10500 10501 case 0xC4: // bin 8 10502 case 0xC5: // bin 16 10503 case 0xC6: // bin 32 10504 case 0xC7: // ext 8 10505 case 0xC8: // ext 16 10506 case 0xC9: // ext 32 10507 case 0xD4: // fixext 1 10508 case 0xD5: // fixext 2 10509 case 0xD6: // fixext 4 10510 case 0xD7: // fixext 8 10511 case 0xD8: // fixext 16 10512 { 10513 binary_t b; 10514 return get_msgpack_binary(b) && sax->binary(b); 10515 } 10516 10517 case 0xCA: // float 32 10518 { 10519 float number{}; 10520 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10521 } 10522 10523 case 0xCB: // float 64 10524 { 10525 double number{}; 10526 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10527 } 10528 10529 case 0xCC: // uint 8 10530 { 10531 std::uint8_t number{}; 10532 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10533 } 10534 10535 case 0xCD: // uint 16 10536 { 10537 std::uint16_t number{}; 10538 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10539 } 10540 10541 case 0xCE: // uint 32 10542 { 10543 std::uint32_t number{}; 10544 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10545 } 10546 10547 case 0xCF: // uint 64 10548 { 10549 std::uint64_t number{}; 10550 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10551 } 10552 10553 case 0xD0: // int 8 10554 { 10555 std::int8_t number{}; 10556 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10557 } 10558 10559 case 0xD1: // int 16 10560 { 10561 std::int16_t number{}; 10562 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10563 } 10564 10565 case 0xD2: // int 32 10566 { 10567 std::int32_t number{}; 10568 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10569 } 10570 10571 case 0xD3: // int 64 10572 { 10573 std::int64_t number{}; 10574 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10575 } 10576 10577 case 0xDC: // array 16 10578 { 10579 std::uint16_t len{}; 10580 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len)); 10581 } 10582 10583 case 0xDD: // array 32 10584 { 10585 std::uint32_t len{}; 10586 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len)); 10587 } 10588 10589 case 0xDE: // map 16 10590 { 10591 std::uint16_t len{}; 10592 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len)); 10593 } 10594 10595 case 0xDF: // map 32 10596 { 10597 std::uint32_t len{}; 10598 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len)); 10599 } 10600 10601 // negative fixint 10602 case 0xE0: 10603 case 0xE1: 10604 case 0xE2: 10605 case 0xE3: 10606 case 0xE4: 10607 case 0xE5: 10608 case 0xE6: 10609 case 0xE7: 10610 case 0xE8: 10611 case 0xE9: 10612 case 0xEA: 10613 case 0xEB: 10614 case 0xEC: 10615 case 0xED: 10616 case 0xEE: 10617 case 0xEF: 10618 case 0xF0: 10619 case 0xF1: 10620 case 0xF2: 10621 case 0xF3: 10622 case 0xF4: 10623 case 0xF5: 10624 case 0xF6: 10625 case 0xF7: 10626 case 0xF8: 10627 case 0xF9: 10628 case 0xFA: 10629 case 0xFB: 10630 case 0xFC: 10631 case 0xFD: 10632 case 0xFE: 10633 case 0xFF: 10634 return sax->number_integer(static_cast<std::int8_t>(current)); 10635 10636 default: // anything else 10637 { 10638 auto last_token = get_token_string(); 10639 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 10640 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); 10641 } 10642 } 10643 } 10644 10645 /*! 10646 @brief reads a MessagePack string 10647 10648 This function first reads starting bytes to determine the expected 10649 string length and then copies this number of bytes into a string. 10650 10651 @param[out] result created string 10652 10653 @return whether string creation completed 10654 */ 10655 bool get_msgpack_string(string_t& result) 10656 { 10657 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) 10658 { 10659 return false; 10660 } 10661 10662 switch (current) 10663 { 10664 // fixstr 10665 case 0xA0: 10666 case 0xA1: 10667 case 0xA2: 10668 case 0xA3: 10669 case 0xA4: 10670 case 0xA5: 10671 case 0xA6: 10672 case 0xA7: 10673 case 0xA8: 10674 case 0xA9: 10675 case 0xAA: 10676 case 0xAB: 10677 case 0xAC: 10678 case 0xAD: 10679 case 0xAE: 10680 case 0xAF: 10681 case 0xB0: 10682 case 0xB1: 10683 case 0xB2: 10684 case 0xB3: 10685 case 0xB4: 10686 case 0xB5: 10687 case 0xB6: 10688 case 0xB7: 10689 case 0xB8: 10690 case 0xB9: 10691 case 0xBA: 10692 case 0xBB: 10693 case 0xBC: 10694 case 0xBD: 10695 case 0xBE: 10696 case 0xBF: 10697 { 10698 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result); 10699 } 10700 10701 case 0xD9: // str 8 10702 { 10703 std::uint8_t len{}; 10704 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10705 } 10706 10707 case 0xDA: // str 16 10708 { 10709 std::uint16_t len{}; 10710 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10711 } 10712 10713 case 0xDB: // str 32 10714 { 10715 std::uint32_t len{}; 10716 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10717 } 10718 10719 default: 10720 { 10721 auto last_token = get_token_string(); 10722 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10723 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); 10724 } 10725 } 10726 } 10727 10728 /*! 10729 @brief reads a MessagePack byte array 10730 10731 This function first reads starting bytes to determine the expected 10732 byte array length and then copies this number of bytes into a byte array. 10733 10734 @param[out] result created byte array 10735 10736 @return whether byte array creation completed 10737 */ 10738 bool get_msgpack_binary(binary_t& result) 10739 { 10740 // helper function to set the subtype 10741 auto assign_and_return_true = [&result](std::int8_t subtype) 10742 { 10743 result.set_subtype(static_cast<std::uint8_t>(subtype)); 10744 return true; 10745 }; 10746 10747 switch (current) 10748 { 10749 case 0xC4: // bin 8 10750 { 10751 std::uint8_t len{}; 10752 return get_number(input_format_t::msgpack, len) && 10753 get_binary(input_format_t::msgpack, len, result); 10754 } 10755 10756 case 0xC5: // bin 16 10757 { 10758 std::uint16_t len{}; 10759 return get_number(input_format_t::msgpack, len) && 10760 get_binary(input_format_t::msgpack, len, result); 10761 } 10762 10763 case 0xC6: // bin 32 10764 { 10765 std::uint32_t len{}; 10766 return get_number(input_format_t::msgpack, len) && 10767 get_binary(input_format_t::msgpack, len, result); 10768 } 10769 10770 case 0xC7: // ext 8 10771 { 10772 std::uint8_t len{}; 10773 std::int8_t subtype{}; 10774 return get_number(input_format_t::msgpack, len) && 10775 get_number(input_format_t::msgpack, subtype) && 10776 get_binary(input_format_t::msgpack, len, result) && 10777 assign_and_return_true(subtype); 10778 } 10779 10780 case 0xC8: // ext 16 10781 { 10782 std::uint16_t len{}; 10783 std::int8_t subtype{}; 10784 return get_number(input_format_t::msgpack, len) && 10785 get_number(input_format_t::msgpack, subtype) && 10786 get_binary(input_format_t::msgpack, len, result) && 10787 assign_and_return_true(subtype); 10788 } 10789 10790 case 0xC9: // ext 32 10791 { 10792 std::uint32_t len{}; 10793 std::int8_t subtype{}; 10794 return get_number(input_format_t::msgpack, len) && 10795 get_number(input_format_t::msgpack, subtype) && 10796 get_binary(input_format_t::msgpack, len, result) && 10797 assign_and_return_true(subtype); 10798 } 10799 10800 case 0xD4: // fixext 1 10801 { 10802 std::int8_t subtype{}; 10803 return get_number(input_format_t::msgpack, subtype) && 10804 get_binary(input_format_t::msgpack, 1, result) && 10805 assign_and_return_true(subtype); 10806 } 10807 10808 case 0xD5: // fixext 2 10809 { 10810 std::int8_t subtype{}; 10811 return get_number(input_format_t::msgpack, subtype) && 10812 get_binary(input_format_t::msgpack, 2, result) && 10813 assign_and_return_true(subtype); 10814 } 10815 10816 case 0xD6: // fixext 4 10817 { 10818 std::int8_t subtype{}; 10819 return get_number(input_format_t::msgpack, subtype) && 10820 get_binary(input_format_t::msgpack, 4, result) && 10821 assign_and_return_true(subtype); 10822 } 10823 10824 case 0xD7: // fixext 8 10825 { 10826 std::int8_t subtype{}; 10827 return get_number(input_format_t::msgpack, subtype) && 10828 get_binary(input_format_t::msgpack, 8, result) && 10829 assign_and_return_true(subtype); 10830 } 10831 10832 case 0xD8: // fixext 16 10833 { 10834 std::int8_t subtype{}; 10835 return get_number(input_format_t::msgpack, subtype) && 10836 get_binary(input_format_t::msgpack, 16, result) && 10837 assign_and_return_true(subtype); 10838 } 10839 10840 default: // LCOV_EXCL_LINE 10841 return false; // LCOV_EXCL_LINE 10842 } 10843 } 10844 10845 /*! 10846 @param[in] len the length of the array 10847 @return whether array creation completed 10848 */ 10849 bool get_msgpack_array(const std::size_t len) 10850 { 10851 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) 10852 { 10853 return false; 10854 } 10855 10856 for (std::size_t i = 0; i < len; ++i) 10857 { 10858 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) 10859 { 10860 return false; 10861 } 10862 } 10863 10864 return sax->end_array(); 10865 } 10866 10867 /*! 10868 @param[in] len the length of the object 10869 @return whether object creation completed 10870 */ 10871 bool get_msgpack_object(const std::size_t len) 10872 { 10873 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) 10874 { 10875 return false; 10876 } 10877 10878 string_t key; 10879 for (std::size_t i = 0; i < len; ++i) 10880 { 10881 get(); 10882 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) 10883 { 10884 return false; 10885 } 10886 10887 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) 10888 { 10889 return false; 10890 } 10891 key.clear(); 10892 } 10893 10894 return sax->end_object(); 10895 } 10896 10897 //////////// 10898 // UBJSON // 10899 //////////// 10900 10901 /*! 10902 @param[in] get_char whether a new character should be retrieved from the 10903 input (true, default) or whether the last read 10904 character should be considered instead 10905 10906 @return whether a valid UBJSON value was passed to the SAX parser 10907 */ 10908 bool parse_ubjson_internal(const bool get_char = true) 10909 { 10910 return get_ubjson_value(get_char ? get_ignore_noop() : current); 10911 } 10912 10913 /*! 10914 @brief reads a UBJSON string 10915 10916 This function is either called after reading the 'S' byte explicitly 10917 indicating a string, or in case of an object key where the 'S' byte can be 10918 left out. 10919 10920 @param[out] result created string 10921 @param[in] get_char whether a new character should be retrieved from the 10922 input (true, default) or whether the last read 10923 character should be considered instead 10924 10925 @return whether string creation completed 10926 */ 10927 bool get_ubjson_string(string_t& result, const bool get_char = true) 10928 { 10929 if (get_char) 10930 { 10931 get(); // TODO(niels): may we ignore N here? 10932 } 10933 10934 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) 10935 { 10936 return false; 10937 } 10938 10939 switch (current) 10940 { 10941 case 'U': 10942 { 10943 std::uint8_t len{}; 10944 return get_number(input_format, len) && get_string(input_format, len, result); 10945 } 10946 10947 case 'i': 10948 { 10949 std::int8_t len{}; 10950 return get_number(input_format, len) && get_string(input_format, len, result); 10951 } 10952 10953 case 'I': 10954 { 10955 std::int16_t len{}; 10956 return get_number(input_format, len) && get_string(input_format, len, result); 10957 } 10958 10959 case 'l': 10960 { 10961 std::int32_t len{}; 10962 return get_number(input_format, len) && get_string(input_format, len, result); 10963 } 10964 10965 case 'L': 10966 { 10967 std::int64_t len{}; 10968 return get_number(input_format, len) && get_string(input_format, len, result); 10969 } 10970 10971 case 'u': 10972 { 10973 if (input_format != input_format_t::bjdata) 10974 { 10975 break; 10976 } 10977 std::uint16_t len{}; 10978 return get_number(input_format, len) && get_string(input_format, len, result); 10979 } 10980 10981 case 'm': 10982 { 10983 if (input_format != input_format_t::bjdata) 10984 { 10985 break; 10986 } 10987 std::uint32_t len{}; 10988 return get_number(input_format, len) && get_string(input_format, len, result); 10989 } 10990 10991 case 'M': 10992 { 10993 if (input_format != input_format_t::bjdata) 10994 { 10995 break; 10996 } 10997 std::uint64_t len{}; 10998 return get_number(input_format, len) && get_string(input_format, len, result); 10999 } 11000 11001 default: 11002 break; 11003 } 11004 auto last_token = get_token_string(); 11005 std::string message; 11006 11007 if (input_format != input_format_t::bjdata) 11008 { 11009 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; 11010 } 11011 else 11012 { 11013 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; 11014 } 11015 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); 11016 } 11017 11018 /*! 11019 @param[out] dim an integer vector storing the ND array dimensions 11020 @return whether reading ND array size vector is successful 11021 */ 11022 bool get_ubjson_ndarray_size(std::vector<size_t>& dim) 11023 { 11024 std::pair<std::size_t, char_int_type> size_and_type; 11025 size_t dimlen = 0; 11026 bool no_ndarray = true; 11027 11028 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) 11029 { 11030 return false; 11031 } 11032 11033 if (size_and_type.first != npos) 11034 { 11035 if (size_and_type.second != 0) 11036 { 11037 if (size_and_type.second != 'N') 11038 { 11039 for (std::size_t i = 0; i < size_and_type.first; ++i) 11040 { 11041 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) 11042 { 11043 return false; 11044 } 11045 dim.push_back(dimlen); 11046 } 11047 } 11048 } 11049 else 11050 { 11051 for (std::size_t i = 0; i < size_and_type.first; ++i) 11052 { 11053 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) 11054 { 11055 return false; 11056 } 11057 dim.push_back(dimlen); 11058 } 11059 } 11060 } 11061 else 11062 { 11063 while (current != ']') 11064 { 11065 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) 11066 { 11067 return false; 11068 } 11069 dim.push_back(dimlen); 11070 get_ignore_noop(); 11071 } 11072 } 11073 return true; 11074 } 11075 11076 /*! 11077 @param[out] result determined size 11078 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector 11079 or ndarray dimension is not allowed; `false` means ndarray 11080 is allowed; for output, `true` means an ndarray is found; 11081 is_ndarray can only return `true` when its initial value 11082 is `false` 11083 @param[in] prefix type marker if already read, otherwise set to 0 11084 11085 @return whether size determination completed 11086 */ 11087 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) 11088 { 11089 if (prefix == 0) 11090 { 11091 prefix = get_ignore_noop(); 11092 } 11093 11094 switch (prefix) 11095 { 11096 case 'U': 11097 { 11098 std::uint8_t number{}; 11099 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11100 { 11101 return false; 11102 } 11103 result = static_cast<std::size_t>(number); 11104 return true; 11105 } 11106 11107 case 'i': 11108 { 11109 std::int8_t number{}; 11110 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11111 { 11112 return false; 11113 } 11114 if (number < 0) 11115 { 11116 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11117 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11118 } 11119 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char 11120 return true; 11121 } 11122 11123 case 'I': 11124 { 11125 std::int16_t number{}; 11126 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11127 { 11128 return false; 11129 } 11130 if (number < 0) 11131 { 11132 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11133 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11134 } 11135 result = static_cast<std::size_t>(number); 11136 return true; 11137 } 11138 11139 case 'l': 11140 { 11141 std::int32_t number{}; 11142 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11143 { 11144 return false; 11145 } 11146 if (number < 0) 11147 { 11148 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11149 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11150 } 11151 result = static_cast<std::size_t>(number); 11152 return true; 11153 } 11154 11155 case 'L': 11156 { 11157 std::int64_t number{}; 11158 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11159 { 11160 return false; 11161 } 11162 if (number < 0) 11163 { 11164 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11165 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11166 } 11167 if (!value_in_range_of<std::size_t>(number)) 11168 { 11169 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, 11170 exception_message(input_format, "integer value overflow", "size"), nullptr)); 11171 } 11172 result = static_cast<std::size_t>(number); 11173 return true; 11174 } 11175 11176 case 'u': 11177 { 11178 if (input_format != input_format_t::bjdata) 11179 { 11180 break; 11181 } 11182 std::uint16_t number{}; 11183 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11184 { 11185 return false; 11186 } 11187 result = static_cast<std::size_t>(number); 11188 return true; 11189 } 11190 11191 case 'm': 11192 { 11193 if (input_format != input_format_t::bjdata) 11194 { 11195 break; 11196 } 11197 std::uint32_t number{}; 11198 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11199 { 11200 return false; 11201 } 11202 result = conditional_static_cast<std::size_t>(number); 11203 return true; 11204 } 11205 11206 case 'M': 11207 { 11208 if (input_format != input_format_t::bjdata) 11209 { 11210 break; 11211 } 11212 std::uint64_t number{}; 11213 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11214 { 11215 return false; 11216 } 11217 if (!value_in_range_of<std::size_t>(number)) 11218 { 11219 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, 11220 exception_message(input_format, "integer value overflow", "size"), nullptr)); 11221 } 11222 result = detail::conditional_static_cast<std::size_t>(number); 11223 return true; 11224 } 11225 11226 case '[': 11227 { 11228 if (input_format != input_format_t::bjdata) 11229 { 11230 break; 11231 } 11232 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array 11233 { 11234 return 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)); 11235 } 11236 std::vector<size_t> dim; 11237 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) 11238 { 11239 return false; 11240 } 11241 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector 11242 { 11243 result = dim.at(dim.size() - 1); 11244 return true; 11245 } 11246 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format 11247 { 11248 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container 11249 { 11250 if ( i == 0 ) 11251 { 11252 result = 0; 11253 return true; 11254 } 11255 } 11256 11257 string_t key = "_ArraySize_"; 11258 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) 11259 { 11260 return false; 11261 } 11262 result = 1; 11263 for (auto i : dim) 11264 { 11265 result *= i; 11266 if (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() 11267 { 11268 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); 11269 } 11270 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i)))) 11271 { 11272 return false; 11273 } 11274 } 11275 is_ndarray = true; 11276 return sax->end_array(); 11277 } 11278 result = 0; 11279 return true; 11280 } 11281 11282 default: 11283 break; 11284 } 11285 auto last_token = get_token_string(); 11286 std::string message; 11287 11288 if (input_format != input_format_t::bjdata) 11289 { 11290 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; 11291 } 11292 else 11293 { 11294 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; 11295 } 11296 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); 11297 } 11298 11299 /*! 11300 @brief determine the type and size for a container 11301 11302 In the optimized UBJSON format, a type and a size can be provided to allow 11303 for a more compact representation. 11304 11305 @param[out] result pair of the size and the type 11306 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector 11307 11308 @return whether pair creation completed 11309 */ 11310 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false) 11311 { 11312 result.first = npos; // size 11313 result.second = 0; // type 11314 bool is_ndarray = false; 11315 11316 get_ignore_noop(); 11317 11318 if (current == '$') 11319 { 11320 result.second = get(); // must not ignore 'N', because 'N' maybe the type 11321 if (input_format == input_format_t::bjdata 11322 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) 11323 { 11324 auto last_token = get_token_string(); 11325 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11326 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); 11327 } 11328 11329 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) 11330 { 11331 return false; 11332 } 11333 11334 get_ignore_noop(); 11335 if (JSON_HEDLEY_UNLIKELY(current != '#')) 11336 { 11337 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) 11338 { 11339 return false; 11340 } 11341 auto last_token = get_token_string(); 11342 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11343 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); 11344 } 11345 11346 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); 11347 if (input_format == input_format_t::bjdata && is_ndarray) 11348 { 11349 if (inside_ndarray) 11350 { 11351 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, 11352 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); 11353 } 11354 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters 11355 } 11356 return is_error; 11357 } 11358 11359 if (current == '#') 11360 { 11361 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); 11362 if (input_format == input_format_t::bjdata && is_ndarray) 11363 { 11364 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, 11365 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); 11366 } 11367 return is_error; 11368 } 11369 11370 return true; 11371 } 11372 11373 /*! 11374 @param prefix the previously read or set type prefix 11375 @return whether value creation completed 11376 */ 11377 bool get_ubjson_value(const char_int_type prefix) 11378 { 11379 switch (prefix) 11380 { 11381 case std::char_traits<char_type>::eof(): // EOF 11382 return unexpect_eof(input_format, "value"); 11383 11384 case 'T': // true 11385 return sax->boolean(true); 11386 case 'F': // false 11387 return sax->boolean(false); 11388 11389 case 'Z': // null 11390 return sax->null(); 11391 11392 case 'U': 11393 { 11394 std::uint8_t number{}; 11395 return get_number(input_format, number) && sax->number_unsigned(number); 11396 } 11397 11398 case 'i': 11399 { 11400 std::int8_t number{}; 11401 return get_number(input_format, number) && sax->number_integer(number); 11402 } 11403 11404 case 'I': 11405 { 11406 std::int16_t number{}; 11407 return get_number(input_format, number) && sax->number_integer(number); 11408 } 11409 11410 case 'l': 11411 { 11412 std::int32_t number{}; 11413 return get_number(input_format, number) && sax->number_integer(number); 11414 } 11415 11416 case 'L': 11417 { 11418 std::int64_t number{}; 11419 return get_number(input_format, number) && sax->number_integer(number); 11420 } 11421 11422 case 'u': 11423 { 11424 if (input_format != input_format_t::bjdata) 11425 { 11426 break; 11427 } 11428 std::uint16_t number{}; 11429 return get_number(input_format, number) && sax->number_unsigned(number); 11430 } 11431 11432 case 'm': 11433 { 11434 if (input_format != input_format_t::bjdata) 11435 { 11436 break; 11437 } 11438 std::uint32_t number{}; 11439 return get_number(input_format, number) && sax->number_unsigned(number); 11440 } 11441 11442 case 'M': 11443 { 11444 if (input_format != input_format_t::bjdata) 11445 { 11446 break; 11447 } 11448 std::uint64_t number{}; 11449 return get_number(input_format, number) && sax->number_unsigned(number); 11450 } 11451 11452 case 'h': 11453 { 11454 if (input_format != input_format_t::bjdata) 11455 { 11456 break; 11457 } 11458 const auto byte1_raw = get(); 11459 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11460 { 11461 return false; 11462 } 11463 const auto byte2_raw = get(); 11464 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11465 { 11466 return false; 11467 } 11468 11469 const auto byte1 = static_cast<unsigned char>(byte1_raw); 11470 const auto byte2 = static_cast<unsigned char>(byte2_raw); 11471 11472 // code from RFC 7049, Appendix D, Figure 3: 11473 // As half-precision floating-point numbers were only added 11474 // to IEEE 754 in 2008, today's programming platforms often 11475 // still only have limited support for them. It is very 11476 // easy to include at least decoding support for them even 11477 // without such support. An example of a small decoder for 11478 // half-precision floating-point numbers in the C language 11479 // is shown in Fig. 3. 11480 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1); 11481 const double val = [&half] 11482 { 11483 const int exp = (half >> 10u) & 0x1Fu; 11484 const unsigned int mant = half & 0x3FFu; 11485 JSON_ASSERT(0 <= exp&& exp <= 32); 11486 JSON_ASSERT(mant <= 1024); 11487 switch (exp) 11488 { 11489 case 0: 11490 return std::ldexp(mant, -24); 11491 case 31: 11492 return (mant == 0) 11493 ? std::numeric_limits<double>::infinity() 11494 : std::numeric_limits<double>::quiet_NaN(); 11495 default: 11496 return std::ldexp(mant + 1024, exp - 25); 11497 } 11498 }(); 11499 return sax->number_float((half & 0x8000u) != 0 11500 ? static_cast<number_float_t>(-val) 11501 : static_cast<number_float_t>(val), ""); 11502 } 11503 11504 case 'd': 11505 { 11506 float number{}; 11507 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); 11508 } 11509 11510 case 'D': 11511 { 11512 double number{}; 11513 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); 11514 } 11515 11516 case 'H': 11517 { 11518 return get_ubjson_high_precision_number(); 11519 } 11520 11521 case 'C': // char 11522 { 11523 get(); 11524 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) 11525 { 11526 return false; 11527 } 11528 if (JSON_HEDLEY_UNLIKELY(current > 127)) 11529 { 11530 auto last_token = get_token_string(); 11531 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 11532 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); 11533 } 11534 string_t s(1, static_cast<typename string_t::value_type>(current)); 11535 return sax->string(s); 11536 } 11537 11538 case 'S': // string 11539 { 11540 string_t s; 11541 return get_ubjson_string(s) && sax->string(s); 11542 } 11543 11544 case '[': // array 11545 return get_ubjson_array(); 11546 11547 case '{': // object 11548 return get_ubjson_object(); 11549 11550 default: // anything else 11551 break; 11552 } 11553 auto last_token = get_token_string(); 11554 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); 11555 } 11556 11557 /*! 11558 @return whether array creation completed 11559 */ 11560 bool get_ubjson_array() 11561 { 11562 std::pair<std::size_t, char_int_type> size_and_type; 11563 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) 11564 { 11565 return false; 11566 } 11567 11568 // 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): 11569 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} 11570 11571 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) 11572 { 11573 size_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 11574 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t) 11575 { 11576 return p.first < t; 11577 }); 11578 string_t key = "_ArrayType_"; 11579 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) 11580 { 11581 auto last_token = get_token_string(); 11582 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11583 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); 11584 } 11585 11586 string_t type = it->second; // sax->string() takes a reference 11587 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) 11588 { 11589 return false; 11590 } 11591 11592 if (size_and_type.second == 'C') 11593 { 11594 size_and_type.second = 'U'; 11595 } 11596 11597 key = "_ArrayData_"; 11598 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) 11599 { 11600 return false; 11601 } 11602 11603 for (std::size_t i = 0; i < size_and_type.first; ++i) 11604 { 11605 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11606 { 11607 return false; 11608 } 11609 } 11610 11611 return (sax->end_array() && sax->end_object()); 11612 } 11613 11614 if (size_and_type.first != npos) 11615 { 11616 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) 11617 { 11618 return false; 11619 } 11620 11621 if (size_and_type.second != 0) 11622 { 11623 if (size_and_type.second != 'N') 11624 { 11625 for (std::size_t i = 0; i < size_and_type.first; ++i) 11626 { 11627 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11628 { 11629 return false; 11630 } 11631 } 11632 } 11633 } 11634 else 11635 { 11636 for (std::size_t i = 0; i < size_and_type.first; ++i) 11637 { 11638 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11639 { 11640 return false; 11641 } 11642 } 11643 } 11644 } 11645 else 11646 { 11647 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 11648 { 11649 return false; 11650 } 11651 11652 while (current != ']') 11653 { 11654 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) 11655 { 11656 return false; 11657 } 11658 get_ignore_noop(); 11659 } 11660 } 11661 11662 return sax->end_array(); 11663 } 11664 11665 /*! 11666 @return whether object creation completed 11667 */ 11668 bool get_ubjson_object() 11669 { 11670 std::pair<std::size_t, char_int_type> size_and_type; 11671 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) 11672 { 11673 return false; 11674 } 11675 11676 // do not accept ND-array size in objects in BJData 11677 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) 11678 { 11679 auto last_token = get_token_string(); 11680 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11681 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); 11682 } 11683 11684 string_t key; 11685 if (size_and_type.first != npos) 11686 { 11687 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) 11688 { 11689 return false; 11690 } 11691 11692 if (size_and_type.second != 0) 11693 { 11694 for (std::size_t i = 0; i < size_and_type.first; ++i) 11695 { 11696 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) 11697 { 11698 return false; 11699 } 11700 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11701 { 11702 return false; 11703 } 11704 key.clear(); 11705 } 11706 } 11707 else 11708 { 11709 for (std::size_t i = 0; i < size_and_type.first; ++i) 11710 { 11711 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) 11712 { 11713 return false; 11714 } 11715 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11716 { 11717 return false; 11718 } 11719 key.clear(); 11720 } 11721 } 11722 } 11723 else 11724 { 11725 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 11726 { 11727 return false; 11728 } 11729 11730 while (current != '}') 11731 { 11732 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) 11733 { 11734 return false; 11735 } 11736 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11737 { 11738 return false; 11739 } 11740 get_ignore_noop(); 11741 key.clear(); 11742 } 11743 } 11744 11745 return sax->end_object(); 11746 } 11747 11748 // Note, no reader for UBJSON binary types is implemented because they do 11749 // not exist 11750 11751 bool get_ubjson_high_precision_number() 11752 { 11753 // get size of following number string 11754 std::size_t size{}; 11755 bool no_ndarray = true; 11756 auto res = get_ubjson_size_value(size, no_ndarray); 11757 if (JSON_HEDLEY_UNLIKELY(!res)) 11758 { 11759 return res; 11760 } 11761 11762 // get number string 11763 std::vector<char> number_vector; 11764 for (std::size_t i = 0; i < size; ++i) 11765 { 11766 get(); 11767 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11768 { 11769 return false; 11770 } 11771 number_vector.push_back(static_cast<char>(current)); 11772 } 11773 11774 // parse number string 11775 using ia_type = decltype(detail::input_adapter(number_vector)); 11776 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false); 11777 const auto result_number = number_lexer.scan(); 11778 const auto number_string = number_lexer.get_token_string(); 11779 const auto result_remainder = number_lexer.scan(); 11780 11781 using token_type = typename detail::lexer_base<BasicJsonType>::token_type; 11782 11783 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) 11784 { 11785 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, 11786 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); 11787 } 11788 11789 switch (result_number) 11790 { 11791 case token_type::value_integer: 11792 return sax->number_integer(number_lexer.get_number_integer()); 11793 case token_type::value_unsigned: 11794 return sax->number_unsigned(number_lexer.get_number_unsigned()); 11795 case token_type::value_float: 11796 return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); 11797 case token_type::uninitialized: 11798 case token_type::literal_true: 11799 case token_type::literal_false: 11800 case token_type::literal_null: 11801 case token_type::value_string: 11802 case token_type::begin_array: 11803 case token_type::begin_object: 11804 case token_type::end_array: 11805 case token_type::end_object: 11806 case token_type::name_separator: 11807 case token_type::value_separator: 11808 case token_type::parse_error: 11809 case token_type::end_of_input: 11810 case token_type::literal_or_value: 11811 default: 11812 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, 11813 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); 11814 } 11815 } 11816 11817 /////////////////////// 11818 // Utility functions // 11819 /////////////////////// 11820 11821 /*! 11822 @brief get next character from the input 11823 11824 This function provides the interface to the used input adapter. It does 11825 not throw in case the input reached EOF, but returns a -'ve valued 11826 `std::char_traits<char_type>::eof()` in that case. 11827 11828 @return character read from the input 11829 */ 11830 char_int_type get() 11831 { 11832 ++chars_read; 11833 return current = ia.get_character(); 11834 } 11835 11836 /*! 11837 @return character read from the input after ignoring all 'N' entries 11838 */ 11839 char_int_type get_ignore_noop() 11840 { 11841 do 11842 { 11843 get(); 11844 } 11845 while (current == 'N'); 11846 11847 return current; 11848 } 11849 11850 /* 11851 @brief read a number from the input 11852 11853 @tparam NumberType the type of the number 11854 @param[in] format the current format (for diagnostics) 11855 @param[out] result number of type @a NumberType 11856 11857 @return whether conversion completed 11858 11859 @note This function needs to respect the system's endianness, because 11860 bytes in CBOR, MessagePack, and UBJSON are stored in network order 11861 (big endian) and therefore need reordering on little endian systems. 11862 On the other hand, BSON and BJData use little endian and should reorder 11863 on big endian systems. 11864 */ 11865 template<typename NumberType, bool InputIsLittleEndian = false> 11866 bool get_number(const input_format_t format, NumberType& result) 11867 { 11868 // step 1: read input into array with system's byte order 11869 std::array<std::uint8_t, sizeof(NumberType)> vec{}; 11870 for (std::size_t i = 0; i < sizeof(NumberType); ++i) 11871 { 11872 get(); 11873 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) 11874 { 11875 return false; 11876 } 11877 11878 // reverse byte order prior to conversion if necessary 11879 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) 11880 { 11881 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current); 11882 } 11883 else 11884 { 11885 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE 11886 } 11887 } 11888 11889 // step 2: convert array into number of type T and return 11890 std::memcpy(&result, vec.data(), sizeof(NumberType)); 11891 return true; 11892 } 11893 11894 /*! 11895 @brief create a string by reading characters from the input 11896 11897 @tparam NumberType the type of the number 11898 @param[in] format the current format (for diagnostics) 11899 @param[in] len number of characters to read 11900 @param[out] result string created by reading @a len bytes 11901 11902 @return whether string creation completed 11903 11904 @note We can not reserve @a len bytes for the result, because @a len 11905 may be too large. Usually, @ref unexpect_eof() detects the end of 11906 the input before we run out of string memory. 11907 */ 11908 template<typename NumberType> 11909 bool get_string(const input_format_t format, 11910 const NumberType len, 11911 string_t& result) 11912 { 11913 bool success = true; 11914 for (NumberType i = 0; i < len; i++) 11915 { 11916 get(); 11917 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) 11918 { 11919 success = false; 11920 break; 11921 } 11922 result.push_back(static_cast<typename string_t::value_type>(current)); 11923 } 11924 return success; 11925 } 11926 11927 /*! 11928 @brief create a byte array by reading bytes from the input 11929 11930 @tparam NumberType the type of the number 11931 @param[in] format the current format (for diagnostics) 11932 @param[in] len number of bytes to read 11933 @param[out] result byte array created by reading @a len bytes 11934 11935 @return whether byte array creation completed 11936 11937 @note We can not reserve @a len bytes for the result, because @a len 11938 may be too large. Usually, @ref unexpect_eof() detects the end of 11939 the input before we run out of memory. 11940 */ 11941 template<typename NumberType> 11942 bool get_binary(const input_format_t format, 11943 const NumberType len, 11944 binary_t& result) 11945 { 11946 bool success = true; 11947 for (NumberType i = 0; i < len; i++) 11948 { 11949 get(); 11950 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) 11951 { 11952 success = false; 11953 break; 11954 } 11955 result.push_back(static_cast<std::uint8_t>(current)); 11956 } 11957 return success; 11958 } 11959 11960 /*! 11961 @param[in] format the current format (for diagnostics) 11962 @param[in] context further context information (for diagnostics) 11963 @return whether the last read character is not EOF 11964 */ 11965 JSON_HEDLEY_NON_NULL(3) 11966 bool unexpect_eof(const input_format_t format, const char* context) const 11967 { 11968 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof())) 11969 { 11970 return sax->parse_error(chars_read, "<end of file>", 11971 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); 11972 } 11973 return true; 11974 } 11975 11976 /*! 11977 @return a string representation of the last read byte 11978 */ 11979 std::string get_token_string() const 11980 { 11981 std::array<char, 3> cr{{}}; 11982 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 11983 return std::string{cr.data()}; 11984 } 11985 11986 /*! 11987 @param[in] format the current format 11988 @param[in] detail a detailed error message 11989 @param[in] context further context information 11990 @return a message string to use in the parse_error exceptions 11991 */ 11992 std::string exception_message(const input_format_t format, 11993 const std::string& detail, 11994 const std::string& context) const 11995 { 11996 std::string error_msg = "syntax error while parsing "; 11997 11998 switch (format) 11999 { 12000 case input_format_t::cbor: 12001 error_msg += "CBOR"; 12002 break; 12003 12004 case input_format_t::msgpack: 12005 error_msg += "MessagePack"; 12006 break; 12007 12008 case input_format_t::ubjson: 12009 error_msg += "UBJSON"; 12010 break; 12011 12012 case input_format_t::bson: 12013 error_msg += "BSON"; 12014 break; 12015 12016 case input_format_t::bjdata: 12017 error_msg += "BJData"; 12018 break; 12019 12020 case input_format_t::json: // LCOV_EXCL_LINE 12021 default: // LCOV_EXCL_LINE 12022 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 12023 } 12024 12025 return concat(error_msg, ' ', context, ": ", detail); 12026 } 12027 12028 private: 12029 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1); 12030 12031 /// input adapter 12032 InputAdapterType ia; 12033 12034 /// the current character 12035 char_int_type current = std::char_traits<char_type>::eof(); 12036 12037 /// the number of characters read 12038 std::size_t chars_read = 0; 12039 12040 /// whether we can assume little endianness 12041 const bool is_little_endian = little_endianness(); 12042 12043 /// input format 12044 const input_format_t input_format = input_format_t::json; 12045 12046 /// the SAX parser 12047 json_sax_t* sax = nullptr; 12048 12049 // excluded markers in bjdata optimized type 12050 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ 12051 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') 12052 12053 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ 12054 make_array<bjd_type>( \ 12055 bjd_type{'C', "char"}, \ 12056 bjd_type{'D', "double"}, \ 12057 bjd_type{'I', "int16"}, \ 12058 bjd_type{'L', "int64"}, \ 12059 bjd_type{'M', "uint64"}, \ 12060 bjd_type{'U', "uint8"}, \ 12061 bjd_type{'d', "single"}, \ 12062 bjd_type{'i', "int8"}, \ 12063 bjd_type{'l', "int32"}, \ 12064 bjd_type{'m', "uint32"}, \ 12065 bjd_type{'u', "uint16"}) 12066 12067 JSON_PRIVATE_UNLESS_TESTED: 12068 // lookup tables 12069 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12070 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = 12071 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; 12072 12073 using bjd_type = std::pair<char_int_type, string_t>; 12074 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12075 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = 12076 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; 12077 12078 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ 12079 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ 12080 }; 12081 12082 #ifndef JSON_HAS_CPP_17 12083 template<typename BasicJsonType, typename InputAdapterType, typename SAX> 12084 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos; 12085 #endif 12086 12087 } // namespace detail 12088 NLOHMANN_JSON_NAMESPACE_END 12089 12090 // #include <nlohmann/detail/input/input_adapters.hpp> 12091 12092 // #include <nlohmann/detail/input/lexer.hpp> 12093 12094 // #include <nlohmann/detail/input/parser.hpp> 12095 // __ _____ _____ _____ 12096 // __| | __| | | | JSON for Modern C++ 12097 // | | |__ | | | | | | version 3.11.2 12098 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12099 // 12100 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 12101 // SPDX-License-Identifier: MIT 12102 12103 12104 12105 #include <cmath> // isfinite 12106 #include <cstdint> // uint8_t 12107 #include <functional> // function 12108 #include <string> // string 12109 #include <utility> // move 12110 #include <vector> // vector 12111 12112 // #include <nlohmann/detail/exceptions.hpp> 12113 12114 // #include <nlohmann/detail/input/input_adapters.hpp> 12115 12116 // #include <nlohmann/detail/input/json_sax.hpp> 12117 12118 // #include <nlohmann/detail/input/lexer.hpp> 12119 12120 // #include <nlohmann/detail/macro_scope.hpp> 12121 12122 // #include <nlohmann/detail/meta/is_sax.hpp> 12123 12124 // #include <nlohmann/detail/string_concat.hpp> 12125 12126 // #include <nlohmann/detail/value_t.hpp> 12127 12128 12129 NLOHMANN_JSON_NAMESPACE_BEGIN 12130 namespace detail 12131 { 12132 //////////// 12133 // parser // 12134 //////////// 12135 12136 enum class parse_event_t : std::uint8_t 12137 { 12138 /// the parser read `{` and started to process a JSON object 12139 object_start, 12140 /// the parser read `}` and finished processing a JSON object 12141 object_end, 12142 /// the parser read `[` and started to process a JSON array 12143 array_start, 12144 /// the parser read `]` and finished processing a JSON array 12145 array_end, 12146 /// the parser read a key of a value in an object 12147 key, 12148 /// the parser finished reading a JSON value 12149 value 12150 }; 12151 12152 template<typename BasicJsonType> 12153 using parser_callback_t = 12154 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; 12155 12156 /*! 12157 @brief syntax analysis 12158 12159 This class implements a recursive descent parser. 12160 */ 12161 template<typename BasicJsonType, typename InputAdapterType> 12162 class parser 12163 { 12164 using number_integer_t = typename BasicJsonType::number_integer_t; 12165 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 12166 using number_float_t = typename BasicJsonType::number_float_t; 12167 using string_t = typename BasicJsonType::string_t; 12168 using lexer_t = lexer<BasicJsonType, InputAdapterType>; 12169 using token_type = typename lexer_t::token_type; 12170 12171 public: 12172 /// a parser reading from an input adapter 12173 explicit parser(InputAdapterType&& adapter, 12174 const parser_callback_t<BasicJsonType> cb = nullptr, 12175 const bool allow_exceptions_ = true, 12176 const bool skip_comments = false) 12177 : callback(cb) 12178 , m_lexer(std::move(adapter), skip_comments) 12179 , allow_exceptions(allow_exceptions_) 12180 { 12181 // read first token 12182 get_token(); 12183 } 12184 12185 /*! 12186 @brief public parser interface 12187 12188 @param[in] strict whether to expect the last token to be EOF 12189 @param[in,out] result parsed JSON value 12190 12191 @throw parse_error.101 in case of an unexpected token 12192 @throw parse_error.102 if to_unicode fails or surrogate error 12193 @throw parse_error.103 if to_unicode fails 12194 */ 12195 void parse(const bool strict, BasicJsonType& result) 12196 { 12197 if (callback) 12198 { 12199 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); 12200 sax_parse_internal(&sdp); 12201 12202 // in strict mode, input must be completely read 12203 if (strict && (get_token() != token_type::end_of_input)) 12204 { 12205 sdp.parse_error(m_lexer.get_position(), 12206 m_lexer.get_token_string(), 12207 parse_error::create(101, m_lexer.get_position(), 12208 exception_message(token_type::end_of_input, "value"), nullptr)); 12209 } 12210 12211 // in case of an error, return discarded value 12212 if (sdp.is_errored()) 12213 { 12214 result = value_t::discarded; 12215 return; 12216 } 12217 12218 // set top-level value to null if it was discarded by the callback 12219 // function 12220 if (result.is_discarded()) 12221 { 12222 result = nullptr; 12223 } 12224 } 12225 else 12226 { 12227 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); 12228 sax_parse_internal(&sdp); 12229 12230 // in strict mode, input must be completely read 12231 if (strict && (get_token() != token_type::end_of_input)) 12232 { 12233 sdp.parse_error(m_lexer.get_position(), 12234 m_lexer.get_token_string(), 12235 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 12236 } 12237 12238 // in case of an error, return discarded value 12239 if (sdp.is_errored()) 12240 { 12241 result = value_t::discarded; 12242 return; 12243 } 12244 } 12245 12246 result.assert_invariant(); 12247 } 12248 12249 /*! 12250 @brief public accept interface 12251 12252 @param[in] strict whether to expect the last token to be EOF 12253 @return whether the input is a proper JSON text 12254 */ 12255 bool accept(const bool strict = true) 12256 { 12257 json_sax_acceptor<BasicJsonType> sax_acceptor; 12258 return sax_parse(&sax_acceptor, strict); 12259 } 12260 12261 template<typename SAX> 12262 JSON_HEDLEY_NON_NULL(2) 12263 bool sax_parse(SAX* sax, const bool strict = true) 12264 { 12265 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; 12266 const bool result = sax_parse_internal(sax); 12267 12268 // strict mode: next byte must be EOF 12269 if (result && strict && (get_token() != token_type::end_of_input)) 12270 { 12271 return sax->parse_error(m_lexer.get_position(), 12272 m_lexer.get_token_string(), 12273 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 12274 } 12275 12276 return result; 12277 } 12278 12279 private: 12280 template<typename SAX> 12281 JSON_HEDLEY_NON_NULL(2) 12282 bool sax_parse_internal(SAX* sax) 12283 { 12284 // stack to remember the hierarchy of structured values we are parsing 12285 // true = array; false = object 12286 std::vector<bool> states; 12287 // value to avoid a goto (see comment where set to true) 12288 bool skip_to_state_evaluation = false; 12289 12290 while (true) 12291 { 12292 if (!skip_to_state_evaluation) 12293 { 12294 // invariant: get_token() was called before each iteration 12295 switch (last_token) 12296 { 12297 case token_type::begin_object: 12298 { 12299 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 12300 { 12301 return false; 12302 } 12303 12304 // closing } -> we are done 12305 if (get_token() == token_type::end_object) 12306 { 12307 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 12308 { 12309 return false; 12310 } 12311 break; 12312 } 12313 12314 // parse key 12315 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) 12316 { 12317 return sax->parse_error(m_lexer.get_position(), 12318 m_lexer.get_token_string(), 12319 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 12320 } 12321 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 12322 { 12323 return false; 12324 } 12325 12326 // parse separator (:) 12327 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 12328 { 12329 return sax->parse_error(m_lexer.get_position(), 12330 m_lexer.get_token_string(), 12331 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 12332 } 12333 12334 // remember we are now inside an object 12335 states.push_back(false); 12336 12337 // parse values 12338 get_token(); 12339 continue; 12340 } 12341 12342 case token_type::begin_array: 12343 { 12344 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 12345 { 12346 return false; 12347 } 12348 12349 // closing ] -> we are done 12350 if (get_token() == token_type::end_array) 12351 { 12352 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 12353 { 12354 return false; 12355 } 12356 break; 12357 } 12358 12359 // remember we are now inside an array 12360 states.push_back(true); 12361 12362 // parse values (no need to call get_token) 12363 continue; 12364 } 12365 12366 case token_type::value_float: 12367 { 12368 const auto res = m_lexer.get_number_float(); 12369 12370 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) 12371 { 12372 return sax->parse_error(m_lexer.get_position(), 12373 m_lexer.get_token_string(), 12374 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); 12375 } 12376 12377 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) 12378 { 12379 return false; 12380 } 12381 12382 break; 12383 } 12384 12385 case token_type::literal_false: 12386 { 12387 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) 12388 { 12389 return false; 12390 } 12391 break; 12392 } 12393 12394 case token_type::literal_null: 12395 { 12396 if (JSON_HEDLEY_UNLIKELY(!sax->null())) 12397 { 12398 return false; 12399 } 12400 break; 12401 } 12402 12403 case token_type::literal_true: 12404 { 12405 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) 12406 { 12407 return false; 12408 } 12409 break; 12410 } 12411 12412 case token_type::value_integer: 12413 { 12414 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) 12415 { 12416 return false; 12417 } 12418 break; 12419 } 12420 12421 case token_type::value_string: 12422 { 12423 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) 12424 { 12425 return false; 12426 } 12427 break; 12428 } 12429 12430 case token_type::value_unsigned: 12431 { 12432 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) 12433 { 12434 return false; 12435 } 12436 break; 12437 } 12438 12439 case token_type::parse_error: 12440 { 12441 // using "uninitialized" to avoid "expected" message 12442 return sax->parse_error(m_lexer.get_position(), 12443 m_lexer.get_token_string(), 12444 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); 12445 } 12446 12447 case token_type::uninitialized: 12448 case token_type::end_array: 12449 case token_type::end_object: 12450 case token_type::name_separator: 12451 case token_type::value_separator: 12452 case token_type::end_of_input: 12453 case token_type::literal_or_value: 12454 default: // the last token was unexpected 12455 { 12456 return sax->parse_error(m_lexer.get_position(), 12457 m_lexer.get_token_string(), 12458 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); 12459 } 12460 } 12461 } 12462 else 12463 { 12464 skip_to_state_evaluation = false; 12465 } 12466 12467 // we reached this line after we successfully parsed a value 12468 if (states.empty()) 12469 { 12470 // empty stack: we reached the end of the hierarchy: done 12471 return true; 12472 } 12473 12474 if (states.back()) // array 12475 { 12476 // comma -> next value 12477 if (get_token() == token_type::value_separator) 12478 { 12479 // parse a new value 12480 get_token(); 12481 continue; 12482 } 12483 12484 // closing ] 12485 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) 12486 { 12487 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 12488 { 12489 return false; 12490 } 12491 12492 // We are done with this array. Before we can parse a 12493 // new value, we need to evaluate the new state first. 12494 // By setting skip_to_state_evaluation to false, we 12495 // are effectively jumping to the beginning of this if. 12496 JSON_ASSERT(!states.empty()); 12497 states.pop_back(); 12498 skip_to_state_evaluation = true; 12499 continue; 12500 } 12501 12502 return sax->parse_error(m_lexer.get_position(), 12503 m_lexer.get_token_string(), 12504 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); 12505 } 12506 12507 // states.back() is false -> object 12508 12509 // comma -> next value 12510 if (get_token() == token_type::value_separator) 12511 { 12512 // parse key 12513 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) 12514 { 12515 return sax->parse_error(m_lexer.get_position(), 12516 m_lexer.get_token_string(), 12517 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 12518 } 12519 12520 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 12521 { 12522 return false; 12523 } 12524 12525 // parse separator (:) 12526 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 12527 { 12528 return sax->parse_error(m_lexer.get_position(), 12529 m_lexer.get_token_string(), 12530 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 12531 } 12532 12533 // parse values 12534 get_token(); 12535 continue; 12536 } 12537 12538 // closing } 12539 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) 12540 { 12541 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 12542 { 12543 return false; 12544 } 12545 12546 // We are done with this object. Before we can parse a 12547 // new value, we need to evaluate the new state first. 12548 // By setting skip_to_state_evaluation to false, we 12549 // are effectively jumping to the beginning of this if. 12550 JSON_ASSERT(!states.empty()); 12551 states.pop_back(); 12552 skip_to_state_evaluation = true; 12553 continue; 12554 } 12555 12556 return sax->parse_error(m_lexer.get_position(), 12557 m_lexer.get_token_string(), 12558 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); 12559 } 12560 } 12561 12562 /// get next token from lexer 12563 token_type get_token() 12564 { 12565 return last_token = m_lexer.scan(); 12566 } 12567 12568 std::string exception_message(const token_type expected, const std::string& context) 12569 { 12570 std::string error_msg = "syntax error "; 12571 12572 if (!context.empty()) 12573 { 12574 error_msg += concat("while parsing ", context, ' '); 12575 } 12576 12577 error_msg += "- "; 12578 12579 if (last_token == token_type::parse_error) 12580 { 12581 error_msg += concat(m_lexer.get_error_message(), "; last read: '", 12582 m_lexer.get_token_string(), '\''); 12583 } 12584 else 12585 { 12586 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); 12587 } 12588 12589 if (expected != token_type::uninitialized) 12590 { 12591 error_msg += concat("; expected ", lexer_t::token_type_name(expected)); 12592 } 12593 12594 return error_msg; 12595 } 12596 12597 private: 12598 /// callback function 12599 const parser_callback_t<BasicJsonType> callback = nullptr; 12600 /// the type of the last read token 12601 token_type last_token = token_type::uninitialized; 12602 /// the lexer 12603 lexer_t m_lexer; 12604 /// whether to throw exceptions in case of errors 12605 const bool allow_exceptions = true; 12606 }; 12607 12608 } // namespace detail 12609 NLOHMANN_JSON_NAMESPACE_END 12610 12611 // #include <nlohmann/detail/iterators/internal_iterator.hpp> 12612 // __ _____ _____ _____ 12613 // __| | __| | | | JSON for Modern C++ 12614 // | | |__ | | | | | | version 3.11.2 12615 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12616 // 12617 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 12618 // SPDX-License-Identifier: MIT 12619 12620 12621 12622 // #include <nlohmann/detail/abi_macros.hpp> 12623 12624 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 12625 // __ _____ _____ _____ 12626 // __| | __| | | | JSON for Modern C++ 12627 // | | |__ | | | | | | version 3.11.2 12628 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12629 // 12630 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 12631 // SPDX-License-Identifier: MIT 12632 12633 12634 12635 #include <cstddef> // ptrdiff_t 12636 #include <limits> // numeric_limits 12637 12638 // #include <nlohmann/detail/macro_scope.hpp> 12639 12640 12641 NLOHMANN_JSON_NAMESPACE_BEGIN 12642 namespace detail 12643 { 12644 12645 /* 12646 @brief an iterator for primitive JSON types 12647 12648 This class models an iterator for primitive JSON types (boolean, number, 12649 string). It's only purpose is to allow the iterator/const_iterator classes 12650 to "iterate" over primitive values. Internally, the iterator is modeled by 12651 a `difference_type` variable. Value begin_value (`0`) models the begin, 12652 end_value (`1`) models past the end. 12653 */ 12654 class primitive_iterator_t 12655 { 12656 private: 12657 using difference_type = std::ptrdiff_t; 12658 static constexpr difference_type begin_value = 0; 12659 static constexpr difference_type end_value = begin_value + 1; 12660 12661 JSON_PRIVATE_UNLESS_TESTED: 12662 /// iterator as signed integer type 12663 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)(); 12664 12665 public: 12666 constexpr difference_type get_value() const noexcept 12667 { 12668 return m_it; 12669 } 12670 12671 /// set iterator to a defined beginning 12672 void set_begin() noexcept 12673 { 12674 m_it = begin_value; 12675 } 12676 12677 /// set iterator to a defined past the end 12678 void set_end() noexcept 12679 { 12680 m_it = end_value; 12681 } 12682 12683 /// return whether the iterator can be dereferenced 12684 constexpr bool is_begin() const noexcept 12685 { 12686 return m_it == begin_value; 12687 } 12688 12689 /// return whether the iterator is at end 12690 constexpr bool is_end() const noexcept 12691 { 12692 return m_it == end_value; 12693 } 12694 12695 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12696 { 12697 return lhs.m_it == rhs.m_it; 12698 } 12699 12700 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12701 { 12702 return lhs.m_it < rhs.m_it; 12703 } 12704 12705 primitive_iterator_t operator+(difference_type n) noexcept 12706 { 12707 auto result = *this; 12708 result += n; 12709 return result; 12710 } 12711 12712 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12713 { 12714 return lhs.m_it - rhs.m_it; 12715 } 12716 12717 primitive_iterator_t& operator++() noexcept 12718 { 12719 ++m_it; 12720 return *this; 12721 } 12722 12723 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) 12724 { 12725 auto result = *this; 12726 ++m_it; 12727 return result; 12728 } 12729 12730 primitive_iterator_t& operator--() noexcept 12731 { 12732 --m_it; 12733 return *this; 12734 } 12735 12736 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) 12737 { 12738 auto result = *this; 12739 --m_it; 12740 return result; 12741 } 12742 12743 primitive_iterator_t& operator+=(difference_type n) noexcept 12744 { 12745 m_it += n; 12746 return *this; 12747 } 12748 12749 primitive_iterator_t& operator-=(difference_type n) noexcept 12750 { 12751 m_it -= n; 12752 return *this; 12753 } 12754 }; 12755 12756 } // namespace detail 12757 NLOHMANN_JSON_NAMESPACE_END 12758 12759 12760 NLOHMANN_JSON_NAMESPACE_BEGIN 12761 namespace detail 12762 { 12763 12764 /*! 12765 @brief an iterator value 12766 12767 @note This structure could easily be a union, but MSVC currently does not allow 12768 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. 12769 */ 12770 template<typename BasicJsonType> struct internal_iterator 12771 { 12772 /// iterator for JSON objects 12773 typename BasicJsonType::object_t::iterator object_iterator {}; 12774 /// iterator for JSON arrays 12775 typename BasicJsonType::array_t::iterator array_iterator {}; 12776 /// generic iterator for all other types 12777 primitive_iterator_t primitive_iterator {}; 12778 }; 12779 12780 } // namespace detail 12781 NLOHMANN_JSON_NAMESPACE_END 12782 12783 // #include <nlohmann/detail/iterators/iter_impl.hpp> 12784 // __ _____ _____ _____ 12785 // __| | __| | | | JSON for Modern C++ 12786 // | | |__ | | | | | | version 3.11.2 12787 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12788 // 12789 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 12790 // SPDX-License-Identifier: MIT 12791 12792 12793 12794 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next 12795 #include <type_traits> // conditional, is_const, remove_const 12796 12797 // #include <nlohmann/detail/exceptions.hpp> 12798 12799 // #include <nlohmann/detail/iterators/internal_iterator.hpp> 12800 12801 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 12802 12803 // #include <nlohmann/detail/macro_scope.hpp> 12804 12805 // #include <nlohmann/detail/meta/cpp_future.hpp> 12806 12807 // #include <nlohmann/detail/meta/type_traits.hpp> 12808 12809 // #include <nlohmann/detail/value_t.hpp> 12810 12811 12812 NLOHMANN_JSON_NAMESPACE_BEGIN 12813 namespace detail 12814 { 12815 12816 // forward declare, to be able to friend it later on 12817 template<typename IteratorType> class iteration_proxy; 12818 template<typename IteratorType> class iteration_proxy_value; 12819 12820 /*! 12821 @brief a template for a bidirectional iterator for the @ref basic_json class 12822 This class implements a both iterators (iterator and const_iterator) for the 12823 @ref basic_json class. 12824 @note An iterator is called *initialized* when a pointer to a JSON value has 12825 been set (e.g., by a constructor or a copy assignment). If the iterator is 12826 default-constructed, it is *uninitialized* and most methods are undefined. 12827 **The library uses assertions to detect calls on uninitialized iterators.** 12828 @requirement The class satisfies the following concept requirements: 12829 - 12830 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 12831 The iterator that can be moved can be moved in both directions (i.e. 12832 incremented and decremented). 12833 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional 12834 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) 12835 */ 12836 template<typename BasicJsonType> 12837 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 12838 { 12839 /// the iterator with BasicJsonType of different const-ness 12840 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; 12841 /// allow basic_json to access private members 12842 friend other_iter_impl; 12843 friend BasicJsonType; 12844 friend iteration_proxy<iter_impl>; 12845 friend iteration_proxy_value<iter_impl>; 12846 12847 using object_t = typename BasicJsonType::object_t; 12848 using array_t = typename BasicJsonType::array_t; 12849 // make sure BasicJsonType is basic_json or const basic_json 12850 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, 12851 "iter_impl only accepts (const) basic_json"); 12852 // superficial check for the LegacyBidirectionalIterator named requirement 12853 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value 12854 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value, 12855 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); 12856 12857 public: 12858 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. 12859 /// The C++ Standard has never required user-defined iterators to derive from std::iterator. 12860 /// A user-defined iterator should provide publicly accessible typedefs named 12861 /// iterator_category, value_type, difference_type, pointer, and reference. 12862 /// Note that value_type is required to be non-const, even for constant iterators. 12863 using iterator_category = std::bidirectional_iterator_tag; 12864 12865 /// the type of the values when the iterator is dereferenced 12866 using value_type = typename BasicJsonType::value_type; 12867 /// a type to represent differences between iterators 12868 using difference_type = typename BasicJsonType::difference_type; 12869 /// defines a pointer to the type iterated over (value_type) 12870 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value, 12871 typename BasicJsonType::const_pointer, 12872 typename BasicJsonType::pointer>::type; 12873 /// defines a reference to the type iterated over (value_type) 12874 using reference = 12875 typename std::conditional<std::is_const<BasicJsonType>::value, 12876 typename BasicJsonType::const_reference, 12877 typename BasicJsonType::reference>::type; 12878 12879 iter_impl() = default; 12880 ~iter_impl() = default; 12881 iter_impl(iter_impl&&) noexcept = default; 12882 iter_impl& operator=(iter_impl&&) noexcept = default; 12883 12884 /*! 12885 @brief constructor for a given JSON instance 12886 @param[in] object pointer to a JSON object for this iterator 12887 @pre object != nullptr 12888 @post The iterator is initialized; i.e. `m_object != nullptr`. 12889 */ 12890 explicit iter_impl(pointer object) noexcept : m_object(object) 12891 { 12892 JSON_ASSERT(m_object != nullptr); 12893 12894 switch (m_object->m_type) 12895 { 12896 case value_t::object: 12897 { 12898 m_it.object_iterator = typename object_t::iterator(); 12899 break; 12900 } 12901 12902 case value_t::array: 12903 { 12904 m_it.array_iterator = typename array_t::iterator(); 12905 break; 12906 } 12907 12908 case value_t::null: 12909 case value_t::string: 12910 case value_t::boolean: 12911 case value_t::number_integer: 12912 case value_t::number_unsigned: 12913 case value_t::number_float: 12914 case value_t::binary: 12915 case value_t::discarded: 12916 default: 12917 { 12918 m_it.primitive_iterator = primitive_iterator_t(); 12919 break; 12920 } 12921 } 12922 } 12923 12924 /*! 12925 @note The conventional copy constructor and copy assignment are implicitly 12926 defined. Combined with the following converting constructor and 12927 assignment, they support: (1) copy from iterator to iterator, (2) 12928 copy from const iterator to const iterator, and (3) conversion from 12929 iterator to const iterator. However conversion from const iterator 12930 to iterator is not defined. 12931 */ 12932 12933 /*! 12934 @brief const copy constructor 12935 @param[in] other const iterator to copy from 12936 @note This copy constructor had to be defined explicitly to circumvent a bug 12937 occurring on msvc v19.0 compiler (VS 2015) debug build. For more 12938 information refer to: https://github.com/nlohmann/json/issues/1608 12939 */ 12940 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept 12941 : m_object(other.m_object), m_it(other.m_it) 12942 {} 12943 12944 /*! 12945 @brief converting assignment 12946 @param[in] other const iterator to copy from 12947 @return const/non-const iterator 12948 @note It is not checked whether @a other is initialized. 12949 */ 12950 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept 12951 { 12952 if (&other != this) 12953 { 12954 m_object = other.m_object; 12955 m_it = other.m_it; 12956 } 12957 return *this; 12958 } 12959 12960 /*! 12961 @brief converting constructor 12962 @param[in] other non-const iterator to copy from 12963 @note It is not checked whether @a other is initialized. 12964 */ 12965 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept 12966 : m_object(other.m_object), m_it(other.m_it) 12967 {} 12968 12969 /*! 12970 @brief converting assignment 12971 @param[in] other non-const iterator to copy from 12972 @return const/non-const iterator 12973 @note It is not checked whether @a other is initialized. 12974 */ 12975 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp) 12976 { 12977 m_object = other.m_object; 12978 m_it = other.m_it; 12979 return *this; 12980 } 12981 12982 JSON_PRIVATE_UNLESS_TESTED: 12983 /*! 12984 @brief set the iterator to the first value 12985 @pre The iterator is initialized; i.e. `m_object != nullptr`. 12986 */ 12987 void set_begin() noexcept 12988 { 12989 JSON_ASSERT(m_object != nullptr); 12990 12991 switch (m_object->m_type) 12992 { 12993 case value_t::object: 12994 { 12995 m_it.object_iterator = m_object->m_value.object->begin(); 12996 break; 12997 } 12998 12999 case value_t::array: 13000 { 13001 m_it.array_iterator = m_object->m_value.array->begin(); 13002 break; 13003 } 13004 13005 case value_t::null: 13006 { 13007 // set to end so begin()==end() is true: null is empty 13008 m_it.primitive_iterator.set_end(); 13009 break; 13010 } 13011 13012 case value_t::string: 13013 case value_t::boolean: 13014 case value_t::number_integer: 13015 case value_t::number_unsigned: 13016 case value_t::number_float: 13017 case value_t::binary: 13018 case value_t::discarded: 13019 default: 13020 { 13021 m_it.primitive_iterator.set_begin(); 13022 break; 13023 } 13024 } 13025 } 13026 13027 /*! 13028 @brief set the iterator past the last value 13029 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13030 */ 13031 void set_end() noexcept 13032 { 13033 JSON_ASSERT(m_object != nullptr); 13034 13035 switch (m_object->m_type) 13036 { 13037 case value_t::object: 13038 { 13039 m_it.object_iterator = m_object->m_value.object->end(); 13040 break; 13041 } 13042 13043 case value_t::array: 13044 { 13045 m_it.array_iterator = m_object->m_value.array->end(); 13046 break; 13047 } 13048 13049 case value_t::null: 13050 case value_t::string: 13051 case value_t::boolean: 13052 case value_t::number_integer: 13053 case value_t::number_unsigned: 13054 case value_t::number_float: 13055 case value_t::binary: 13056 case value_t::discarded: 13057 default: 13058 { 13059 m_it.primitive_iterator.set_end(); 13060 break; 13061 } 13062 } 13063 } 13064 13065 public: 13066 /*! 13067 @brief return a reference to the value pointed to by the iterator 13068 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13069 */ 13070 reference operator*() const 13071 { 13072 JSON_ASSERT(m_object != nullptr); 13073 13074 switch (m_object->m_type) 13075 { 13076 case value_t::object: 13077 { 13078 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); 13079 return m_it.object_iterator->second; 13080 } 13081 13082 case value_t::array: 13083 { 13084 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); 13085 return *m_it.array_iterator; 13086 } 13087 13088 case value_t::null: 13089 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13090 13091 case value_t::string: 13092 case value_t::boolean: 13093 case value_t::number_integer: 13094 case value_t::number_unsigned: 13095 case value_t::number_float: 13096 case value_t::binary: 13097 case value_t::discarded: 13098 default: 13099 { 13100 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) 13101 { 13102 return *m_object; 13103 } 13104 13105 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13106 } 13107 } 13108 } 13109 13110 /*! 13111 @brief dereference the iterator 13112 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13113 */ 13114 pointer operator->() const 13115 { 13116 JSON_ASSERT(m_object != nullptr); 13117 13118 switch (m_object->m_type) 13119 { 13120 case value_t::object: 13121 { 13122 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); 13123 return &(m_it.object_iterator->second); 13124 } 13125 13126 case value_t::array: 13127 { 13128 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); 13129 return &*m_it.array_iterator; 13130 } 13131 13132 case value_t::null: 13133 case value_t::string: 13134 case value_t::boolean: 13135 case value_t::number_integer: 13136 case value_t::number_unsigned: 13137 case value_t::number_float: 13138 case value_t::binary: 13139 case value_t::discarded: 13140 default: 13141 { 13142 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) 13143 { 13144 return m_object; 13145 } 13146 13147 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13148 } 13149 } 13150 } 13151 13152 /*! 13153 @brief post-increment (it++) 13154 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13155 */ 13156 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) 13157 { 13158 auto result = *this; 13159 ++(*this); 13160 return result; 13161 } 13162 13163 /*! 13164 @brief pre-increment (++it) 13165 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13166 */ 13167 iter_impl& operator++() 13168 { 13169 JSON_ASSERT(m_object != nullptr); 13170 13171 switch (m_object->m_type) 13172 { 13173 case value_t::object: 13174 { 13175 std::advance(m_it.object_iterator, 1); 13176 break; 13177 } 13178 13179 case value_t::array: 13180 { 13181 std::advance(m_it.array_iterator, 1); 13182 break; 13183 } 13184 13185 case value_t::null: 13186 case value_t::string: 13187 case value_t::boolean: 13188 case value_t::number_integer: 13189 case value_t::number_unsigned: 13190 case value_t::number_float: 13191 case value_t::binary: 13192 case value_t::discarded: 13193 default: 13194 { 13195 ++m_it.primitive_iterator; 13196 break; 13197 } 13198 } 13199 13200 return *this; 13201 } 13202 13203 /*! 13204 @brief post-decrement (it--) 13205 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13206 */ 13207 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) 13208 { 13209 auto result = *this; 13210 --(*this); 13211 return result; 13212 } 13213 13214 /*! 13215 @brief pre-decrement (--it) 13216 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13217 */ 13218 iter_impl& operator--() 13219 { 13220 JSON_ASSERT(m_object != nullptr); 13221 13222 switch (m_object->m_type) 13223 { 13224 case value_t::object: 13225 { 13226 std::advance(m_it.object_iterator, -1); 13227 break; 13228 } 13229 13230 case value_t::array: 13231 { 13232 std::advance(m_it.array_iterator, -1); 13233 break; 13234 } 13235 13236 case value_t::null: 13237 case value_t::string: 13238 case value_t::boolean: 13239 case value_t::number_integer: 13240 case value_t::number_unsigned: 13241 case value_t::number_float: 13242 case value_t::binary: 13243 case value_t::discarded: 13244 default: 13245 { 13246 --m_it.primitive_iterator; 13247 break; 13248 } 13249 } 13250 13251 return *this; 13252 } 13253 13254 /*! 13255 @brief comparison: equal 13256 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13257 */ 13258 template < 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 > 13259 bool operator==(const IterImpl& other) const 13260 { 13261 // if objects are not the same, the comparison is undefined 13262 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) 13263 { 13264 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); 13265 } 13266 13267 JSON_ASSERT(m_object != nullptr); 13268 13269 switch (m_object->m_type) 13270 { 13271 case value_t::object: 13272 return (m_it.object_iterator == other.m_it.object_iterator); 13273 13274 case value_t::array: 13275 return (m_it.array_iterator == other.m_it.array_iterator); 13276 13277 case value_t::null: 13278 case value_t::string: 13279 case value_t::boolean: 13280 case value_t::number_integer: 13281 case value_t::number_unsigned: 13282 case value_t::number_float: 13283 case value_t::binary: 13284 case value_t::discarded: 13285 default: 13286 return (m_it.primitive_iterator == other.m_it.primitive_iterator); 13287 } 13288 } 13289 13290 /*! 13291 @brief comparison: not equal 13292 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13293 */ 13294 template < 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 > 13295 bool operator!=(const IterImpl& other) const 13296 { 13297 return !operator==(other); 13298 } 13299 13300 /*! 13301 @brief comparison: smaller 13302 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13303 */ 13304 bool operator<(const iter_impl& other) const 13305 { 13306 // if objects are not the same, the comparison is undefined 13307 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) 13308 { 13309 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); 13310 } 13311 13312 JSON_ASSERT(m_object != nullptr); 13313 13314 switch (m_object->m_type) 13315 { 13316 case value_t::object: 13317 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); 13318 13319 case value_t::array: 13320 return (m_it.array_iterator < other.m_it.array_iterator); 13321 13322 case value_t::null: 13323 case value_t::string: 13324 case value_t::boolean: 13325 case value_t::number_integer: 13326 case value_t::number_unsigned: 13327 case value_t::number_float: 13328 case value_t::binary: 13329 case value_t::discarded: 13330 default: 13331 return (m_it.primitive_iterator < other.m_it.primitive_iterator); 13332 } 13333 } 13334 13335 /*! 13336 @brief comparison: less than or equal 13337 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13338 */ 13339 bool operator<=(const iter_impl& other) const 13340 { 13341 return !other.operator < (*this); 13342 } 13343 13344 /*! 13345 @brief comparison: greater than 13346 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13347 */ 13348 bool operator>(const iter_impl& other) const 13349 { 13350 return !operator<=(other); 13351 } 13352 13353 /*! 13354 @brief comparison: greater than or equal 13355 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13356 */ 13357 bool operator>=(const iter_impl& other) const 13358 { 13359 return !operator<(other); 13360 } 13361 13362 /*! 13363 @brief add to iterator 13364 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13365 */ 13366 iter_impl& operator+=(difference_type i) 13367 { 13368 JSON_ASSERT(m_object != nullptr); 13369 13370 switch (m_object->m_type) 13371 { 13372 case value_t::object: 13373 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); 13374 13375 case value_t::array: 13376 { 13377 std::advance(m_it.array_iterator, i); 13378 break; 13379 } 13380 13381 case value_t::null: 13382 case value_t::string: 13383 case value_t::boolean: 13384 case value_t::number_integer: 13385 case value_t::number_unsigned: 13386 case value_t::number_float: 13387 case value_t::binary: 13388 case value_t::discarded: 13389 default: 13390 { 13391 m_it.primitive_iterator += i; 13392 break; 13393 } 13394 } 13395 13396 return *this; 13397 } 13398 13399 /*! 13400 @brief subtract from iterator 13401 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13402 */ 13403 iter_impl& operator-=(difference_type i) 13404 { 13405 return operator+=(-i); 13406 } 13407 13408 /*! 13409 @brief add to iterator 13410 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13411 */ 13412 iter_impl operator+(difference_type i) const 13413 { 13414 auto result = *this; 13415 result += i; 13416 return result; 13417 } 13418 13419 /*! 13420 @brief addition of distance and iterator 13421 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13422 */ 13423 friend iter_impl operator+(difference_type i, const iter_impl& it) 13424 { 13425 auto result = it; 13426 result += i; 13427 return result; 13428 } 13429 13430 /*! 13431 @brief subtract from iterator 13432 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13433 */ 13434 iter_impl operator-(difference_type i) const 13435 { 13436 auto result = *this; 13437 result -= i; 13438 return result; 13439 } 13440 13441 /*! 13442 @brief return difference 13443 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13444 */ 13445 difference_type operator-(const iter_impl& other) const 13446 { 13447 JSON_ASSERT(m_object != nullptr); 13448 13449 switch (m_object->m_type) 13450 { 13451 case value_t::object: 13452 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); 13453 13454 case value_t::array: 13455 return m_it.array_iterator - other.m_it.array_iterator; 13456 13457 case value_t::null: 13458 case value_t::string: 13459 case value_t::boolean: 13460 case value_t::number_integer: 13461 case value_t::number_unsigned: 13462 case value_t::number_float: 13463 case value_t::binary: 13464 case value_t::discarded: 13465 default: 13466 return m_it.primitive_iterator - other.m_it.primitive_iterator; 13467 } 13468 } 13469 13470 /*! 13471 @brief access to successor 13472 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13473 */ 13474 reference operator[](difference_type n) const 13475 { 13476 JSON_ASSERT(m_object != nullptr); 13477 13478 switch (m_object->m_type) 13479 { 13480 case value_t::object: 13481 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); 13482 13483 case value_t::array: 13484 return *std::next(m_it.array_iterator, n); 13485 13486 case value_t::null: 13487 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13488 13489 case value_t::string: 13490 case value_t::boolean: 13491 case value_t::number_integer: 13492 case value_t::number_unsigned: 13493 case value_t::number_float: 13494 case value_t::binary: 13495 case value_t::discarded: 13496 default: 13497 { 13498 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) 13499 { 13500 return *m_object; 13501 } 13502 13503 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13504 } 13505 } 13506 } 13507 13508 /*! 13509 @brief return the key of an object iterator 13510 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13511 */ 13512 const typename object_t::key_type& key() const 13513 { 13514 JSON_ASSERT(m_object != nullptr); 13515 13516 if (JSON_HEDLEY_LIKELY(m_object->is_object())) 13517 { 13518 return m_it.object_iterator->first; 13519 } 13520 13521 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); 13522 } 13523 13524 /*! 13525 @brief return the value of an iterator 13526 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13527 */ 13528 reference value() const 13529 { 13530 return operator*(); 13531 } 13532 13533 JSON_PRIVATE_UNLESS_TESTED: 13534 /// associated JSON instance 13535 pointer m_object = nullptr; 13536 /// the actual iterator of the associated instance 13537 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {}; 13538 }; 13539 13540 } // namespace detail 13541 NLOHMANN_JSON_NAMESPACE_END 13542 13543 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> 13544 13545 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> 13546 // __ _____ _____ _____ 13547 // __| | __| | | | JSON for Modern C++ 13548 // | | |__ | | | | | | version 3.11.2 13549 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13550 // 13551 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 13552 // SPDX-License-Identifier: MIT 13553 13554 13555 13556 #include <cstddef> // ptrdiff_t 13557 #include <iterator> // reverse_iterator 13558 #include <utility> // declval 13559 13560 // #include <nlohmann/detail/abi_macros.hpp> 13561 13562 13563 NLOHMANN_JSON_NAMESPACE_BEGIN 13564 namespace detail 13565 { 13566 13567 ////////////////////// 13568 // reverse_iterator // 13569 ////////////////////// 13570 13571 /*! 13572 @brief a template for a reverse iterator class 13573 13574 @tparam Base the base iterator type to reverse. Valid types are @ref 13575 iterator (to create @ref reverse_iterator) and @ref const_iterator (to 13576 create @ref const_reverse_iterator). 13577 13578 @requirement The class satisfies the following concept requirements: 13579 - 13580 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 13581 The iterator that can be moved can be moved in both directions (i.e. 13582 incremented and decremented). 13583 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): 13584 It is possible to write to the pointed-to element (only if @a Base is 13585 @ref iterator). 13586 13587 @since version 1.0.0 13588 */ 13589 template<typename Base> 13590 class json_reverse_iterator : public std::reverse_iterator<Base> 13591 { 13592 public: 13593 using difference_type = std::ptrdiff_t; 13594 /// shortcut to the reverse iterator adapter 13595 using base_iterator = std::reverse_iterator<Base>; 13596 /// the reference type for the pointed-to element 13597 using reference = typename Base::reference; 13598 13599 /// create reverse iterator from iterator 13600 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept 13601 : base_iterator(it) {} 13602 13603 /// create reverse iterator from base class 13604 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} 13605 13606 /// post-increment (it++) 13607 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) 13608 { 13609 return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); 13610 } 13611 13612 /// pre-increment (++it) 13613 json_reverse_iterator& operator++() 13614 { 13615 return static_cast<json_reverse_iterator&>(base_iterator::operator++()); 13616 } 13617 13618 /// post-decrement (it--) 13619 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) 13620 { 13621 return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); 13622 } 13623 13624 /// pre-decrement (--it) 13625 json_reverse_iterator& operator--() 13626 { 13627 return static_cast<json_reverse_iterator&>(base_iterator::operator--()); 13628 } 13629 13630 /// add to iterator 13631 json_reverse_iterator& operator+=(difference_type i) 13632 { 13633 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i)); 13634 } 13635 13636 /// add to iterator 13637 json_reverse_iterator operator+(difference_type i) const 13638 { 13639 return static_cast<json_reverse_iterator>(base_iterator::operator+(i)); 13640 } 13641 13642 /// subtract from iterator 13643 json_reverse_iterator operator-(difference_type i) const 13644 { 13645 return static_cast<json_reverse_iterator>(base_iterator::operator-(i)); 13646 } 13647 13648 /// return difference 13649 difference_type operator-(const json_reverse_iterator& other) const 13650 { 13651 return base_iterator(*this) - base_iterator(other); 13652 } 13653 13654 /// access to successor 13655 reference operator[](difference_type n) const 13656 { 13657 return *(this->operator+(n)); 13658 } 13659 13660 /// return the key of an object iterator 13661 auto key() const -> decltype(std::declval<Base>().key()) 13662 { 13663 auto it = --this->base(); 13664 return it.key(); 13665 } 13666 13667 /// return the value of an iterator 13668 reference value() const 13669 { 13670 auto it = --this->base(); 13671 return it.operator * (); 13672 } 13673 }; 13674 13675 } // namespace detail 13676 NLOHMANN_JSON_NAMESPACE_END 13677 13678 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 13679 13680 // #include <nlohmann/detail/json_custom_base_class.hpp> 13681 13682 13683 #include <type_traits> // conditional, is_same 13684 13685 // #include <nlohmann/detail/abi_macros.hpp> 13686 13687 13688 NLOHMANN_JSON_NAMESPACE_BEGIN 13689 namespace detail 13690 { 13691 13692 /*! 13693 @brief Default base class of the @ref basic_json class. 13694 13695 So that the correct implementations of the copy / move ctors / assign operators 13696 of @ref basic_json do not require complex case distinctions 13697 (no base class / custom base class used as customization point), 13698 @ref basic_json always has a base class. 13699 By default, this class is used because it is empty and thus has no effect 13700 on the behavior of @ref basic_json. 13701 */ 13702 struct json_default_base {}; 13703 13704 template<class T> 13705 using json_base_class = typename std::conditional < 13706 std::is_same<T, void>::value, 13707 json_default_base, 13708 T 13709 >::type; 13710 13711 } // namespace detail 13712 NLOHMANN_JSON_NAMESPACE_END 13713 13714 // #include <nlohmann/detail/json_pointer.hpp> 13715 // __ _____ _____ _____ 13716 // __| | __| | | | JSON for Modern C++ 13717 // | | |__ | | | | | | version 3.11.2 13718 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13719 // 13720 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 13721 // SPDX-License-Identifier: MIT 13722 13723 13724 13725 #include <algorithm> // all_of 13726 #include <cctype> // isdigit 13727 #include <cerrno> // errno, ERANGE 13728 #include <cstdlib> // strtoull 13729 #ifndef JSON_NO_IO 13730 #include <iosfwd> // ostream 13731 #endif // JSON_NO_IO 13732 #include <limits> // max 13733 #include <numeric> // accumulate 13734 #include <string> // string 13735 #include <utility> // move 13736 #include <vector> // vector 13737 13738 // #include <nlohmann/detail/exceptions.hpp> 13739 13740 // #include <nlohmann/detail/macro_scope.hpp> 13741 13742 // #include <nlohmann/detail/string_concat.hpp> 13743 13744 // #include <nlohmann/detail/string_escape.hpp> 13745 13746 // #include <nlohmann/detail/value_t.hpp> 13747 13748 13749 NLOHMANN_JSON_NAMESPACE_BEGIN 13750 13751 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 13752 /// @sa https://json.nlohmann.me/api/json_pointer/ 13753 template<typename RefStringType> 13754 class json_pointer 13755 { 13756 // allow basic_json to access private members 13757 NLOHMANN_BASIC_JSON_TPL_DECLARATION 13758 friend class basic_json; 13759 13760 template<typename> 13761 friend class json_pointer; 13762 13763 template<typename T> 13764 struct string_t_helper 13765 { 13766 using type = T; 13767 }; 13768 13769 NLOHMANN_BASIC_JSON_TPL_DECLARATION 13770 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL> 13771 { 13772 using type = StringType; 13773 }; 13774 13775 public: 13776 // for backwards compatibility accept BasicJsonType 13777 using string_t = typename string_t_helper<RefStringType>::type; 13778 13779 /// @brief create JSON pointer 13780 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ 13781 explicit json_pointer(const string_t& s = "") 13782 : reference_tokens(split(s)) 13783 {} 13784 13785 /// @brief return a string representation of the JSON pointer 13786 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ 13787 string_t to_string() const 13788 { 13789 return std::accumulate(reference_tokens.begin(), reference_tokens.end(), 13790 string_t{}, 13791 [](const string_t& a, const string_t& b) 13792 { 13793 return detail::concat(a, '/', detail::escape(b)); 13794 }); 13795 } 13796 13797 /// @brief return a string representation of the JSON pointer 13798 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ 13799 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) 13800 operator string_t() const 13801 { 13802 return to_string(); 13803 } 13804 13805 #ifndef JSON_NO_IO 13806 /// @brief write string representation of the JSON pointer to stream 13807 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 13808 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) 13809 { 13810 o << ptr.to_string(); 13811 return o; 13812 } 13813 #endif 13814 13815 /// @brief append another JSON pointer at the end of this JSON pointer 13816 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 13817 json_pointer& operator/=(const json_pointer& ptr) 13818 { 13819 reference_tokens.insert(reference_tokens.end(), 13820 ptr.reference_tokens.begin(), 13821 ptr.reference_tokens.end()); 13822 return *this; 13823 } 13824 13825 /// @brief append an unescaped reference token at the end of this JSON pointer 13826 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 13827 json_pointer& operator/=(string_t token) 13828 { 13829 push_back(std::move(token)); 13830 return *this; 13831 } 13832 13833 /// @brief append an array index at the end of this JSON pointer 13834 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 13835 json_pointer& operator/=(std::size_t array_idx) 13836 { 13837 return *this /= std::to_string(array_idx); 13838 } 13839 13840 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer 13841 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 13842 friend json_pointer operator/(const json_pointer& lhs, 13843 const json_pointer& rhs) 13844 { 13845 return json_pointer(lhs) /= rhs; 13846 } 13847 13848 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer 13849 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 13850 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) 13851 { 13852 return json_pointer(lhs) /= std::move(token); 13853 } 13854 13855 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer 13856 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 13857 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) 13858 { 13859 return json_pointer(lhs) /= array_idx; 13860 } 13861 13862 /// @brief returns the parent of this JSON pointer 13863 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ 13864 json_pointer parent_pointer() const 13865 { 13866 if (empty()) 13867 { 13868 return *this; 13869 } 13870 13871 json_pointer res = *this; 13872 res.pop_back(); 13873 return res; 13874 } 13875 13876 /// @brief remove last reference token 13877 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ 13878 void pop_back() 13879 { 13880 if (JSON_HEDLEY_UNLIKELY(empty())) 13881 { 13882 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 13883 } 13884 13885 reference_tokens.pop_back(); 13886 } 13887 13888 /// @brief return last reference token 13889 /// @sa https://json.nlohmann.me/api/json_pointer/back/ 13890 const string_t& back() const 13891 { 13892 if (JSON_HEDLEY_UNLIKELY(empty())) 13893 { 13894 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 13895 } 13896 13897 return reference_tokens.back(); 13898 } 13899 13900 /// @brief append an unescaped token at the end of the reference pointer 13901 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 13902 void push_back(const string_t& token) 13903 { 13904 reference_tokens.push_back(token); 13905 } 13906 13907 /// @brief append an unescaped token at the end of the reference pointer 13908 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 13909 void push_back(string_t&& token) 13910 { 13911 reference_tokens.push_back(std::move(token)); 13912 } 13913 13914 /// @brief return whether pointer points to the root document 13915 /// @sa https://json.nlohmann.me/api/json_pointer/empty/ 13916 bool empty() const noexcept 13917 { 13918 return reference_tokens.empty(); 13919 } 13920 13921 private: 13922 /*! 13923 @param[in] s reference token to be converted into an array index 13924 13925 @return integer representation of @a s 13926 13927 @throw parse_error.106 if an array index begins with '0' 13928 @throw parse_error.109 if an array index begins not with a digit 13929 @throw out_of_range.404 if string @a s could not be converted to an integer 13930 @throw out_of_range.410 if an array index exceeds size_type 13931 */ 13932 template<typename BasicJsonType> 13933 static typename BasicJsonType::size_type array_index(const string_t& s) 13934 { 13935 using size_type = typename BasicJsonType::size_type; 13936 13937 // error condition (cf. RFC 6901, Sect. 4) 13938 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) 13939 { 13940 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); 13941 } 13942 13943 // error condition (cf. RFC 6901, Sect. 4) 13944 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) 13945 { 13946 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); 13947 } 13948 13949 const char* p = s.c_str(); 13950 char* p_end = nullptr; 13951 errno = 0; // strtoull doesn't reset errno 13952 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) 13953 if (p == p_end // invalid input or empty string 13954 || errno == ERANGE // out of range 13955 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read 13956 { 13957 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); 13958 } 13959 13960 // only triggered on special platforms (like 32bit), see also 13961 // https://github.com/nlohmann/json/pull/2203 13962 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int) 13963 { 13964 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE 13965 } 13966 13967 return static_cast<size_type>(res); 13968 } 13969 13970 JSON_PRIVATE_UNLESS_TESTED: 13971 json_pointer top() const 13972 { 13973 if (JSON_HEDLEY_UNLIKELY(empty())) 13974 { 13975 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 13976 } 13977 13978 json_pointer result = *this; 13979 result.reference_tokens = {reference_tokens[0]}; 13980 return result; 13981 } 13982 13983 private: 13984 /*! 13985 @brief create and return a reference to the pointed to value 13986 13987 @complexity Linear in the number of reference tokens. 13988 13989 @throw parse_error.109 if array index is not a number 13990 @throw type_error.313 if value cannot be unflattened 13991 */ 13992 template<typename BasicJsonType> 13993 BasicJsonType& get_and_create(BasicJsonType& j) const 13994 { 13995 auto* result = &j; 13996 13997 // in case no reference tokens exist, return a reference to the JSON value 13998 // j which will be overwritten by a primitive value 13999 for (const auto& reference_token : reference_tokens) 14000 { 14001 switch (result->type()) 14002 { 14003 case detail::value_t::null: 14004 { 14005 if (reference_token == "0") 14006 { 14007 // start a new array if reference token is 0 14008 result = &result->operator[](0); 14009 } 14010 else 14011 { 14012 // start a new object otherwise 14013 result = &result->operator[](reference_token); 14014 } 14015 break; 14016 } 14017 14018 case detail::value_t::object: 14019 { 14020 // create an entry in the object 14021 result = &result->operator[](reference_token); 14022 break; 14023 } 14024 14025 case detail::value_t::array: 14026 { 14027 // create an entry in the array 14028 result = &result->operator[](array_index<BasicJsonType>(reference_token)); 14029 break; 14030 } 14031 14032 /* 14033 The following code is only reached if there exists a reference 14034 token _and_ the current value is primitive. In this case, we have 14035 an error situation, because primitive values may only occur as 14036 single value; that is, with an empty list of reference tokens. 14037 */ 14038 case detail::value_t::string: 14039 case detail::value_t::boolean: 14040 case detail::value_t::number_integer: 14041 case detail::value_t::number_unsigned: 14042 case detail::value_t::number_float: 14043 case detail::value_t::binary: 14044 case detail::value_t::discarded: 14045 default: 14046 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); 14047 } 14048 } 14049 14050 return *result; 14051 } 14052 14053 /*! 14054 @brief return a reference to the pointed to value 14055 14056 @note This version does not throw if a value is not present, but tries to 14057 create nested values instead. For instance, calling this function 14058 with pointer `"/this/that"` on a null value is equivalent to calling 14059 `operator[]("this").operator[]("that")` on that value, effectively 14060 changing the null value to an object. 14061 14062 @param[in] ptr a JSON value 14063 14064 @return reference to the JSON value pointed to by the JSON pointer 14065 14066 @complexity Linear in the length of the JSON pointer. 14067 14068 @throw parse_error.106 if an array index begins with '0' 14069 @throw parse_error.109 if an array index was not a number 14070 @throw out_of_range.404 if the JSON pointer can not be resolved 14071 */ 14072 template<typename BasicJsonType> 14073 BasicJsonType& get_unchecked(BasicJsonType* ptr) const 14074 { 14075 for (const auto& reference_token : reference_tokens) 14076 { 14077 // convert null values to arrays or objects before continuing 14078 if (ptr->is_null()) 14079 { 14080 // check if reference token is a number 14081 const bool nums = 14082 std::all_of(reference_token.begin(), reference_token.end(), 14083 [](const unsigned char x) 14084 { 14085 return std::isdigit(x); 14086 }); 14087 14088 // change value to array for numbers or "-" or to object otherwise 14089 *ptr = (nums || reference_token == "-") 14090 ? detail::value_t::array 14091 : detail::value_t::object; 14092 } 14093 14094 switch (ptr->type()) 14095 { 14096 case detail::value_t::object: 14097 { 14098 // use unchecked object access 14099 ptr = &ptr->operator[](reference_token); 14100 break; 14101 } 14102 14103 case detail::value_t::array: 14104 { 14105 if (reference_token == "-") 14106 { 14107 // explicitly treat "-" as index beyond the end 14108 ptr = &ptr->operator[](ptr->m_value.array->size()); 14109 } 14110 else 14111 { 14112 // convert array index to number; unchecked access 14113 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); 14114 } 14115 break; 14116 } 14117 14118 case detail::value_t::null: 14119 case detail::value_t::string: 14120 case detail::value_t::boolean: 14121 case detail::value_t::number_integer: 14122 case detail::value_t::number_unsigned: 14123 case detail::value_t::number_float: 14124 case detail::value_t::binary: 14125 case detail::value_t::discarded: 14126 default: 14127 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14128 } 14129 } 14130 14131 return *ptr; 14132 } 14133 14134 /*! 14135 @throw parse_error.106 if an array index begins with '0' 14136 @throw parse_error.109 if an array index was not a number 14137 @throw out_of_range.402 if the array index '-' is used 14138 @throw out_of_range.404 if the JSON pointer can not be resolved 14139 */ 14140 template<typename BasicJsonType> 14141 BasicJsonType& get_checked(BasicJsonType* ptr) const 14142 { 14143 for (const auto& reference_token : reference_tokens) 14144 { 14145 switch (ptr->type()) 14146 { 14147 case detail::value_t::object: 14148 { 14149 // note: at performs range check 14150 ptr = &ptr->at(reference_token); 14151 break; 14152 } 14153 14154 case detail::value_t::array: 14155 { 14156 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14157 { 14158 // "-" always fails the range check 14159 JSON_THROW(detail::out_of_range::create(402, detail::concat( 14160 "array index '-' (", std::to_string(ptr->m_value.array->size()), 14161 ") is out of range"), ptr)); 14162 } 14163 14164 // note: at performs range check 14165 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); 14166 break; 14167 } 14168 14169 case detail::value_t::null: 14170 case detail::value_t::string: 14171 case detail::value_t::boolean: 14172 case detail::value_t::number_integer: 14173 case detail::value_t::number_unsigned: 14174 case detail::value_t::number_float: 14175 case detail::value_t::binary: 14176 case detail::value_t::discarded: 14177 default: 14178 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14179 } 14180 } 14181 14182 return *ptr; 14183 } 14184 14185 /*! 14186 @brief return a const reference to the pointed to value 14187 14188 @param[in] ptr a JSON value 14189 14190 @return const reference to the JSON value pointed to by the JSON 14191 pointer 14192 14193 @throw parse_error.106 if an array index begins with '0' 14194 @throw parse_error.109 if an array index was not a number 14195 @throw out_of_range.402 if the array index '-' is used 14196 @throw out_of_range.404 if the JSON pointer can not be resolved 14197 */ 14198 template<typename BasicJsonType> 14199 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const 14200 { 14201 for (const auto& reference_token : reference_tokens) 14202 { 14203 switch (ptr->type()) 14204 { 14205 case detail::value_t::object: 14206 { 14207 // use unchecked object access 14208 ptr = &ptr->operator[](reference_token); 14209 break; 14210 } 14211 14212 case detail::value_t::array: 14213 { 14214 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14215 { 14216 // "-" cannot be used for const access 14217 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); 14218 } 14219 14220 // use unchecked array access 14221 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); 14222 break; 14223 } 14224 14225 case detail::value_t::null: 14226 case detail::value_t::string: 14227 case detail::value_t::boolean: 14228 case detail::value_t::number_integer: 14229 case detail::value_t::number_unsigned: 14230 case detail::value_t::number_float: 14231 case detail::value_t::binary: 14232 case detail::value_t::discarded: 14233 default: 14234 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14235 } 14236 } 14237 14238 return *ptr; 14239 } 14240 14241 /*! 14242 @throw parse_error.106 if an array index begins with '0' 14243 @throw parse_error.109 if an array index was not a number 14244 @throw out_of_range.402 if the array index '-' is used 14245 @throw out_of_range.404 if the JSON pointer can not be resolved 14246 */ 14247 template<typename BasicJsonType> 14248 const BasicJsonType& get_checked(const BasicJsonType* ptr) const 14249 { 14250 for (const auto& reference_token : reference_tokens) 14251 { 14252 switch (ptr->type()) 14253 { 14254 case detail::value_t::object: 14255 { 14256 // note: at performs range check 14257 ptr = &ptr->at(reference_token); 14258 break; 14259 } 14260 14261 case detail::value_t::array: 14262 { 14263 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14264 { 14265 // "-" always fails the range check 14266 JSON_THROW(detail::out_of_range::create(402, detail::concat( 14267 "array index '-' (", std::to_string(ptr->m_value.array->size()), 14268 ") is out of range"), ptr)); 14269 } 14270 14271 // note: at performs range check 14272 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); 14273 break; 14274 } 14275 14276 case detail::value_t::null: 14277 case detail::value_t::string: 14278 case detail::value_t::boolean: 14279 case detail::value_t::number_integer: 14280 case detail::value_t::number_unsigned: 14281 case detail::value_t::number_float: 14282 case detail::value_t::binary: 14283 case detail::value_t::discarded: 14284 default: 14285 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14286 } 14287 } 14288 14289 return *ptr; 14290 } 14291 14292 /*! 14293 @throw parse_error.106 if an array index begins with '0' 14294 @throw parse_error.109 if an array index was not a number 14295 */ 14296 template<typename BasicJsonType> 14297 bool contains(const BasicJsonType* ptr) const 14298 { 14299 for (const auto& reference_token : reference_tokens) 14300 { 14301 switch (ptr->type()) 14302 { 14303 case detail::value_t::object: 14304 { 14305 if (!ptr->contains(reference_token)) 14306 { 14307 // we did not find the key in the object 14308 return false; 14309 } 14310 14311 ptr = &ptr->operator[](reference_token); 14312 break; 14313 } 14314 14315 case detail::value_t::array: 14316 { 14317 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14318 { 14319 // "-" always fails the range check 14320 return false; 14321 } 14322 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) 14323 { 14324 // invalid char 14325 return false; 14326 } 14327 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) 14328 { 14329 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) 14330 { 14331 // first char should be between '1' and '9' 14332 return false; 14333 } 14334 for (std::size_t i = 1; i < reference_token.size(); i++) 14335 { 14336 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) 14337 { 14338 // other char should be between '0' and '9' 14339 return false; 14340 } 14341 } 14342 } 14343 14344 const auto idx = array_index<BasicJsonType>(reference_token); 14345 if (idx >= ptr->size()) 14346 { 14347 // index out of range 14348 return false; 14349 } 14350 14351 ptr = &ptr->operator[](idx); 14352 break; 14353 } 14354 14355 case detail::value_t::null: 14356 case detail::value_t::string: 14357 case detail::value_t::boolean: 14358 case detail::value_t::number_integer: 14359 case detail::value_t::number_unsigned: 14360 case detail::value_t::number_float: 14361 case detail::value_t::binary: 14362 case detail::value_t::discarded: 14363 default: 14364 { 14365 // we do not expect primitive values if there is still a 14366 // reference token to process 14367 return false; 14368 } 14369 } 14370 } 14371 14372 // no reference token left means we found a primitive value 14373 return true; 14374 } 14375 14376 /*! 14377 @brief split the string input to reference tokens 14378 14379 @note This function is only called by the json_pointer constructor. 14380 All exceptions below are documented there. 14381 14382 @throw parse_error.107 if the pointer is not empty or begins with '/' 14383 @throw parse_error.108 if character '~' is not followed by '0' or '1' 14384 */ 14385 static std::vector<string_t> split(const string_t& reference_string) 14386 { 14387 std::vector<string_t> result; 14388 14389 // special case: empty reference string -> no reference tokens 14390 if (reference_string.empty()) 14391 { 14392 return result; 14393 } 14394 14395 // check if nonempty reference string begins with slash 14396 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) 14397 { 14398 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); 14399 } 14400 14401 // extract the reference tokens: 14402 // - slash: position of the last read slash (or end of string) 14403 // - start: position after the previous slash 14404 for ( 14405 // search for the first slash after the first character 14406 std::size_t slash = reference_string.find_first_of('/', 1), 14407 // set the beginning of the first reference token 14408 start = 1; 14409 // we can stop if start == 0 (if slash == string_t::npos) 14410 start != 0; 14411 // set the beginning of the next reference token 14412 // (will eventually be 0 if slash == string_t::npos) 14413 start = (slash == string_t::npos) ? 0 : slash + 1, 14414 // find next slash 14415 slash = reference_string.find_first_of('/', start)) 14416 { 14417 // use the text between the beginning of the reference token 14418 // (start) and the last slash (slash). 14419 auto reference_token = reference_string.substr(start, slash - start); 14420 14421 // check reference tokens are properly escaped 14422 for (std::size_t pos = reference_token.find_first_of('~'); 14423 pos != string_t::npos; 14424 pos = reference_token.find_first_of('~', pos + 1)) 14425 { 14426 JSON_ASSERT(reference_token[pos] == '~'); 14427 14428 // ~ must be followed by 0 or 1 14429 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || 14430 (reference_token[pos + 1] != '0' && 14431 reference_token[pos + 1] != '1'))) 14432 { 14433 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); 14434 } 14435 } 14436 14437 // finally, store the reference token 14438 detail::unescape(reference_token); 14439 result.push_back(reference_token); 14440 } 14441 14442 return result; 14443 } 14444 14445 private: 14446 /*! 14447 @param[in] reference_string the reference string to the current value 14448 @param[in] value the value to consider 14449 @param[in,out] result the result object to insert values to 14450 14451 @note Empty objects or arrays are flattened to `null`. 14452 */ 14453 template<typename BasicJsonType> 14454 static void flatten(const string_t& reference_string, 14455 const BasicJsonType& value, 14456 BasicJsonType& result) 14457 { 14458 switch (value.type()) 14459 { 14460 case detail::value_t::array: 14461 { 14462 if (value.m_value.array->empty()) 14463 { 14464 // flatten empty array as null 14465 result[reference_string] = nullptr; 14466 } 14467 else 14468 { 14469 // iterate array and use index as reference string 14470 for (std::size_t i = 0; i < value.m_value.array->size(); ++i) 14471 { 14472 flatten(detail::concat(reference_string, '/', std::to_string(i)), 14473 value.m_value.array->operator[](i), result); 14474 } 14475 } 14476 break; 14477 } 14478 14479 case detail::value_t::object: 14480 { 14481 if (value.m_value.object->empty()) 14482 { 14483 // flatten empty object as null 14484 result[reference_string] = nullptr; 14485 } 14486 else 14487 { 14488 // iterate object and use keys as reference string 14489 for (const auto& element : *value.m_value.object) 14490 { 14491 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); 14492 } 14493 } 14494 break; 14495 } 14496 14497 case detail::value_t::null: 14498 case detail::value_t::string: 14499 case detail::value_t::boolean: 14500 case detail::value_t::number_integer: 14501 case detail::value_t::number_unsigned: 14502 case detail::value_t::number_float: 14503 case detail::value_t::binary: 14504 case detail::value_t::discarded: 14505 default: 14506 { 14507 // add primitive value with its reference string 14508 result[reference_string] = value; 14509 break; 14510 } 14511 } 14512 } 14513 14514 /*! 14515 @param[in] value flattened JSON 14516 14517 @return unflattened JSON 14518 14519 @throw parse_error.109 if array index is not a number 14520 @throw type_error.314 if value is not an object 14521 @throw type_error.315 if object values are not primitive 14522 @throw type_error.313 if value cannot be unflattened 14523 */ 14524 template<typename BasicJsonType> 14525 static BasicJsonType 14526 unflatten(const BasicJsonType& value) 14527 { 14528 if (JSON_HEDLEY_UNLIKELY(!value.is_object())) 14529 { 14530 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); 14531 } 14532 14533 BasicJsonType result; 14534 14535 // iterate the JSON object values 14536 for (const auto& element : *value.m_value.object) 14537 { 14538 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) 14539 { 14540 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); 14541 } 14542 14543 // assign value to reference pointed to by JSON pointer; Note that if 14544 // the JSON pointer is "" (i.e., points to the whole value), function 14545 // get_and_create returns a reference to result itself. An assignment 14546 // will then create a primitive value. 14547 json_pointer(element.first).get_and_create(result) = element.second; 14548 } 14549 14550 return result; 14551 } 14552 14553 // can't use conversion operator because of ambiguity 14554 json_pointer<string_t> convert() const& 14555 { 14556 json_pointer<string_t> result; 14557 result.reference_tokens = reference_tokens; 14558 return result; 14559 } 14560 14561 json_pointer<string_t> convert()&& 14562 { 14563 json_pointer<string_t> result; 14564 result.reference_tokens = std::move(reference_tokens); 14565 return result; 14566 } 14567 14568 public: 14569 #if JSON_HAS_THREE_WAY_COMPARISON 14570 /// @brief compares two JSON pointers for equality 14571 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14572 template<typename RefStringTypeRhs> 14573 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept 14574 { 14575 return reference_tokens == rhs.reference_tokens; 14576 } 14577 14578 /// @brief compares JSON pointer and string for equality 14579 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14580 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) 14581 bool operator==(const string_t& rhs) const 14582 { 14583 return *this == json_pointer(rhs); 14584 } 14585 14586 /// @brief 3-way compares two JSON pointers 14587 template<typename RefStringTypeRhs> 14588 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD* 14589 { 14590 return reference_tokens <=> rhs.reference_tokens; // *NOPAD* 14591 } 14592 #else 14593 /// @brief compares two JSON pointers for equality 14594 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14595 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14596 // NOLINTNEXTLINE(readability-redundant-declaration) 14597 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14598 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14599 14600 /// @brief compares JSON pointer and string for equality 14601 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14602 template<typename RefStringTypeLhs, typename StringType> 14603 // NOLINTNEXTLINE(readability-redundant-declaration) 14604 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14605 const StringType& rhs); 14606 14607 /// @brief compares string and JSON pointer for equality 14608 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14609 template<typename RefStringTypeRhs, typename StringType> 14610 // NOLINTNEXTLINE(readability-redundant-declaration) 14611 friend bool operator==(const StringType& lhs, 14612 const json_pointer<RefStringTypeRhs>& rhs); 14613 14614 /// @brief compares two JSON pointers for inequality 14615 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14616 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14617 // NOLINTNEXTLINE(readability-redundant-declaration) 14618 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14619 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14620 14621 /// @brief compares JSON pointer and string for inequality 14622 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14623 template<typename RefStringTypeLhs, typename StringType> 14624 // NOLINTNEXTLINE(readability-redundant-declaration) 14625 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14626 const StringType& rhs); 14627 14628 /// @brief compares string and JSON pointer for inequality 14629 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14630 template<typename RefStringTypeRhs, typename StringType> 14631 // NOLINTNEXTLINE(readability-redundant-declaration) 14632 friend bool operator!=(const StringType& lhs, 14633 const json_pointer<RefStringTypeRhs>& rhs); 14634 14635 /// @brief compares two JSON pointer for less-than 14636 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14637 // NOLINTNEXTLINE(readability-redundant-declaration) 14638 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs, 14639 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14640 #endif 14641 14642 private: 14643 /// the reference tokens 14644 std::vector<string_t> reference_tokens; 14645 }; 14646 14647 #if !JSON_HAS_THREE_WAY_COMPARISON 14648 // functions cannot be defined inside class due to ODR violations 14649 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14650 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14651 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14652 { 14653 return lhs.reference_tokens == rhs.reference_tokens; 14654 } 14655 14656 template<typename RefStringTypeLhs, 14657 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> 14658 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 14659 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14660 const StringType& rhs) 14661 { 14662 return lhs == json_pointer<RefStringTypeLhs>(rhs); 14663 } 14664 14665 template<typename RefStringTypeRhs, 14666 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> 14667 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 14668 inline bool operator==(const StringType& lhs, 14669 const json_pointer<RefStringTypeRhs>& rhs) 14670 { 14671 return json_pointer<RefStringTypeRhs>(lhs) == rhs; 14672 } 14673 14674 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14675 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14676 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14677 { 14678 return !(lhs == rhs); 14679 } 14680 14681 template<typename RefStringTypeLhs, 14682 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> 14683 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) 14684 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14685 const StringType& rhs) 14686 { 14687 return !(lhs == rhs); 14688 } 14689 14690 template<typename RefStringTypeRhs, 14691 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> 14692 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) 14693 inline bool operator!=(const StringType& lhs, 14694 const json_pointer<RefStringTypeRhs>& rhs) 14695 { 14696 return !(lhs == rhs); 14697 } 14698 14699 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14700 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, 14701 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14702 { 14703 return lhs.reference_tokens < rhs.reference_tokens; 14704 } 14705 #endif 14706 14707 NLOHMANN_JSON_NAMESPACE_END 14708 14709 // #include <nlohmann/detail/json_ref.hpp> 14710 // __ _____ _____ _____ 14711 // __| | __| | | | JSON for Modern C++ 14712 // | | |__ | | | | | | version 3.11.2 14713 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14714 // 14715 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 14716 // SPDX-License-Identifier: MIT 14717 14718 14719 14720 #include <initializer_list> 14721 #include <utility> 14722 14723 // #include <nlohmann/detail/abi_macros.hpp> 14724 14725 // #include <nlohmann/detail/meta/type_traits.hpp> 14726 14727 14728 NLOHMANN_JSON_NAMESPACE_BEGIN 14729 namespace detail 14730 { 14731 14732 template<typename BasicJsonType> 14733 class json_ref 14734 { 14735 public: 14736 using value_type = BasicJsonType; 14737 14738 json_ref(value_type&& value) 14739 : owned_value(std::move(value)) 14740 {} 14741 14742 json_ref(const value_type& value) 14743 : value_ref(&value) 14744 {} 14745 14746 json_ref(std::initializer_list<json_ref> init) 14747 : owned_value(init) 14748 {} 14749 14750 template < 14751 class... Args, 14752 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 > 14753 json_ref(Args && ... args) 14754 : owned_value(std::forward<Args>(args)...) 14755 {} 14756 14757 // class should be movable only 14758 json_ref(json_ref&&) noexcept = default; 14759 json_ref(const json_ref&) = delete; 14760 json_ref& operator=(const json_ref&) = delete; 14761 json_ref& operator=(json_ref&&) = delete; 14762 ~json_ref() = default; 14763 14764 value_type moved_or_copied() const 14765 { 14766 if (value_ref == nullptr) 14767 { 14768 return std::move(owned_value); 14769 } 14770 return *value_ref; 14771 } 14772 14773 value_type const& operator*() const 14774 { 14775 return value_ref ? *value_ref : owned_value; 14776 } 14777 14778 value_type const* operator->() const 14779 { 14780 return &** this; 14781 } 14782 14783 private: 14784 mutable value_type owned_value = nullptr; 14785 value_type const* value_ref = nullptr; 14786 }; 14787 14788 } // namespace detail 14789 NLOHMANN_JSON_NAMESPACE_END 14790 14791 // #include <nlohmann/detail/macro_scope.hpp> 14792 14793 // #include <nlohmann/detail/string_concat.hpp> 14794 14795 // #include <nlohmann/detail/string_escape.hpp> 14796 14797 // #include <nlohmann/detail/meta/cpp_future.hpp> 14798 14799 // #include <nlohmann/detail/meta/type_traits.hpp> 14800 14801 // #include <nlohmann/detail/output/binary_writer.hpp> 14802 // __ _____ _____ _____ 14803 // __| | __| | | | JSON for Modern C++ 14804 // | | |__ | | | | | | version 3.11.2 14805 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14806 // 14807 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 14808 // SPDX-License-Identifier: MIT 14809 14810 14811 14812 #include <algorithm> // reverse 14813 #include <array> // array 14814 #include <map> // map 14815 #include <cmath> // isnan, isinf 14816 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 14817 #include <cstring> // memcpy 14818 #include <limits> // numeric_limits 14819 #include <string> // string 14820 #include <utility> // move 14821 #include <vector> // vector 14822 14823 // #include <nlohmann/detail/input/binary_reader.hpp> 14824 14825 // #include <nlohmann/detail/macro_scope.hpp> 14826 14827 // #include <nlohmann/detail/output/output_adapters.hpp> 14828 // __ _____ _____ _____ 14829 // __| | __| | | | JSON for Modern C++ 14830 // | | |__ | | | | | | version 3.11.2 14831 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14832 // 14833 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 14834 // SPDX-License-Identifier: MIT 14835 14836 14837 14838 #include <algorithm> // copy 14839 #include <cstddef> // size_t 14840 #include <iterator> // back_inserter 14841 #include <memory> // shared_ptr, make_shared 14842 #include <string> // basic_string 14843 #include <vector> // vector 14844 14845 #ifndef JSON_NO_IO 14846 #include <ios> // streamsize 14847 #include <ostream> // basic_ostream 14848 #endif // JSON_NO_IO 14849 14850 // #include <nlohmann/detail/macro_scope.hpp> 14851 14852 14853 NLOHMANN_JSON_NAMESPACE_BEGIN 14854 namespace detail 14855 { 14856 14857 /// abstract output adapter interface 14858 template<typename CharType> struct output_adapter_protocol 14859 { 14860 virtual void write_character(CharType c) = 0; 14861 virtual void write_characters(const CharType* s, std::size_t length) = 0; 14862 virtual ~output_adapter_protocol() = default; 14863 14864 output_adapter_protocol() = default; 14865 output_adapter_protocol(const output_adapter_protocol&) = default; 14866 output_adapter_protocol(output_adapter_protocol&&) noexcept = default; 14867 output_adapter_protocol& operator=(const output_adapter_protocol&) = default; 14868 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; 14869 }; 14870 14871 /// a type to simplify interfaces 14872 template<typename CharType> 14873 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; 14874 14875 /// output adapter for byte vectors 14876 template<typename CharType, typename AllocatorType = std::allocator<CharType>> 14877 class output_vector_adapter : public output_adapter_protocol<CharType> 14878 { 14879 public: 14880 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept 14881 : v(vec) 14882 {} 14883 14884 void write_character(CharType c) override 14885 { 14886 v.push_back(c); 14887 } 14888 14889 JSON_HEDLEY_NON_NULL(2) 14890 void write_characters(const CharType* s, std::size_t length) override 14891 { 14892 v.insert(v.end(), s, s + length); 14893 } 14894 14895 private: 14896 std::vector<CharType, AllocatorType>& v; 14897 }; 14898 14899 #ifndef JSON_NO_IO 14900 /// output adapter for output streams 14901 template<typename CharType> 14902 class output_stream_adapter : public output_adapter_protocol<CharType> 14903 { 14904 public: 14905 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept 14906 : stream(s) 14907 {} 14908 14909 void write_character(CharType c) override 14910 { 14911 stream.put(c); 14912 } 14913 14914 JSON_HEDLEY_NON_NULL(2) 14915 void write_characters(const CharType* s, std::size_t length) override 14916 { 14917 stream.write(s, static_cast<std::streamsize>(length)); 14918 } 14919 14920 private: 14921 std::basic_ostream<CharType>& stream; 14922 }; 14923 #endif // JSON_NO_IO 14924 14925 /// output adapter for basic_string 14926 template<typename CharType, typename StringType = std::basic_string<CharType>> 14927 class output_string_adapter : public output_adapter_protocol<CharType> 14928 { 14929 public: 14930 explicit output_string_adapter(StringType& s) noexcept 14931 : str(s) 14932 {} 14933 14934 void write_character(CharType c) override 14935 { 14936 str.push_back(c); 14937 } 14938 14939 JSON_HEDLEY_NON_NULL(2) 14940 void write_characters(const CharType* s, std::size_t length) override 14941 { 14942 str.append(s, length); 14943 } 14944 14945 private: 14946 StringType& str; 14947 }; 14948 14949 template<typename CharType, typename StringType = std::basic_string<CharType>> 14950 class output_adapter 14951 { 14952 public: 14953 template<typename AllocatorType = std::allocator<CharType>> 14954 output_adapter(std::vector<CharType, AllocatorType>& vec) 14955 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {} 14956 14957 #ifndef JSON_NO_IO 14958 output_adapter(std::basic_ostream<CharType>& s) 14959 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {} 14960 #endif // JSON_NO_IO 14961 14962 output_adapter(StringType& s) 14963 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {} 14964 14965 operator output_adapter_t<CharType>() 14966 { 14967 return oa; 14968 } 14969 14970 private: 14971 output_adapter_t<CharType> oa = nullptr; 14972 }; 14973 14974 } // namespace detail 14975 NLOHMANN_JSON_NAMESPACE_END 14976 14977 // #include <nlohmann/detail/string_concat.hpp> 14978 14979 14980 NLOHMANN_JSON_NAMESPACE_BEGIN 14981 namespace detail 14982 { 14983 14984 /////////////////// 14985 // binary writer // 14986 /////////////////// 14987 14988 /*! 14989 @brief serialization to CBOR and MessagePack values 14990 */ 14991 template<typename BasicJsonType, typename CharType> 14992 class binary_writer 14993 { 14994 using string_t = typename BasicJsonType::string_t; 14995 using binary_t = typename BasicJsonType::binary_t; 14996 using number_float_t = typename BasicJsonType::number_float_t; 14997 14998 public: 14999 /*! 15000 @brief create a binary writer 15001 15002 @param[in] adapter output adapter to write to 15003 */ 15004 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter)) 15005 { 15006 JSON_ASSERT(oa); 15007 } 15008 15009 /*! 15010 @param[in] j JSON value to serialize 15011 @pre j.type() == value_t::object 15012 */ 15013 void write_bson(const BasicJsonType& j) 15014 { 15015 switch (j.type()) 15016 { 15017 case value_t::object: 15018 { 15019 write_bson_object(*j.m_value.object); 15020 break; 15021 } 15022 15023 case value_t::null: 15024 case value_t::array: 15025 case value_t::string: 15026 case value_t::boolean: 15027 case value_t::number_integer: 15028 case value_t::number_unsigned: 15029 case value_t::number_float: 15030 case value_t::binary: 15031 case value_t::discarded: 15032 default: 15033 { 15034 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j)); 15035 } 15036 } 15037 } 15038 15039 /*! 15040 @param[in] j JSON value to serialize 15041 */ 15042 void write_cbor(const BasicJsonType& j) 15043 { 15044 switch (j.type()) 15045 { 15046 case value_t::null: 15047 { 15048 oa->write_character(to_char_type(0xF6)); 15049 break; 15050 } 15051 15052 case value_t::boolean: 15053 { 15054 oa->write_character(j.m_value.boolean 15055 ? to_char_type(0xF5) 15056 : to_char_type(0xF4)); 15057 break; 15058 } 15059 15060 case value_t::number_integer: 15061 { 15062 if (j.m_value.number_integer >= 0) 15063 { 15064 // CBOR does not differentiate between positive signed 15065 // integers and unsigned integers. Therefore, we used the 15066 // code from the value_t::number_unsigned case here. 15067 if (j.m_value.number_integer <= 0x17) 15068 { 15069 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 15070 } 15071 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 15072 { 15073 oa->write_character(to_char_type(0x18)); 15074 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 15075 } 15076 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()) 15077 { 15078 oa->write_character(to_char_type(0x19)); 15079 write_number(static_cast<std::uint16_t>(j.m_value.number_integer)); 15080 } 15081 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()) 15082 { 15083 oa->write_character(to_char_type(0x1A)); 15084 write_number(static_cast<std::uint32_t>(j.m_value.number_integer)); 15085 } 15086 else 15087 { 15088 oa->write_character(to_char_type(0x1B)); 15089 write_number(static_cast<std::uint64_t>(j.m_value.number_integer)); 15090 } 15091 } 15092 else 15093 { 15094 // The conversions below encode the sign in the first 15095 // byte, and the value is converted to a positive number. 15096 const auto positive_number = -1 - j.m_value.number_integer; 15097 if (j.m_value.number_integer >= -24) 15098 { 15099 write_number(static_cast<std::uint8_t>(0x20 + positive_number)); 15100 } 15101 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) 15102 { 15103 oa->write_character(to_char_type(0x38)); 15104 write_number(static_cast<std::uint8_t>(positive_number)); 15105 } 15106 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) 15107 { 15108 oa->write_character(to_char_type(0x39)); 15109 write_number(static_cast<std::uint16_t>(positive_number)); 15110 } 15111 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) 15112 { 15113 oa->write_character(to_char_type(0x3A)); 15114 write_number(static_cast<std::uint32_t>(positive_number)); 15115 } 15116 else 15117 { 15118 oa->write_character(to_char_type(0x3B)); 15119 write_number(static_cast<std::uint64_t>(positive_number)); 15120 } 15121 } 15122 break; 15123 } 15124 15125 case value_t::number_unsigned: 15126 { 15127 if (j.m_value.number_unsigned <= 0x17) 15128 { 15129 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned)); 15130 } 15131 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15132 { 15133 oa->write_character(to_char_type(0x18)); 15134 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned)); 15135 } 15136 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15137 { 15138 oa->write_character(to_char_type(0x19)); 15139 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned)); 15140 } 15141 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15142 { 15143 oa->write_character(to_char_type(0x1A)); 15144 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned)); 15145 } 15146 else 15147 { 15148 oa->write_character(to_char_type(0x1B)); 15149 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned)); 15150 } 15151 break; 15152 } 15153 15154 case value_t::number_float: 15155 { 15156 if (std::isnan(j.m_value.number_float)) 15157 { 15158 // NaN is 0xf97e00 in CBOR 15159 oa->write_character(to_char_type(0xF9)); 15160 oa->write_character(to_char_type(0x7E)); 15161 oa->write_character(to_char_type(0x00)); 15162 } 15163 else if (std::isinf(j.m_value.number_float)) 15164 { 15165 // Infinity is 0xf97c00, -Infinity is 0xf9fc00 15166 oa->write_character(to_char_type(0xf9)); 15167 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); 15168 oa->write_character(to_char_type(0x00)); 15169 } 15170 else 15171 { 15172 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); 15173 } 15174 break; 15175 } 15176 15177 case value_t::string: 15178 { 15179 // step 1: write control byte and the string length 15180 const auto N = j.m_value.string->size(); 15181 if (N <= 0x17) 15182 { 15183 write_number(static_cast<std::uint8_t>(0x60 + N)); 15184 } 15185 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15186 { 15187 oa->write_character(to_char_type(0x78)); 15188 write_number(static_cast<std::uint8_t>(N)); 15189 } 15190 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15191 { 15192 oa->write_character(to_char_type(0x79)); 15193 write_number(static_cast<std::uint16_t>(N)); 15194 } 15195 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15196 { 15197 oa->write_character(to_char_type(0x7A)); 15198 write_number(static_cast<std::uint32_t>(N)); 15199 } 15200 // LCOV_EXCL_START 15201 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15202 { 15203 oa->write_character(to_char_type(0x7B)); 15204 write_number(static_cast<std::uint64_t>(N)); 15205 } 15206 // LCOV_EXCL_STOP 15207 15208 // step 2: write the string 15209 oa->write_characters( 15210 reinterpret_cast<const CharType*>(j.m_value.string->c_str()), 15211 j.m_value.string->size()); 15212 break; 15213 } 15214 15215 case value_t::array: 15216 { 15217 // step 1: write control byte and the array size 15218 const auto N = j.m_value.array->size(); 15219 if (N <= 0x17) 15220 { 15221 write_number(static_cast<std::uint8_t>(0x80 + N)); 15222 } 15223 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15224 { 15225 oa->write_character(to_char_type(0x98)); 15226 write_number(static_cast<std::uint8_t>(N)); 15227 } 15228 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15229 { 15230 oa->write_character(to_char_type(0x99)); 15231 write_number(static_cast<std::uint16_t>(N)); 15232 } 15233 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15234 { 15235 oa->write_character(to_char_type(0x9A)); 15236 write_number(static_cast<std::uint32_t>(N)); 15237 } 15238 // LCOV_EXCL_START 15239 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15240 { 15241 oa->write_character(to_char_type(0x9B)); 15242 write_number(static_cast<std::uint64_t>(N)); 15243 } 15244 // LCOV_EXCL_STOP 15245 15246 // step 2: write each element 15247 for (const auto& el : *j.m_value.array) 15248 { 15249 write_cbor(el); 15250 } 15251 break; 15252 } 15253 15254 case value_t::binary: 15255 { 15256 if (j.m_value.binary->has_subtype()) 15257 { 15258 if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)()) 15259 { 15260 write_number(static_cast<std::uint8_t>(0xd8)); 15261 write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype())); 15262 } 15263 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)()) 15264 { 15265 write_number(static_cast<std::uint8_t>(0xd9)); 15266 write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype())); 15267 } 15268 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)()) 15269 { 15270 write_number(static_cast<std::uint8_t>(0xda)); 15271 write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype())); 15272 } 15273 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)()) 15274 { 15275 write_number(static_cast<std::uint8_t>(0xdb)); 15276 write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype())); 15277 } 15278 } 15279 15280 // step 1: write control byte and the binary array size 15281 const auto N = j.m_value.binary->size(); 15282 if (N <= 0x17) 15283 { 15284 write_number(static_cast<std::uint8_t>(0x40 + N)); 15285 } 15286 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15287 { 15288 oa->write_character(to_char_type(0x58)); 15289 write_number(static_cast<std::uint8_t>(N)); 15290 } 15291 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15292 { 15293 oa->write_character(to_char_type(0x59)); 15294 write_number(static_cast<std::uint16_t>(N)); 15295 } 15296 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15297 { 15298 oa->write_character(to_char_type(0x5A)); 15299 write_number(static_cast<std::uint32_t>(N)); 15300 } 15301 // LCOV_EXCL_START 15302 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15303 { 15304 oa->write_character(to_char_type(0x5B)); 15305 write_number(static_cast<std::uint64_t>(N)); 15306 } 15307 // LCOV_EXCL_STOP 15308 15309 // step 2: write each element 15310 oa->write_characters( 15311 reinterpret_cast<const CharType*>(j.m_value.binary->data()), 15312 N); 15313 15314 break; 15315 } 15316 15317 case value_t::object: 15318 { 15319 // step 1: write control byte and the object size 15320 const auto N = j.m_value.object->size(); 15321 if (N <= 0x17) 15322 { 15323 write_number(static_cast<std::uint8_t>(0xA0 + N)); 15324 } 15325 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15326 { 15327 oa->write_character(to_char_type(0xB8)); 15328 write_number(static_cast<std::uint8_t>(N)); 15329 } 15330 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15331 { 15332 oa->write_character(to_char_type(0xB9)); 15333 write_number(static_cast<std::uint16_t>(N)); 15334 } 15335 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15336 { 15337 oa->write_character(to_char_type(0xBA)); 15338 write_number(static_cast<std::uint32_t>(N)); 15339 } 15340 // LCOV_EXCL_START 15341 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15342 { 15343 oa->write_character(to_char_type(0xBB)); 15344 write_number(static_cast<std::uint64_t>(N)); 15345 } 15346 // LCOV_EXCL_STOP 15347 15348 // step 2: write each element 15349 for (const auto& el : *j.m_value.object) 15350 { 15351 write_cbor(el.first); 15352 write_cbor(el.second); 15353 } 15354 break; 15355 } 15356 15357 case value_t::discarded: 15358 default: 15359 break; 15360 } 15361 } 15362 15363 /*! 15364 @param[in] j JSON value to serialize 15365 */ 15366 void write_msgpack(const BasicJsonType& j) 15367 { 15368 switch (j.type()) 15369 { 15370 case value_t::null: // nil 15371 { 15372 oa->write_character(to_char_type(0xC0)); 15373 break; 15374 } 15375 15376 case value_t::boolean: // true and false 15377 { 15378 oa->write_character(j.m_value.boolean 15379 ? to_char_type(0xC3) 15380 : to_char_type(0xC2)); 15381 break; 15382 } 15383 15384 case value_t::number_integer: 15385 { 15386 if (j.m_value.number_integer >= 0) 15387 { 15388 // MessagePack does not differentiate between positive 15389 // signed integers and unsigned integers. Therefore, we used 15390 // the code from the value_t::number_unsigned case here. 15391 if (j.m_value.number_unsigned < 128) 15392 { 15393 // positive fixnum 15394 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 15395 } 15396 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15397 { 15398 // uint 8 15399 oa->write_character(to_char_type(0xCC)); 15400 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 15401 } 15402 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15403 { 15404 // uint 16 15405 oa->write_character(to_char_type(0xCD)); 15406 write_number(static_cast<std::uint16_t>(j.m_value.number_integer)); 15407 } 15408 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15409 { 15410 // uint 32 15411 oa->write_character(to_char_type(0xCE)); 15412 write_number(static_cast<std::uint32_t>(j.m_value.number_integer)); 15413 } 15414 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 15415 { 15416 // uint 64 15417 oa->write_character(to_char_type(0xCF)); 15418 write_number(static_cast<std::uint64_t>(j.m_value.number_integer)); 15419 } 15420 } 15421 else 15422 { 15423 if (j.m_value.number_integer >= -32) 15424 { 15425 // negative fixnum 15426 write_number(static_cast<std::int8_t>(j.m_value.number_integer)); 15427 } 15428 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() && 15429 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 15430 { 15431 // int 8 15432 oa->write_character(to_char_type(0xD0)); 15433 write_number(static_cast<std::int8_t>(j.m_value.number_integer)); 15434 } 15435 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() && 15436 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 15437 { 15438 // int 16 15439 oa->write_character(to_char_type(0xD1)); 15440 write_number(static_cast<std::int16_t>(j.m_value.number_integer)); 15441 } 15442 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() && 15443 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 15444 { 15445 // int 32 15446 oa->write_character(to_char_type(0xD2)); 15447 write_number(static_cast<std::int32_t>(j.m_value.number_integer)); 15448 } 15449 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() && 15450 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) 15451 { 15452 // int 64 15453 oa->write_character(to_char_type(0xD3)); 15454 write_number(static_cast<std::int64_t>(j.m_value.number_integer)); 15455 } 15456 } 15457 break; 15458 } 15459 15460 case value_t::number_unsigned: 15461 { 15462 if (j.m_value.number_unsigned < 128) 15463 { 15464 // positive fixnum 15465 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 15466 } 15467 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15468 { 15469 // uint 8 15470 oa->write_character(to_char_type(0xCC)); 15471 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 15472 } 15473 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15474 { 15475 // uint 16 15476 oa->write_character(to_char_type(0xCD)); 15477 write_number(static_cast<std::uint16_t>(j.m_value.number_integer)); 15478 } 15479 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15480 { 15481 // uint 32 15482 oa->write_character(to_char_type(0xCE)); 15483 write_number(static_cast<std::uint32_t>(j.m_value.number_integer)); 15484 } 15485 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 15486 { 15487 // uint 64 15488 oa->write_character(to_char_type(0xCF)); 15489 write_number(static_cast<std::uint64_t>(j.m_value.number_integer)); 15490 } 15491 break; 15492 } 15493 15494 case value_t::number_float: 15495 { 15496 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); 15497 break; 15498 } 15499 15500 case value_t::string: 15501 { 15502 // step 1: write control byte and the string length 15503 const auto N = j.m_value.string->size(); 15504 if (N <= 31) 15505 { 15506 // fixstr 15507 write_number(static_cast<std::uint8_t>(0xA0 | N)); 15508 } 15509 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15510 { 15511 // str 8 15512 oa->write_character(to_char_type(0xD9)); 15513 write_number(static_cast<std::uint8_t>(N)); 15514 } 15515 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15516 { 15517 // str 16 15518 oa->write_character(to_char_type(0xDA)); 15519 write_number(static_cast<std::uint16_t>(N)); 15520 } 15521 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15522 { 15523 // str 32 15524 oa->write_character(to_char_type(0xDB)); 15525 write_number(static_cast<std::uint32_t>(N)); 15526 } 15527 15528 // step 2: write the string 15529 oa->write_characters( 15530 reinterpret_cast<const CharType*>(j.m_value.string->c_str()), 15531 j.m_value.string->size()); 15532 break; 15533 } 15534 15535 case value_t::array: 15536 { 15537 // step 1: write control byte and the array size 15538 const auto N = j.m_value.array->size(); 15539 if (N <= 15) 15540 { 15541 // fixarray 15542 write_number(static_cast<std::uint8_t>(0x90 | N)); 15543 } 15544 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15545 { 15546 // array 16 15547 oa->write_character(to_char_type(0xDC)); 15548 write_number(static_cast<std::uint16_t>(N)); 15549 } 15550 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15551 { 15552 // array 32 15553 oa->write_character(to_char_type(0xDD)); 15554 write_number(static_cast<std::uint32_t>(N)); 15555 } 15556 15557 // step 2: write each element 15558 for (const auto& el : *j.m_value.array) 15559 { 15560 write_msgpack(el); 15561 } 15562 break; 15563 } 15564 15565 case value_t::binary: 15566 { 15567 // step 0: determine if the binary type has a set subtype to 15568 // determine whether or not to use the ext or fixext types 15569 const bool use_ext = j.m_value.binary->has_subtype(); 15570 15571 // step 1: write control byte and the byte string length 15572 const auto N = j.m_value.binary->size(); 15573 if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15574 { 15575 std::uint8_t output_type{}; 15576 bool fixed = true; 15577 if (use_ext) 15578 { 15579 switch (N) 15580 { 15581 case 1: 15582 output_type = 0xD4; // fixext 1 15583 break; 15584 case 2: 15585 output_type = 0xD5; // fixext 2 15586 break; 15587 case 4: 15588 output_type = 0xD6; // fixext 4 15589 break; 15590 case 8: 15591 output_type = 0xD7; // fixext 8 15592 break; 15593 case 16: 15594 output_type = 0xD8; // fixext 16 15595 break; 15596 default: 15597 output_type = 0xC7; // ext 8 15598 fixed = false; 15599 break; 15600 } 15601 15602 } 15603 else 15604 { 15605 output_type = 0xC4; // bin 8 15606 fixed = false; 15607 } 15608 15609 oa->write_character(to_char_type(output_type)); 15610 if (!fixed) 15611 { 15612 write_number(static_cast<std::uint8_t>(N)); 15613 } 15614 } 15615 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15616 { 15617 const std::uint8_t output_type = use_ext 15618 ? 0xC8 // ext 16 15619 : 0xC5; // bin 16 15620 15621 oa->write_character(to_char_type(output_type)); 15622 write_number(static_cast<std::uint16_t>(N)); 15623 } 15624 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15625 { 15626 const std::uint8_t output_type = use_ext 15627 ? 0xC9 // ext 32 15628 : 0xC6; // bin 32 15629 15630 oa->write_character(to_char_type(output_type)); 15631 write_number(static_cast<std::uint32_t>(N)); 15632 } 15633 15634 // step 1.5: if this is an ext type, write the subtype 15635 if (use_ext) 15636 { 15637 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype())); 15638 } 15639 15640 // step 2: write the byte string 15641 oa->write_characters( 15642 reinterpret_cast<const CharType*>(j.m_value.binary->data()), 15643 N); 15644 15645 break; 15646 } 15647 15648 case value_t::object: 15649 { 15650 // step 1: write control byte and the object size 15651 const auto N = j.m_value.object->size(); 15652 if (N <= 15) 15653 { 15654 // fixmap 15655 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF))); 15656 } 15657 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15658 { 15659 // map 16 15660 oa->write_character(to_char_type(0xDE)); 15661 write_number(static_cast<std::uint16_t>(N)); 15662 } 15663 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15664 { 15665 // map 32 15666 oa->write_character(to_char_type(0xDF)); 15667 write_number(static_cast<std::uint32_t>(N)); 15668 } 15669 15670 // step 2: write each element 15671 for (const auto& el : *j.m_value.object) 15672 { 15673 write_msgpack(el.first); 15674 write_msgpack(el.second); 15675 } 15676 break; 15677 } 15678 15679 case value_t::discarded: 15680 default: 15681 break; 15682 } 15683 } 15684 15685 /*! 15686 @param[in] j JSON value to serialize 15687 @param[in] use_count whether to use '#' prefixes (optimized format) 15688 @param[in] use_type whether to use '$' prefixes (optimized format) 15689 @param[in] add_prefix whether prefixes need to be used for this value 15690 @param[in] use_bjdata whether write in BJData format, default is false 15691 */ 15692 void write_ubjson(const BasicJsonType& j, const bool use_count, 15693 const bool use_type, const bool add_prefix = true, 15694 const bool use_bjdata = false) 15695 { 15696 switch (j.type()) 15697 { 15698 case value_t::null: 15699 { 15700 if (add_prefix) 15701 { 15702 oa->write_character(to_char_type('Z')); 15703 } 15704 break; 15705 } 15706 15707 case value_t::boolean: 15708 { 15709 if (add_prefix) 15710 { 15711 oa->write_character(j.m_value.boolean 15712 ? to_char_type('T') 15713 : to_char_type('F')); 15714 } 15715 break; 15716 } 15717 15718 case value_t::number_integer: 15719 { 15720 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata); 15721 break; 15722 } 15723 15724 case value_t::number_unsigned: 15725 { 15726 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata); 15727 break; 15728 } 15729 15730 case value_t::number_float: 15731 { 15732 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata); 15733 break; 15734 } 15735 15736 case value_t::string: 15737 { 15738 if (add_prefix) 15739 { 15740 oa->write_character(to_char_type('S')); 15741 } 15742 write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata); 15743 oa->write_characters( 15744 reinterpret_cast<const CharType*>(j.m_value.string->c_str()), 15745 j.m_value.string->size()); 15746 break; 15747 } 15748 15749 case value_t::array: 15750 { 15751 if (add_prefix) 15752 { 15753 oa->write_character(to_char_type('[')); 15754 } 15755 15756 bool prefix_required = true; 15757 if (use_type && !j.m_value.array->empty()) 15758 { 15759 JSON_ASSERT(use_count); 15760 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); 15761 const bool same_prefix = std::all_of(j.begin() + 1, j.end(), 15762 [this, first_prefix, use_bjdata](const BasicJsonType & v) 15763 { 15764 return ubjson_prefix(v, use_bjdata) == first_prefix; 15765 }); 15766 15767 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type 15768 15769 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) 15770 { 15771 prefix_required = false; 15772 oa->write_character(to_char_type('$')); 15773 oa->write_character(first_prefix); 15774 } 15775 } 15776 15777 if (use_count) 15778 { 15779 oa->write_character(to_char_type('#')); 15780 write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata); 15781 } 15782 15783 for (const auto& el : *j.m_value.array) 15784 { 15785 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); 15786 } 15787 15788 if (!use_count) 15789 { 15790 oa->write_character(to_char_type(']')); 15791 } 15792 15793 break; 15794 } 15795 15796 case value_t::binary: 15797 { 15798 if (add_prefix) 15799 { 15800 oa->write_character(to_char_type('[')); 15801 } 15802 15803 if (use_type && !j.m_value.binary->empty()) 15804 { 15805 JSON_ASSERT(use_count); 15806 oa->write_character(to_char_type('$')); 15807 oa->write_character('U'); 15808 } 15809 15810 if (use_count) 15811 { 15812 oa->write_character(to_char_type('#')); 15813 write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata); 15814 } 15815 15816 if (use_type) 15817 { 15818 oa->write_characters( 15819 reinterpret_cast<const CharType*>(j.m_value.binary->data()), 15820 j.m_value.binary->size()); 15821 } 15822 else 15823 { 15824 for (size_t i = 0; i < j.m_value.binary->size(); ++i) 15825 { 15826 oa->write_character(to_char_type('U')); 15827 oa->write_character(j.m_value.binary->data()[i]); 15828 } 15829 } 15830 15831 if (!use_count) 15832 { 15833 oa->write_character(to_char_type(']')); 15834 } 15835 15836 break; 15837 } 15838 15839 case value_t::object: 15840 { 15841 if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end()) 15842 { 15843 if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) 15844 { 15845 break; 15846 } 15847 } 15848 15849 if (add_prefix) 15850 { 15851 oa->write_character(to_char_type('{')); 15852 } 15853 15854 bool prefix_required = true; 15855 if (use_type && !j.m_value.object->empty()) 15856 { 15857 JSON_ASSERT(use_count); 15858 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); 15859 const bool same_prefix = std::all_of(j.begin(), j.end(), 15860 [this, first_prefix, use_bjdata](const BasicJsonType & v) 15861 { 15862 return ubjson_prefix(v, use_bjdata) == first_prefix; 15863 }); 15864 15865 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type 15866 15867 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) 15868 { 15869 prefix_required = false; 15870 oa->write_character(to_char_type('$')); 15871 oa->write_character(first_prefix); 15872 } 15873 } 15874 15875 if (use_count) 15876 { 15877 oa->write_character(to_char_type('#')); 15878 write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata); 15879 } 15880 15881 for (const auto& el : *j.m_value.object) 15882 { 15883 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); 15884 oa->write_characters( 15885 reinterpret_cast<const CharType*>(el.first.c_str()), 15886 el.first.size()); 15887 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata); 15888 } 15889 15890 if (!use_count) 15891 { 15892 oa->write_character(to_char_type('}')); 15893 } 15894 15895 break; 15896 } 15897 15898 case value_t::discarded: 15899 default: 15900 break; 15901 } 15902 } 15903 15904 private: 15905 ////////// 15906 // BSON // 15907 ////////// 15908 15909 /*! 15910 @return The size of a BSON document entry header, including the id marker 15911 and the entry name size (and its null-terminator). 15912 */ 15913 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) 15914 { 15915 const auto it = name.find(static_cast<typename string_t::value_type>(0)); 15916 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) 15917 { 15918 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j)); 15919 static_cast<void>(j); 15920 } 15921 15922 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; 15923 } 15924 15925 /*! 15926 @brief Writes the given @a element_type and @a name to the output adapter 15927 */ 15928 void write_bson_entry_header(const string_t& name, 15929 const std::uint8_t element_type) 15930 { 15931 oa->write_character(to_char_type(element_type)); // boolean 15932 oa->write_characters( 15933 reinterpret_cast<const CharType*>(name.c_str()), 15934 name.size() + 1u); 15935 } 15936 15937 /*! 15938 @brief Writes a BSON element with key @a name and boolean value @a value 15939 */ 15940 void write_bson_boolean(const string_t& name, 15941 const bool value) 15942 { 15943 write_bson_entry_header(name, 0x08); 15944 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); 15945 } 15946 15947 /*! 15948 @brief Writes a BSON element with key @a name and double value @a value 15949 */ 15950 void write_bson_double(const string_t& name, 15951 const double value) 15952 { 15953 write_bson_entry_header(name, 0x01); 15954 write_number<double>(value, true); 15955 } 15956 15957 /*! 15958 @return The size of the BSON-encoded string in @a value 15959 */ 15960 static std::size_t calc_bson_string_size(const string_t& value) 15961 { 15962 return sizeof(std::int32_t) + value.size() + 1ul; 15963 } 15964 15965 /*! 15966 @brief Writes a BSON element with key @a name and string value @a value 15967 */ 15968 void write_bson_string(const string_t& name, 15969 const string_t& value) 15970 { 15971 write_bson_entry_header(name, 0x02); 15972 15973 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true); 15974 oa->write_characters( 15975 reinterpret_cast<const CharType*>(value.c_str()), 15976 value.size() + 1); 15977 } 15978 15979 /*! 15980 @brief Writes a BSON element with key @a name and null value 15981 */ 15982 void write_bson_null(const string_t& name) 15983 { 15984 write_bson_entry_header(name, 0x0A); 15985 } 15986 15987 /*! 15988 @return The size of the BSON-encoded integer @a value 15989 */ 15990 static std::size_t calc_bson_integer_size(const std::int64_t value) 15991 { 15992 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)() 15993 ? sizeof(std::int32_t) 15994 : sizeof(std::int64_t); 15995 } 15996 15997 /*! 15998 @brief Writes a BSON element with key @a name and integer @a value 15999 */ 16000 void write_bson_integer(const string_t& name, 16001 const std::int64_t value) 16002 { 16003 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()) 16004 { 16005 write_bson_entry_header(name, 0x10); // int32 16006 write_number<std::int32_t>(static_cast<std::int32_t>(value), true); 16007 } 16008 else 16009 { 16010 write_bson_entry_header(name, 0x12); // int64 16011 write_number<std::int64_t>(static_cast<std::int64_t>(value), true); 16012 } 16013 } 16014 16015 /*! 16016 @return The size of the BSON-encoded unsigned integer in @a j 16017 */ 16018 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept 16019 { 16020 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16021 ? sizeof(std::int32_t) 16022 : sizeof(std::int64_t); 16023 } 16024 16025 /*! 16026 @brief Writes a BSON element with key @a name and unsigned @a value 16027 */ 16028 void write_bson_unsigned(const string_t& name, 16029 const BasicJsonType& j) 16030 { 16031 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16032 { 16033 write_bson_entry_header(name, 0x10 /* int32 */); 16034 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true); 16035 } 16036 else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16037 { 16038 write_bson_entry_header(name, 0x12 /* int64 */); 16039 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true); 16040 } 16041 else 16042 { 16043 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); 16044 } 16045 } 16046 16047 /*! 16048 @brief Writes a BSON element with key @a name and object @a value 16049 */ 16050 void write_bson_object_entry(const string_t& name, 16051 const typename BasicJsonType::object_t& value) 16052 { 16053 write_bson_entry_header(name, 0x03); // object 16054 write_bson_object(value); 16055 } 16056 16057 /*! 16058 @return The size of the BSON-encoded array @a value 16059 */ 16060 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) 16061 { 16062 std::size_t array_index = 0ul; 16063 16064 const 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) 16065 { 16066 return result + calc_bson_element_size(std::to_string(array_index++), el); 16067 }); 16068 16069 return sizeof(std::int32_t) + embedded_document_size + 1ul; 16070 } 16071 16072 /*! 16073 @return The size of the BSON-encoded binary array @a value 16074 */ 16075 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) 16076 { 16077 return sizeof(std::int32_t) + value.size() + 1ul; 16078 } 16079 16080 /*! 16081 @brief Writes a BSON element with key @a name and array @a value 16082 */ 16083 void write_bson_array(const string_t& name, 16084 const typename BasicJsonType::array_t& value) 16085 { 16086 write_bson_entry_header(name, 0x04); // array 16087 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true); 16088 16089 std::size_t array_index = 0ul; 16090 16091 for (const auto& el : value) 16092 { 16093 write_bson_element(std::to_string(array_index++), el); 16094 } 16095 16096 oa->write_character(to_char_type(0x00)); 16097 } 16098 16099 /*! 16100 @brief Writes a BSON element with key @a name and binary value @a value 16101 */ 16102 void write_bson_binary(const string_t& name, 16103 const binary_t& value) 16104 { 16105 write_bson_entry_header(name, 0x05); 16106 16107 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true); 16108 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00)); 16109 16110 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size()); 16111 } 16112 16113 /*! 16114 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name 16115 @return The calculated size for the BSON document entry for @a j with the given @a name. 16116 */ 16117 static std::size_t calc_bson_element_size(const string_t& name, 16118 const BasicJsonType& j) 16119 { 16120 const auto header_size = calc_bson_entry_header_size(name, j); 16121 switch (j.type()) 16122 { 16123 case value_t::object: 16124 return header_size + calc_bson_object_size(*j.m_value.object); 16125 16126 case value_t::array: 16127 return header_size + calc_bson_array_size(*j.m_value.array); 16128 16129 case value_t::binary: 16130 return header_size + calc_bson_binary_size(*j.m_value.binary); 16131 16132 case value_t::boolean: 16133 return header_size + 1ul; 16134 16135 case value_t::number_float: 16136 return header_size + 8ul; 16137 16138 case value_t::number_integer: 16139 return header_size + calc_bson_integer_size(j.m_value.number_integer); 16140 16141 case value_t::number_unsigned: 16142 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); 16143 16144 case value_t::string: 16145 return header_size + calc_bson_string_size(*j.m_value.string); 16146 16147 case value_t::null: 16148 return header_size + 0ul; 16149 16150 // LCOV_EXCL_START 16151 case value_t::discarded: 16152 default: 16153 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16154 return 0ul; 16155 // LCOV_EXCL_STOP 16156 } 16157 } 16158 16159 /*! 16160 @brief Serializes the JSON value @a j to BSON and associates it with the 16161 key @a name. 16162 @param name The name to associate with the JSON entity @a j within the 16163 current BSON document 16164 */ 16165 void write_bson_element(const string_t& name, 16166 const BasicJsonType& j) 16167 { 16168 switch (j.type()) 16169 { 16170 case value_t::object: 16171 return write_bson_object_entry(name, *j.m_value.object); 16172 16173 case value_t::array: 16174 return write_bson_array(name, *j.m_value.array); 16175 16176 case value_t::binary: 16177 return write_bson_binary(name, *j.m_value.binary); 16178 16179 case value_t::boolean: 16180 return write_bson_boolean(name, j.m_value.boolean); 16181 16182 case value_t::number_float: 16183 return write_bson_double(name, j.m_value.number_float); 16184 16185 case value_t::number_integer: 16186 return write_bson_integer(name, j.m_value.number_integer); 16187 16188 case value_t::number_unsigned: 16189 return write_bson_unsigned(name, j); 16190 16191 case value_t::string: 16192 return write_bson_string(name, *j.m_value.string); 16193 16194 case value_t::null: 16195 return write_bson_null(name); 16196 16197 // LCOV_EXCL_START 16198 case value_t::discarded: 16199 default: 16200 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16201 return; 16202 // LCOV_EXCL_STOP 16203 } 16204 } 16205 16206 /*! 16207 @brief Calculates the size of the BSON serialization of the given 16208 JSON-object @a j. 16209 @param[in] value JSON value to serialize 16210 @pre value.type() == value_t::object 16211 */ 16212 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) 16213 { 16214 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0), 16215 [](size_t result, const typename BasicJsonType::object_t::value_type & el) 16216 { 16217 return result += calc_bson_element_size(el.first, el.second); 16218 }); 16219 16220 return sizeof(std::int32_t) + document_size + 1ul; 16221 } 16222 16223 /*! 16224 @param[in] value JSON value to serialize 16225 @pre value.type() == value_t::object 16226 */ 16227 void write_bson_object(const typename BasicJsonType::object_t& value) 16228 { 16229 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true); 16230 16231 for (const auto& el : value) 16232 { 16233 write_bson_element(el.first, el.second); 16234 } 16235 16236 oa->write_character(to_char_type(0x00)); 16237 } 16238 16239 ////////// 16240 // CBOR // 16241 ////////// 16242 16243 static constexpr CharType get_cbor_float_prefix(float /*unused*/) 16244 { 16245 return to_char_type(0xFA); // Single-Precision Float 16246 } 16247 16248 static constexpr CharType get_cbor_float_prefix(double /*unused*/) 16249 { 16250 return to_char_type(0xFB); // Double-Precision Float 16251 } 16252 16253 ///////////// 16254 // MsgPack // 16255 ///////////// 16256 16257 static constexpr CharType get_msgpack_float_prefix(float /*unused*/) 16258 { 16259 return to_char_type(0xCA); // float 32 16260 } 16261 16262 static constexpr CharType get_msgpack_float_prefix(double /*unused*/) 16263 { 16264 return to_char_type(0xCB); // float 64 16265 } 16266 16267 //////////// 16268 // UBJSON // 16269 //////////// 16270 16271 // UBJSON: write number (floating point) 16272 template<typename NumberType, typename std::enable_if< 16273 std::is_floating_point<NumberType>::value, int>::type = 0> 16274 void write_number_with_ubjson_prefix(const NumberType n, 16275 const bool add_prefix, 16276 const bool use_bjdata) 16277 { 16278 if (add_prefix) 16279 { 16280 oa->write_character(get_ubjson_float_prefix(n)); 16281 } 16282 write_number(n, use_bjdata); 16283 } 16284 16285 // UBJSON: write number (unsigned integer) 16286 template<typename NumberType, typename std::enable_if< 16287 std::is_unsigned<NumberType>::value, int>::type = 0> 16288 void write_number_with_ubjson_prefix(const NumberType n, 16289 const bool add_prefix, 16290 const bool use_bjdata) 16291 { 16292 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) 16293 { 16294 if (add_prefix) 16295 { 16296 oa->write_character(to_char_type('i')); // int8 16297 } 16298 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16299 } 16300 else if (n <= (std::numeric_limits<std::uint8_t>::max)()) 16301 { 16302 if (add_prefix) 16303 { 16304 oa->write_character(to_char_type('U')); // uint8 16305 } 16306 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16307 } 16308 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) 16309 { 16310 if (add_prefix) 16311 { 16312 oa->write_character(to_char_type('I')); // int16 16313 } 16314 write_number(static_cast<std::int16_t>(n), use_bjdata); 16315 } 16316 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) 16317 { 16318 if (add_prefix) 16319 { 16320 oa->write_character(to_char_type('u')); // uint16 - bjdata only 16321 } 16322 write_number(static_cast<std::uint16_t>(n), use_bjdata); 16323 } 16324 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16325 { 16326 if (add_prefix) 16327 { 16328 oa->write_character(to_char_type('l')); // int32 16329 } 16330 write_number(static_cast<std::int32_t>(n), use_bjdata); 16331 } 16332 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) 16333 { 16334 if (add_prefix) 16335 { 16336 oa->write_character(to_char_type('m')); // uint32 - bjdata only 16337 } 16338 write_number(static_cast<std::uint32_t>(n), use_bjdata); 16339 } 16340 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16341 { 16342 if (add_prefix) 16343 { 16344 oa->write_character(to_char_type('L')); // int64 16345 } 16346 write_number(static_cast<std::int64_t>(n), use_bjdata); 16347 } 16348 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) 16349 { 16350 if (add_prefix) 16351 { 16352 oa->write_character(to_char_type('M')); // uint64 - bjdata only 16353 } 16354 write_number(static_cast<std::uint64_t>(n), use_bjdata); 16355 } 16356 else 16357 { 16358 if (add_prefix) 16359 { 16360 oa->write_character(to_char_type('H')); // high-precision number 16361 } 16362 16363 const auto number = BasicJsonType(n).dump(); 16364 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); 16365 for (std::size_t i = 0; i < number.size(); ++i) 16366 { 16367 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); 16368 } 16369 } 16370 } 16371 16372 // UBJSON: write number (signed integer) 16373 template < typename NumberType, typename std::enable_if < 16374 std::is_signed<NumberType>::value&& 16375 !std::is_floating_point<NumberType>::value, int >::type = 0 > 16376 void write_number_with_ubjson_prefix(const NumberType n, 16377 const bool add_prefix, 16378 const bool use_bjdata) 16379 { 16380 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) 16381 { 16382 if (add_prefix) 16383 { 16384 oa->write_character(to_char_type('i')); // int8 16385 } 16386 write_number(static_cast<std::int8_t>(n), use_bjdata); 16387 } 16388 else 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)())) 16389 { 16390 if (add_prefix) 16391 { 16392 oa->write_character(to_char_type('U')); // uint8 16393 } 16394 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16395 } 16396 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) 16397 { 16398 if (add_prefix) 16399 { 16400 oa->write_character(to_char_type('I')); // int16 16401 } 16402 write_number(static_cast<std::int16_t>(n), use_bjdata); 16403 } 16404 else 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)()))) 16405 { 16406 if (add_prefix) 16407 { 16408 oa->write_character(to_char_type('u')); // uint16 - bjdata only 16409 } 16410 write_number(static_cast<uint16_t>(n), use_bjdata); 16411 } 16412 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) 16413 { 16414 if (add_prefix) 16415 { 16416 oa->write_character(to_char_type('l')); // int32 16417 } 16418 write_number(static_cast<std::int32_t>(n), use_bjdata); 16419 } 16420 else 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)()))) 16421 { 16422 if (add_prefix) 16423 { 16424 oa->write_character(to_char_type('m')); // uint32 - bjdata only 16425 } 16426 write_number(static_cast<uint32_t>(n), use_bjdata); 16427 } 16428 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) 16429 { 16430 if (add_prefix) 16431 { 16432 oa->write_character(to_char_type('L')); // int64 16433 } 16434 write_number(static_cast<std::int64_t>(n), use_bjdata); 16435 } 16436 // LCOV_EXCL_START 16437 else 16438 { 16439 if (add_prefix) 16440 { 16441 oa->write_character(to_char_type('H')); // high-precision number 16442 } 16443 16444 const auto number = BasicJsonType(n).dump(); 16445 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); 16446 for (std::size_t i = 0; i < number.size(); ++i) 16447 { 16448 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); 16449 } 16450 } 16451 // LCOV_EXCL_STOP 16452 } 16453 16454 /*! 16455 @brief determine the type prefix of container values 16456 */ 16457 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept 16458 { 16459 switch (j.type()) 16460 { 16461 case value_t::null: 16462 return 'Z'; 16463 16464 case value_t::boolean: 16465 return j.m_value.boolean ? 'T' : 'F'; 16466 16467 case value_t::number_integer: 16468 { 16469 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 16470 { 16471 return 'i'; 16472 } 16473 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 16474 { 16475 return 'U'; 16476 } 16477 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 16478 { 16479 return 'I'; 16480 } 16481 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())) 16482 { 16483 return 'u'; 16484 } 16485 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 16486 { 16487 return 'l'; 16488 } 16489 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())) 16490 { 16491 return 'm'; 16492 } 16493 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) 16494 { 16495 return 'L'; 16496 } 16497 // anything else is treated as high-precision number 16498 return 'H'; // LCOV_EXCL_LINE 16499 } 16500 16501 case value_t::number_unsigned: 16502 { 16503 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) 16504 { 16505 return 'i'; 16506 } 16507 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)())) 16508 { 16509 return 'U'; 16510 } 16511 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) 16512 { 16513 return 'I'; 16514 } 16515 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) 16516 { 16517 return 'u'; 16518 } 16519 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16520 { 16521 return 'l'; 16522 } 16523 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) 16524 { 16525 return 'm'; 16526 } 16527 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16528 { 16529 return 'L'; 16530 } 16531 if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 16532 { 16533 return 'M'; 16534 } 16535 // anything else is treated as high-precision number 16536 return 'H'; // LCOV_EXCL_LINE 16537 } 16538 16539 case value_t::number_float: 16540 return get_ubjson_float_prefix(j.m_value.number_float); 16541 16542 case value_t::string: 16543 return 'S'; 16544 16545 case value_t::array: // fallthrough 16546 case value_t::binary: 16547 return '['; 16548 16549 case value_t::object: 16550 return '{'; 16551 16552 case value_t::discarded: 16553 default: // discarded values 16554 return 'N'; 16555 } 16556 } 16557 16558 static constexpr CharType get_ubjson_float_prefix(float /*unused*/) 16559 { 16560 return 'd'; // float 32 16561 } 16562 16563 static constexpr CharType get_ubjson_float_prefix(double /*unused*/) 16564 { 16565 return 'D'; // float 64 16566 } 16567 16568 /*! 16569 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid 16570 */ 16571 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type) 16572 { 16573 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'}, 16574 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'} 16575 }; 16576 16577 string_t key = "_ArrayType_"; 16578 auto it = bjdtype.find(static_cast<string_t>(value.at(key))); 16579 if (it == bjdtype.end()) 16580 { 16581 return true; 16582 } 16583 CharType dtype = it->second; 16584 16585 key = "_ArraySize_"; 16586 std::size_t len = (value.at(key).empty() ? 0 : 1); 16587 for (const auto& el : value.at(key)) 16588 { 16589 len *= static_cast<std::size_t>(el.m_value.number_unsigned); 16590 } 16591 16592 key = "_ArrayData_"; 16593 if (value.at(key).size() != len) 16594 { 16595 return true; 16596 } 16597 16598 oa->write_character('['); 16599 oa->write_character('$'); 16600 oa->write_character(dtype); 16601 oa->write_character('#'); 16602 16603 key = "_ArraySize_"; 16604 write_ubjson(value.at(key), use_count, use_type, true, true); 16605 16606 key = "_ArrayData_"; 16607 if (dtype == 'U' || dtype == 'C') 16608 { 16609 for (const auto& el : value.at(key)) 16610 { 16611 write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true); 16612 } 16613 } 16614 else if (dtype == 'i') 16615 { 16616 for (const auto& el : value.at(key)) 16617 { 16618 write_number(static_cast<std::int8_t>(el.m_value.number_integer), true); 16619 } 16620 } 16621 else if (dtype == 'u') 16622 { 16623 for (const auto& el : value.at(key)) 16624 { 16625 write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true); 16626 } 16627 } 16628 else if (dtype == 'I') 16629 { 16630 for (const auto& el : value.at(key)) 16631 { 16632 write_number(static_cast<std::int16_t>(el.m_value.number_integer), true); 16633 } 16634 } 16635 else if (dtype == 'm') 16636 { 16637 for (const auto& el : value.at(key)) 16638 { 16639 write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true); 16640 } 16641 } 16642 else if (dtype == 'l') 16643 { 16644 for (const auto& el : value.at(key)) 16645 { 16646 write_number(static_cast<std::int32_t>(el.m_value.number_integer), true); 16647 } 16648 } 16649 else if (dtype == 'M') 16650 { 16651 for (const auto& el : value.at(key)) 16652 { 16653 write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true); 16654 } 16655 } 16656 else if (dtype == 'L') 16657 { 16658 for (const auto& el : value.at(key)) 16659 { 16660 write_number(static_cast<std::int64_t>(el.m_value.number_integer), true); 16661 } 16662 } 16663 else if (dtype == 'd') 16664 { 16665 for (const auto& el : value.at(key)) 16666 { 16667 write_number(static_cast<float>(el.m_value.number_float), true); 16668 } 16669 } 16670 else if (dtype == 'D') 16671 { 16672 for (const auto& el : value.at(key)) 16673 { 16674 write_number(static_cast<double>(el.m_value.number_float), true); 16675 } 16676 } 16677 return false; 16678 } 16679 16680 /////////////////////// 16681 // Utility functions // 16682 /////////////////////// 16683 16684 /* 16685 @brief write a number to output input 16686 @param[in] n number of type @a NumberType 16687 @param[in] OutputIsLittleEndian Set to true if output data is 16688 required to be little endian 16689 @tparam NumberType the type of the number 16690 16691 @note This function needs to respect the system's endianness, because bytes 16692 in CBOR, MessagePack, and UBJSON are stored in network order (big 16693 endian) and therefore need reordering on little endian systems. 16694 On the other hand, BSON and BJData use little endian and should reorder 16695 on big endian systems. 16696 */ 16697 template<typename NumberType> 16698 void write_number(const NumberType n, const bool OutputIsLittleEndian = false) 16699 { 16700 // step 1: write number to array of length NumberType 16701 std::array<CharType, sizeof(NumberType)> vec{}; 16702 std::memcpy(vec.data(), &n, sizeof(NumberType)); 16703 16704 // step 2: write array to output (with possible reordering) 16705 if (is_little_endian != OutputIsLittleEndian) 16706 { 16707 // reverse byte order prior to conversion if necessary 16708 std::reverse(vec.begin(), vec.end()); 16709 } 16710 16711 oa->write_characters(vec.data(), sizeof(NumberType)); 16712 } 16713 16714 void write_compact_float(const number_float_t n, detail::input_format_t format) 16715 { 16716 #ifdef __GNUC__ 16717 #pragma GCC diagnostic push 16718 #pragma GCC diagnostic ignored "-Wfloat-equal" 16719 #endif 16720 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) && 16721 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) && 16722 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n)) 16723 { 16724 oa->write_character(format == detail::input_format_t::cbor 16725 ? get_cbor_float_prefix(static_cast<float>(n)) 16726 : get_msgpack_float_prefix(static_cast<float>(n))); 16727 write_number(static_cast<float>(n)); 16728 } 16729 else 16730 { 16731 oa->write_character(format == detail::input_format_t::cbor 16732 ? get_cbor_float_prefix(n) 16733 : get_msgpack_float_prefix(n)); 16734 write_number(n); 16735 } 16736 #ifdef __GNUC__ 16737 #pragma GCC diagnostic pop 16738 #endif 16739 } 16740 16741 public: 16742 // The following to_char_type functions are implement the conversion 16743 // between uint8_t and CharType. In case CharType is not unsigned, 16744 // such a conversion is required to allow values greater than 128. 16745 // See <https://github.com/nlohmann/json/issues/1286> for a discussion. 16746 template < typename C = CharType, 16747 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr > 16748 static constexpr CharType to_char_type(std::uint8_t x) noexcept 16749 { 16750 return *reinterpret_cast<char*>(&x); 16751 } 16752 16753 template < typename C = CharType, 16754 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr > 16755 static CharType to_char_type(std::uint8_t x) noexcept 16756 { 16757 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); 16758 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial"); 16759 CharType result; 16760 std::memcpy(&result, &x, sizeof(x)); 16761 return result; 16762 } 16763 16764 template<typename C = CharType, 16765 enable_if_t<std::is_unsigned<C>::value>* = nullptr> 16766 static constexpr CharType to_char_type(std::uint8_t x) noexcept 16767 { 16768 return x; 16769 } 16770 16771 template < typename InputCharType, typename C = CharType, 16772 enable_if_t < 16773 std::is_signed<C>::value && 16774 std::is_signed<char>::value && 16775 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value 16776 > * = nullptr > 16777 static constexpr CharType to_char_type(InputCharType x) noexcept 16778 { 16779 return x; 16780 } 16781 16782 private: 16783 /// whether we can assume little endianness 16784 const bool is_little_endian = little_endianness(); 16785 16786 /// the output 16787 output_adapter_t<CharType> oa = nullptr; 16788 }; 16789 16790 } // namespace detail 16791 NLOHMANN_JSON_NAMESPACE_END 16792 16793 // #include <nlohmann/detail/output/output_adapters.hpp> 16794 16795 // #include <nlohmann/detail/output/serializer.hpp> 16796 // __ _____ _____ _____ 16797 // __| | __| | | | JSON for Modern C++ 16798 // | | |__ | | | | | | version 3.11.2 16799 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 16800 // 16801 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de> 16802 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 16803 // SPDX-License-Identifier: MIT 16804 16805 16806 16807 #include <algorithm> // reverse, remove, fill, find, none_of 16808 #include <array> // array 16809 #include <clocale> // localeconv, lconv 16810 #include <cmath> // labs, isfinite, isnan, signbit 16811 #include <cstddef> // size_t, ptrdiff_t 16812 #include <cstdint> // uint8_t 16813 #include <cstdio> // snprintf 16814 #include <limits> // numeric_limits 16815 #include <string> // string, char_traits 16816 #include <iomanip> // setfill, setw 16817 #include <type_traits> // is_same 16818 #include <utility> // move 16819 16820 // #include <nlohmann/detail/conversions/to_chars.hpp> 16821 // __ _____ _____ _____ 16822 // __| | __| | | | JSON for Modern C++ 16823 // | | |__ | | | | | | version 3.11.2 16824 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 16825 // 16826 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/> 16827 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 16828 // SPDX-License-Identifier: MIT 16829 16830 16831 16832 #include <array> // array 16833 #include <cmath> // signbit, isfinite 16834 #include <cstdint> // intN_t, uintN_t 16835 #include <cstring> // memcpy, memmove 16836 #include <limits> // numeric_limits 16837 #include <type_traits> // conditional 16838 16839 // #include <nlohmann/detail/macro_scope.hpp> 16840 16841 16842 NLOHMANN_JSON_NAMESPACE_BEGIN 16843 namespace detail 16844 { 16845 16846 /*! 16847 @brief implements the Grisu2 algorithm for binary to decimal floating-point 16848 conversion. 16849 16850 This implementation is a slightly modified version of the reference 16851 implementation which may be obtained from 16852 http://florian.loitsch.com/publications (bench.tar.gz). 16853 16854 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. 16855 16856 For a detailed description of the algorithm see: 16857 16858 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with 16859 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming 16860 Language Design and Implementation, PLDI 2010 16861 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", 16862 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language 16863 Design and Implementation, PLDI 1996 16864 */ 16865 namespace dtoa_impl 16866 { 16867 16868 template<typename Target, typename Source> 16869 Target reinterpret_bits(const Source source) 16870 { 16871 static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); 16872 16873 Target target; 16874 std::memcpy(&target, &source, sizeof(Source)); 16875 return target; 16876 } 16877 16878 struct diyfp // f * 2^e 16879 { 16880 static constexpr int kPrecision = 64; // = q 16881 16882 std::uint64_t f = 0; 16883 int e = 0; 16884 16885 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} 16886 16887 /*! 16888 @brief returns x - y 16889 @pre x.e == y.e and x.f >= y.f 16890 */ 16891 static diyfp sub(const diyfp& x, const diyfp& y) noexcept 16892 { 16893 JSON_ASSERT(x.e == y.e); 16894 JSON_ASSERT(x.f >= y.f); 16895 16896 return {x.f - y.f, x.e}; 16897 } 16898 16899 /*! 16900 @brief returns x * y 16901 @note The result is rounded. (Only the upper q bits are returned.) 16902 */ 16903 static diyfp mul(const diyfp& x, const diyfp& y) noexcept 16904 { 16905 static_assert(kPrecision == 64, "internal error"); 16906 16907 // Computes: 16908 // f = round((x.f * y.f) / 2^q) 16909 // e = x.e + y.e + q 16910 16911 // Emulate the 64-bit * 64-bit multiplication: 16912 // 16913 // p = u * v 16914 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) 16915 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) 16916 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) 16917 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) 16918 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) 16919 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) 16920 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) 16921 // 16922 // (Since Q might be larger than 2^32 - 1) 16923 // 16924 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) 16925 // 16926 // (Q_hi + H does not overflow a 64-bit int) 16927 // 16928 // = p_lo + 2^64 p_hi 16929 16930 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; 16931 const std::uint64_t u_hi = x.f >> 32u; 16932 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; 16933 const std::uint64_t v_hi = y.f >> 32u; 16934 16935 const std::uint64_t p0 = u_lo * v_lo; 16936 const std::uint64_t p1 = u_lo * v_hi; 16937 const std::uint64_t p2 = u_hi * v_lo; 16938 const std::uint64_t p3 = u_hi * v_hi; 16939 16940 const std::uint64_t p0_hi = p0 >> 32u; 16941 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; 16942 const std::uint64_t p1_hi = p1 >> 32u; 16943 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; 16944 const std::uint64_t p2_hi = p2 >> 32u; 16945 16946 std::uint64_t Q = p0_hi + p1_lo + p2_lo; 16947 16948 // The full product might now be computed as 16949 // 16950 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) 16951 // p_lo = p0_lo + (Q << 32) 16952 // 16953 // But in this particular case here, the full p_lo is not required. 16954 // Effectively we only need to add the highest bit in p_lo to p_hi (and 16955 // Q_hi + 1 does not overflow). 16956 16957 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up 16958 16959 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); 16960 16961 return {h, x.e + y.e + 64}; 16962 } 16963 16964 /*! 16965 @brief normalize x such that the significand is >= 2^(q-1) 16966 @pre x.f != 0 16967 */ 16968 static diyfp normalize(diyfp x) noexcept 16969 { 16970 JSON_ASSERT(x.f != 0); 16971 16972 while ((x.f >> 63u) == 0) 16973 { 16974 x.f <<= 1u; 16975 x.e--; 16976 } 16977 16978 return x; 16979 } 16980 16981 /*! 16982 @brief normalize x such that the result has the exponent E 16983 @pre e >= x.e and the upper e - x.e bits of x.f must be zero. 16984 */ 16985 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept 16986 { 16987 const int delta = x.e - target_exponent; 16988 16989 JSON_ASSERT(delta >= 0); 16990 JSON_ASSERT(((x.f << delta) >> delta) == x.f); 16991 16992 return {x.f << delta, target_exponent}; 16993 } 16994 }; 16995 16996 struct boundaries 16997 { 16998 diyfp w; 16999 diyfp minus; 17000 diyfp plus; 17001 }; 17002 17003 /*! 17004 Compute the (normalized) diyfp representing the input number 'value' and its 17005 boundaries. 17006 17007 @pre value must be finite and positive 17008 */ 17009 template<typename FloatType> 17010 boundaries compute_boundaries(FloatType value) 17011 { 17012 JSON_ASSERT(std::isfinite(value)); 17013 JSON_ASSERT(value > 0); 17014 17015 // Convert the IEEE representation into a diyfp. 17016 // 17017 // If v is denormal: 17018 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) 17019 // If v is normalized: 17020 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) 17021 17022 static_assert(std::numeric_limits<FloatType>::is_iec559, 17023 "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); 17024 17025 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit) 17026 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1); 17027 constexpr int kMinExp = 1 - kBias; 17028 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) 17029 17030 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type; 17031 17032 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value)); 17033 const std::uint64_t E = bits >> (kPrecision - 1); 17034 const std::uint64_t F = bits & (kHiddenBit - 1); 17035 17036 const bool is_denormal = E == 0; 17037 const diyfp v = is_denormal 17038 ? diyfp(F, kMinExp) 17039 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias); 17040 17041 // Compute the boundaries m- and m+ of the floating-point value 17042 // v = f * 2^e. 17043 // 17044 // Determine v- and v+, the floating-point predecessor and successor if v, 17045 // respectively. 17046 // 17047 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) 17048 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) 17049 // 17050 // v+ = v + 2^e 17051 // 17052 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ 17053 // between m- and m+ round to v, regardless of how the input rounding 17054 // algorithm breaks ties. 17055 // 17056 // ---+-------------+-------------+-------------+-------------+--- (A) 17057 // v- m- v m+ v+ 17058 // 17059 // -----------------+------+------+-------------+-------------+--- (B) 17060 // v- m- v m+ v+ 17061 17062 const bool lower_boundary_is_closer = F == 0 && E > 1; 17063 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); 17064 const diyfp m_minus = lower_boundary_is_closer 17065 ? diyfp(4 * v.f - 1, v.e - 2) // (B) 17066 : diyfp(2 * v.f - 1, v.e - 1); // (A) 17067 17068 // Determine the normalized w+ = m+. 17069 const diyfp w_plus = diyfp::normalize(m_plus); 17070 17071 // Determine w- = m- such that e_(w-) = e_(w+). 17072 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); 17073 17074 return {diyfp::normalize(v), w_minus, w_plus}; 17075 } 17076 17077 // Given normalized diyfp w, Grisu needs to find a (normalized) cached 17078 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies 17079 // within a certain range [alpha, gamma] (Definition 3.2 from [1]) 17080 // 17081 // alpha <= e = e_c + e_w + q <= gamma 17082 // 17083 // or 17084 // 17085 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q 17086 // <= f_c * f_w * 2^gamma 17087 // 17088 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies 17089 // 17090 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma 17091 // 17092 // or 17093 // 17094 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) 17095 // 17096 // The choice of (alpha,gamma) determines the size of the table and the form of 17097 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well 17098 // in practice: 17099 // 17100 // The idea is to cut the number c * w = f * 2^e into two parts, which can be 17101 // processed independently: An integral part p1, and a fractional part p2: 17102 // 17103 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e 17104 // = (f div 2^-e) + (f mod 2^-e) * 2^e 17105 // = p1 + p2 * 2^e 17106 // 17107 // The conversion of p1 into decimal form requires a series of divisions and 17108 // modulos by (a power of) 10. These operations are faster for 32-bit than for 17109 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be 17110 // achieved by choosing 17111 // 17112 // -e >= 32 or e <= -32 := gamma 17113 // 17114 // In order to convert the fractional part 17115 // 17116 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... 17117 // 17118 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits 17119 // d[-i] are extracted in order: 17120 // 17121 // (10 * p2) div 2^-e = d[-1] 17122 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ... 17123 // 17124 // The multiplication by 10 must not overflow. It is sufficient to choose 17125 // 17126 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. 17127 // 17128 // Since p2 = f mod 2^-e < 2^-e, 17129 // 17130 // -e <= 60 or e >= -60 := alpha 17131 17132 constexpr int kAlpha = -60; 17133 constexpr int kGamma = -32; 17134 17135 struct cached_power // c = f * 2^e ~= 10^k 17136 { 17137 std::uint64_t f; 17138 int e; 17139 int k; 17140 }; 17141 17142 /*! 17143 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached 17144 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c 17145 satisfies (Definition 3.2 from [1]) 17146 17147 alpha <= e_c + e + q <= gamma. 17148 */ 17149 inline cached_power get_cached_power_for_binary_exponent(int e) 17150 { 17151 // Now 17152 // 17153 // alpha <= e_c + e + q <= gamma (1) 17154 // ==> f_c * 2^alpha <= c * 2^e * 2^q 17155 // 17156 // and since the c's are normalized, 2^(q-1) <= f_c, 17157 // 17158 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) 17159 // ==> 2^(alpha - e - 1) <= c 17160 // 17161 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as 17162 // 17163 // k = ceil( log_10( 2^(alpha - e - 1) ) ) 17164 // = ceil( (alpha - e - 1) * log_10(2) ) 17165 // 17166 // From the paper: 17167 // "In theory the result of the procedure could be wrong since c is rounded, 17168 // and the computation itself is approximated [...]. In practice, however, 17169 // this simple function is sufficient." 17170 // 17171 // For IEEE double precision floating-point numbers converted into 17172 // normalized diyfp's w = f * 2^e, with q = 64, 17173 // 17174 // e >= -1022 (min IEEE exponent) 17175 // -52 (p - 1) 17176 // -52 (p - 1, possibly normalize denormal IEEE numbers) 17177 // -11 (normalize the diyfp) 17178 // = -1137 17179 // 17180 // and 17181 // 17182 // e <= +1023 (max IEEE exponent) 17183 // -52 (p - 1) 17184 // -11 (normalize the diyfp) 17185 // = 960 17186 // 17187 // This binary exponent range [-1137,960] results in a decimal exponent 17188 // range [-307,324]. One does not need to store a cached power for each 17189 // k in this range. For each such k it suffices to find a cached power 17190 // such that the exponent of the product lies in [alpha,gamma]. 17191 // This implies that the difference of the decimal exponents of adjacent 17192 // table entries must be less than or equal to 17193 // 17194 // floor( (gamma - alpha) * log_10(2) ) = 8. 17195 // 17196 // (A smaller distance gamma-alpha would require a larger table.) 17197 17198 // NB: 17199 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. 17200 17201 constexpr int kCachedPowersMinDecExp = -300; 17202 constexpr int kCachedPowersDecStep = 8; 17203 17204 static constexpr std::array<cached_power, 79> kCachedPowers = 17205 { 17206 { 17207 { 0xAB70FE17C79AC6CA, -1060, -300 }, 17208 { 0xFF77B1FCBEBCDC4F, -1034, -292 }, 17209 { 0xBE5691EF416BD60C, -1007, -284 }, 17210 { 0x8DD01FAD907FFC3C, -980, -276 }, 17211 { 0xD3515C2831559A83, -954, -268 }, 17212 { 0x9D71AC8FADA6C9B5, -927, -260 }, 17213 { 0xEA9C227723EE8BCB, -901, -252 }, 17214 { 0xAECC49914078536D, -874, -244 }, 17215 { 0x823C12795DB6CE57, -847, -236 }, 17216 { 0xC21094364DFB5637, -821, -228 }, 17217 { 0x9096EA6F3848984F, -794, -220 }, 17218 { 0xD77485CB25823AC7, -768, -212 }, 17219 { 0xA086CFCD97BF97F4, -741, -204 }, 17220 { 0xEF340A98172AACE5, -715, -196 }, 17221 { 0xB23867FB2A35B28E, -688, -188 }, 17222 { 0x84C8D4DFD2C63F3B, -661, -180 }, 17223 { 0xC5DD44271AD3CDBA, -635, -172 }, 17224 { 0x936B9FCEBB25C996, -608, -164 }, 17225 { 0xDBAC6C247D62A584, -582, -156 }, 17226 { 0xA3AB66580D5FDAF6, -555, -148 }, 17227 { 0xF3E2F893DEC3F126, -529, -140 }, 17228 { 0xB5B5ADA8AAFF80B8, -502, -132 }, 17229 { 0x87625F056C7C4A8B, -475, -124 }, 17230 { 0xC9BCFF6034C13053, -449, -116 }, 17231 { 0x964E858C91BA2655, -422, -108 }, 17232 { 0xDFF9772470297EBD, -396, -100 }, 17233 { 0xA6DFBD9FB8E5B88F, -369, -92 }, 17234 { 0xF8A95FCF88747D94, -343, -84 }, 17235 { 0xB94470938FA89BCF, -316, -76 }, 17236 { 0x8A08F0F8BF0F156B, -289, -68 }, 17237 { 0xCDB02555653131B6, -263, -60 }, 17238 { 0x993FE2C6D07B7FAC, -236, -52 }, 17239 { 0xE45C10C42A2B3B06, -210, -44 }, 17240 { 0xAA242499697392D3, -183, -36 }, 17241 { 0xFD87B5F28300CA0E, -157, -28 }, 17242 { 0xBCE5086492111AEB, -130, -20 }, 17243 { 0x8CBCCC096F5088CC, -103, -12 }, 17244 { 0xD1B71758E219652C, -77, -4 }, 17245 { 0x9C40000000000000, -50, 4 }, 17246 { 0xE8D4A51000000000, -24, 12 }, 17247 { 0xAD78EBC5AC620000, 3, 20 }, 17248 { 0x813F3978F8940984, 30, 28 }, 17249 { 0xC097CE7BC90715B3, 56, 36 }, 17250 { 0x8F7E32CE7BEA5C70, 83, 44 }, 17251 { 0xD5D238A4ABE98068, 109, 52 }, 17252 { 0x9F4F2726179A2245, 136, 60 }, 17253 { 0xED63A231D4C4FB27, 162, 68 }, 17254 { 0xB0DE65388CC8ADA8, 189, 76 }, 17255 { 0x83C7088E1AAB65DB, 216, 84 }, 17256 { 0xC45D1DF942711D9A, 242, 92 }, 17257 { 0x924D692CA61BE758, 269, 100 }, 17258 { 0xDA01EE641A708DEA, 295, 108 }, 17259 { 0xA26DA3999AEF774A, 322, 116 }, 17260 { 0xF209787BB47D6B85, 348, 124 }, 17261 { 0xB454E4A179DD1877, 375, 132 }, 17262 { 0x865B86925B9BC5C2, 402, 140 }, 17263 { 0xC83553C5C8965D3D, 428, 148 }, 17264 { 0x952AB45CFA97A0B3, 455, 156 }, 17265 { 0xDE469FBD99A05FE3, 481, 164 }, 17266 { 0xA59BC234DB398C25, 508, 172 }, 17267 { 0xF6C69A72A3989F5C, 534, 180 }, 17268 { 0xB7DCBF5354E9BECE, 561, 188 }, 17269 { 0x88FCF317F22241E2, 588, 196 }, 17270 { 0xCC20CE9BD35C78A5, 614, 204 }, 17271 { 0x98165AF37B2153DF, 641, 212 }, 17272 { 0xE2A0B5DC971F303A, 667, 220 }, 17273 { 0xA8D9D1535CE3B396, 694, 228 }, 17274 { 0xFB9B7CD9A4A7443C, 720, 236 }, 17275 { 0xBB764C4CA7A44410, 747, 244 }, 17276 { 0x8BAB8EEFB6409C1A, 774, 252 }, 17277 { 0xD01FEF10A657842C, 800, 260 }, 17278 { 0x9B10A4E5E9913129, 827, 268 }, 17279 { 0xE7109BFBA19C0C9D, 853, 276 }, 17280 { 0xAC2820D9623BF429, 880, 284 }, 17281 { 0x80444B5E7AA7CF85, 907, 292 }, 17282 { 0xBF21E44003ACDD2D, 933, 300 }, 17283 { 0x8E679C2F5E44FF8F, 960, 308 }, 17284 { 0xD433179D9C8CB841, 986, 316 }, 17285 { 0x9E19DB92B4E31BA9, 1013, 324 }, 17286 } 17287 }; 17288 17289 // This computation gives exactly the same results for k as 17290 // k = ceil((kAlpha - e - 1) * 0.30102999566398114) 17291 // for |e| <= 1500, but doesn't require floating-point operations. 17292 // NB: log_10(2) ~= 78913 / 2^18 17293 JSON_ASSERT(e >= -1500); 17294 JSON_ASSERT(e <= 1500); 17295 const int f = kAlpha - e - 1; 17296 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0); 17297 17298 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; 17299 JSON_ASSERT(index >= 0); 17300 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size()); 17301 17302 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)]; 17303 JSON_ASSERT(kAlpha <= cached.e + e + 64); 17304 JSON_ASSERT(kGamma >= cached.e + e + 64); 17305 17306 return cached; 17307 } 17308 17309 /*! 17310 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. 17311 For n == 0, returns 1 and sets pow10 := 1. 17312 */ 17313 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) 17314 { 17315 // LCOV_EXCL_START 17316 if (n >= 1000000000) 17317 { 17318 pow10 = 1000000000; 17319 return 10; 17320 } 17321 // LCOV_EXCL_STOP 17322 if (n >= 100000000) 17323 { 17324 pow10 = 100000000; 17325 return 9; 17326 } 17327 if (n >= 10000000) 17328 { 17329 pow10 = 10000000; 17330 return 8; 17331 } 17332 if (n >= 1000000) 17333 { 17334 pow10 = 1000000; 17335 return 7; 17336 } 17337 if (n >= 100000) 17338 { 17339 pow10 = 100000; 17340 return 6; 17341 } 17342 if (n >= 10000) 17343 { 17344 pow10 = 10000; 17345 return 5; 17346 } 17347 if (n >= 1000) 17348 { 17349 pow10 = 1000; 17350 return 4; 17351 } 17352 if (n >= 100) 17353 { 17354 pow10 = 100; 17355 return 3; 17356 } 17357 if (n >= 10) 17358 { 17359 pow10 = 10; 17360 return 2; 17361 } 17362 17363 pow10 = 1; 17364 return 1; 17365 } 17366 17367 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, 17368 std::uint64_t rest, std::uint64_t ten_k) 17369 { 17370 JSON_ASSERT(len >= 1); 17371 JSON_ASSERT(dist <= delta); 17372 JSON_ASSERT(rest <= delta); 17373 JSON_ASSERT(ten_k > 0); 17374 17375 // <--------------------------- delta ----> 17376 // <---- dist ---------> 17377 // --------------[------------------+-------------------]-------------- 17378 // M- w M+ 17379 // 17380 // ten_k 17381 // <------> 17382 // <---- rest ----> 17383 // --------------[------------------+----+--------------]-------------- 17384 // w V 17385 // = buf * 10^k 17386 // 17387 // ten_k represents a unit-in-the-last-place in the decimal representation 17388 // stored in buf. 17389 // Decrement buf by ten_k while this takes buf closer to w. 17390 17391 // The tests are written in this order to avoid overflow in unsigned 17392 // integer arithmetic. 17393 17394 while (rest < dist 17395 && delta - rest >= ten_k 17396 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) 17397 { 17398 JSON_ASSERT(buf[len - 1] != '0'); 17399 buf[len - 1]--; 17400 rest += ten_k; 17401 } 17402 } 17403 17404 /*! 17405 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. 17406 M- and M+ must be normalized and share the same exponent -60 <= e <= -32. 17407 */ 17408 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, 17409 diyfp M_minus, diyfp w, diyfp M_plus) 17410 { 17411 static_assert(kAlpha >= -60, "internal error"); 17412 static_assert(kGamma <= -32, "internal error"); 17413 17414 // Generates the digits (and the exponent) of a decimal floating-point 17415 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's 17416 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. 17417 // 17418 // <--------------------------- delta ----> 17419 // <---- dist ---------> 17420 // --------------[------------------+-------------------]-------------- 17421 // M- w M+ 17422 // 17423 // Grisu2 generates the digits of M+ from left to right and stops as soon as 17424 // V is in [M-,M+]. 17425 17426 JSON_ASSERT(M_plus.e >= kAlpha); 17427 JSON_ASSERT(M_plus.e <= kGamma); 17428 17429 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) 17430 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) 17431 17432 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): 17433 // 17434 // M+ = f * 2^e 17435 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e 17436 // = ((p1 ) * 2^-e + (p2 )) * 2^e 17437 // = p1 + p2 * 2^e 17438 17439 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); 17440 17441 auto 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.) 17442 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e 17443 17444 // 1) 17445 // 17446 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] 17447 17448 JSON_ASSERT(p1 > 0); 17449 17450 std::uint32_t pow10{}; 17451 const int k = find_largest_pow10(p1, pow10); 17452 17453 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) 17454 // 17455 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) 17456 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) 17457 // 17458 // M+ = p1 + p2 * 2^e 17459 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e 17460 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e 17461 // = d[k-1] * 10^(k-1) + ( rest) * 2^e 17462 // 17463 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) 17464 // 17465 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] 17466 // 17467 // but stop as soon as 17468 // 17469 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e 17470 17471 int n = k; 17472 while (n > 0) 17473 { 17474 // Invariants: 17475 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) 17476 // pow10 = 10^(n-1) <= p1 < 10^n 17477 // 17478 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) 17479 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) 17480 // 17481 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e 17482 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) 17483 // 17484 JSON_ASSERT(d <= 9); 17485 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 17486 // 17487 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) 17488 // 17489 p1 = r; 17490 n--; 17491 // 17492 // M+ = buffer * 10^n + (p1 + p2 * 2^e) 17493 // pow10 = 10^n 17494 // 17495 17496 // Now check if enough digits have been generated. 17497 // Compute 17498 // 17499 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e 17500 // 17501 // Note: 17502 // Since rest and delta share the same exponent e, it suffices to 17503 // compare the significands. 17504 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; 17505 if (rest <= delta) 17506 { 17507 // V = buffer * 10^n, with M- <= V <= M+. 17508 17509 decimal_exponent += n; 17510 17511 // We may now just stop. But instead look if the buffer could be 17512 // decremented to bring V closer to w. 17513 // 17514 // pow10 = 10^n is now 1 ulp in the decimal representation V. 17515 // The rounding procedure works with diyfp's with an implicit 17516 // exponent of e. 17517 // 17518 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e 17519 // 17520 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; 17521 grisu2_round(buffer, length, dist, delta, rest, ten_n); 17522 17523 return; 17524 } 17525 17526 pow10 /= 10; 17527 // 17528 // pow10 = 10^(n-1) <= p1 < 10^n 17529 // Invariants restored. 17530 } 17531 17532 // 2) 17533 // 17534 // The digits of the integral part have been generated: 17535 // 17536 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e 17537 // = buffer + p2 * 2^e 17538 // 17539 // Now generate the digits of the fractional part p2 * 2^e. 17540 // 17541 // Note: 17542 // No decimal point is generated: the exponent is adjusted instead. 17543 // 17544 // p2 actually represents the fraction 17545 // 17546 // p2 * 2^e 17547 // = p2 / 2^-e 17548 // = d[-1] / 10^1 + d[-2] / 10^2 + ... 17549 // 17550 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) 17551 // 17552 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m 17553 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) 17554 // 17555 // using 17556 // 17557 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) 17558 // = ( d) * 2^-e + ( r) 17559 // 17560 // or 17561 // 10^m * p2 * 2^e = d + r * 2^e 17562 // 17563 // i.e. 17564 // 17565 // M+ = buffer + p2 * 2^e 17566 // = buffer + 10^-m * (d + r * 2^e) 17567 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e 17568 // 17569 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e 17570 17571 JSON_ASSERT(p2 > delta); 17572 17573 int m = 0; 17574 for (;;) 17575 { 17576 // Invariant: 17577 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e 17578 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e 17579 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e 17580 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e 17581 // 17582 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10); 17583 p2 *= 10; 17584 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e 17585 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e 17586 // 17587 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e 17588 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) 17589 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e 17590 // 17591 JSON_ASSERT(d <= 9); 17592 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 17593 // 17594 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e 17595 // 17596 p2 = r; 17597 m++; 17598 // 17599 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e 17600 // Invariant restored. 17601 17602 // Check if enough digits have been generated. 17603 // 17604 // 10^-m * p2 * 2^e <= delta * 2^e 17605 // p2 * 2^e <= 10^m * delta * 2^e 17606 // p2 <= 10^m * delta 17607 delta *= 10; 17608 dist *= 10; 17609 if (p2 <= delta) 17610 { 17611 break; 17612 } 17613 } 17614 17615 // V = buffer * 10^-m, with M- <= V <= M+. 17616 17617 decimal_exponent -= m; 17618 17619 // 1 ulp in the decimal representation is now 10^-m. 17620 // Since delta and dist are now scaled by 10^m, we need to do the 17621 // same with ulp in order to keep the units in sync. 17622 // 17623 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e 17624 // 17625 const std::uint64_t ten_m = one.f; 17626 grisu2_round(buffer, length, dist, delta, p2, ten_m); 17627 17628 // By construction this algorithm generates the shortest possible decimal 17629 // number (Loitsch, Theorem 6.2) which rounds back to w. 17630 // For an input number of precision p, at least 17631 // 17632 // N = 1 + ceil(p * log_10(2)) 17633 // 17634 // decimal digits are sufficient to identify all binary floating-point 17635 // numbers (Matula, "In-and-Out conversions"). 17636 // This implies that the algorithm does not produce more than N decimal 17637 // digits. 17638 // 17639 // N = 17 for p = 53 (IEEE double precision) 17640 // N = 9 for p = 24 (IEEE single precision) 17641 } 17642 17643 /*! 17644 v = buf * 10^decimal_exponent 17645 len is the length of the buffer (number of decimal digits) 17646 The buffer must be large enough, i.e. >= max_digits10. 17647 */ 17648 JSON_HEDLEY_NON_NULL(1) 17649 inline void grisu2(char* buf, int& len, int& decimal_exponent, 17650 diyfp m_minus, diyfp v, diyfp m_plus) 17651 { 17652 JSON_ASSERT(m_plus.e == m_minus.e); 17653 JSON_ASSERT(m_plus.e == v.e); 17654 17655 // --------(-----------------------+-----------------------)-------- (A) 17656 // m- v m+ 17657 // 17658 // --------------------(-----------+-----------------------)-------- (B) 17659 // m- v m+ 17660 // 17661 // First scale v (and m- and m+) such that the exponent is in the range 17662 // [alpha, gamma]. 17663 17664 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); 17665 17666 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k 17667 17668 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] 17669 const diyfp w = diyfp::mul(v, c_minus_k); 17670 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); 17671 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); 17672 17673 // ----(---+---)---------------(---+---)---------------(---+---)---- 17674 // w- w w+ 17675 // = c*m- = c*v = c*m+ 17676 // 17677 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and 17678 // w+ are now off by a small amount. 17679 // In fact: 17680 // 17681 // w - v * 10^k < 1 ulp 17682 // 17683 // To account for this inaccuracy, add resp. subtract 1 ulp. 17684 // 17685 // --------+---[---------------(---+---)---------------]---+-------- 17686 // w- M- w M+ w+ 17687 // 17688 // Now any number in [M-, M+] (bounds included) will round to w when input, 17689 // regardless of how the input rounding algorithm breaks ties. 17690 // 17691 // And digit_gen generates the shortest possible such number in [M-, M+]. 17692 // Note that this does not mean that Grisu2 always generates the shortest 17693 // possible number in the interval (m-, m+). 17694 const diyfp M_minus(w_minus.f + 1, w_minus.e); 17695 const diyfp M_plus (w_plus.f - 1, w_plus.e ); 17696 17697 decimal_exponent = -cached.k; // = -(-k) = k 17698 17699 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); 17700 } 17701 17702 /*! 17703 v = buf * 10^decimal_exponent 17704 len is the length of the buffer (number of decimal digits) 17705 The buffer must be large enough, i.e. >= max_digits10. 17706 */ 17707 template<typename FloatType> 17708 JSON_HEDLEY_NON_NULL(1) 17709 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) 17710 { 17711 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, 17712 "internal error: not enough precision"); 17713 17714 JSON_ASSERT(std::isfinite(value)); 17715 JSON_ASSERT(value > 0); 17716 17717 // If the neighbors (and boundaries) of 'value' are always computed for double-precision 17718 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting 17719 // decimal representations are not exactly "short". 17720 // 17721 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) 17722 // says "value is converted to a string as if by std::sprintf in the default ("C") locale" 17723 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' 17724 // does. 17725 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the 17726 // representation using the corresponding std::from_chars function recovers value exactly". That 17727 // indicates that single precision floating-point numbers should be recovered using 17728 // 'std::strtof'. 17729 // 17730 // NB: If the neighbors are computed for single-precision numbers, there is a single float 17731 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision 17732 // value is off by 1 ulp. 17733 #if 0 17734 const boundaries w = compute_boundaries(static_cast<double>(value)); 17735 #else 17736 const boundaries w = compute_boundaries(value); 17737 #endif 17738 17739 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); 17740 } 17741 17742 /*! 17743 @brief appends a decimal representation of e to buf 17744 @return a pointer to the element following the exponent. 17745 @pre -1000 < e < 1000 17746 */ 17747 JSON_HEDLEY_NON_NULL(1) 17748 JSON_HEDLEY_RETURNS_NON_NULL 17749 inline char* append_exponent(char* buf, int e) 17750 { 17751 JSON_ASSERT(e > -1000); 17752 JSON_ASSERT(e < 1000); 17753 17754 if (e < 0) 17755 { 17756 e = -e; 17757 *buf++ = '-'; 17758 } 17759 else 17760 { 17761 *buf++ = '+'; 17762 } 17763 17764 auto k = static_cast<std::uint32_t>(e); 17765 if (k < 10) 17766 { 17767 // Always print at least two digits in the exponent. 17768 // This is for compatibility with printf("%g"). 17769 *buf++ = '0'; 17770 *buf++ = static_cast<char>('0' + k); 17771 } 17772 else if (k < 100) 17773 { 17774 *buf++ = static_cast<char>('0' + k / 10); 17775 k %= 10; 17776 *buf++ = static_cast<char>('0' + k); 17777 } 17778 else 17779 { 17780 *buf++ = static_cast<char>('0' + k / 100); 17781 k %= 100; 17782 *buf++ = static_cast<char>('0' + k / 10); 17783 k %= 10; 17784 *buf++ = static_cast<char>('0' + k); 17785 } 17786 17787 return buf; 17788 } 17789 17790 /*! 17791 @brief prettify v = buf * 10^decimal_exponent 17792 17793 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point 17794 notation. Otherwise it will be printed in exponential notation. 17795 17796 @pre min_exp < 0 17797 @pre max_exp > 0 17798 */ 17799 JSON_HEDLEY_NON_NULL(1) 17800 JSON_HEDLEY_RETURNS_NON_NULL 17801 inline char* format_buffer(char* buf, int len, int decimal_exponent, 17802 int min_exp, int max_exp) 17803 { 17804 JSON_ASSERT(min_exp < 0); 17805 JSON_ASSERT(max_exp > 0); 17806 17807 const int k = len; 17808 const int n = len + decimal_exponent; 17809 17810 // v = buf * 10^(n-k) 17811 // k is the length of the buffer (number of decimal digits) 17812 // n is the position of the decimal point relative to the start of the buffer. 17813 17814 if (k <= n && n <= max_exp) 17815 { 17816 // digits[000] 17817 // len <= max_exp + 2 17818 17819 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k)); 17820 // Make it look like a floating-point number (#362, #378) 17821 buf[n + 0] = '.'; 17822 buf[n + 1] = '0'; 17823 return buf + (static_cast<size_t>(n) + 2); 17824 } 17825 17826 if (0 < n && n <= max_exp) 17827 { 17828 // dig.its 17829 // len <= max_digits10 + 1 17830 17831 JSON_ASSERT(k > n); 17832 17833 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n)); 17834 buf[n] = '.'; 17835 return buf + (static_cast<size_t>(k) + 1U); 17836 } 17837 17838 if (min_exp < n && n <= 0) 17839 { 17840 // 0.[000]digits 17841 // len <= 2 + (-min_exp - 1) + max_digits10 17842 17843 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k)); 17844 buf[0] = '0'; 17845 buf[1] = '.'; 17846 std::memset(buf + 2, '0', static_cast<size_t>(-n)); 17847 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k)); 17848 } 17849 17850 if (k == 1) 17851 { 17852 // dE+123 17853 // len <= 1 + 5 17854 17855 buf += 1; 17856 } 17857 else 17858 { 17859 // d.igitsE+123 17860 // len <= max_digits10 + 1 + 5 17861 17862 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1); 17863 buf[1] = '.'; 17864 buf += 1 + static_cast<size_t>(k); 17865 } 17866 17867 *buf++ = 'e'; 17868 return append_exponent(buf, n - 1); 17869 } 17870 17871 } // namespace dtoa_impl 17872 17873 /*! 17874 @brief generates a decimal representation of the floating-point number value in [first, last). 17875 17876 The format of the resulting decimal representation is similar to printf's %g 17877 format. Returns an iterator pointing past-the-end of the decimal representation. 17878 17879 @note The input number must be finite, i.e. NaN's and Inf's are not supported. 17880 @note The buffer must be large enough. 17881 @note The result is NOT null-terminated. 17882 */ 17883 template<typename FloatType> 17884 JSON_HEDLEY_NON_NULL(1, 2) 17885 JSON_HEDLEY_RETURNS_NON_NULL 17886 char* to_chars(char* first, const char* last, FloatType value) 17887 { 17888 static_cast<void>(last); // maybe unused - fix warning 17889 JSON_ASSERT(std::isfinite(value)); 17890 17891 // Use signbit(value) instead of (value < 0) since signbit works for -0. 17892 if (std::signbit(value)) 17893 { 17894 value = -value; 17895 *first++ = '-'; 17896 } 17897 17898 #ifdef __GNUC__ 17899 #pragma GCC diagnostic push 17900 #pragma GCC diagnostic ignored "-Wfloat-equal" 17901 #endif 17902 if (value == 0) // +-0 17903 { 17904 *first++ = '0'; 17905 // Make it look like a floating-point number (#362, #378) 17906 *first++ = '.'; 17907 *first++ = '0'; 17908 return first; 17909 } 17910 #ifdef __GNUC__ 17911 #pragma GCC diagnostic pop 17912 #endif 17913 17914 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10); 17915 17916 // Compute v = buffer * 10^decimal_exponent. 17917 // The decimal digits are stored in the buffer, which needs to be interpreted 17918 // as an unsigned decimal integer. 17919 // len is the length of the buffer, i.e. the number of decimal digits. 17920 int len = 0; 17921 int decimal_exponent = 0; 17922 dtoa_impl::grisu2(first, len, decimal_exponent, value); 17923 17924 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10); 17925 17926 // Format the buffer like printf("%.*g", prec, value) 17927 constexpr int kMinExp = -4; 17928 // Use digits10 here to increase compatibility with version 2. 17929 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10; 17930 17931 JSON_ASSERT(last - first >= kMaxExp + 2); 17932 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10); 17933 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6); 17934 17935 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); 17936 } 17937 17938 } // namespace detail 17939 NLOHMANN_JSON_NAMESPACE_END 17940 17941 // #include <nlohmann/detail/exceptions.hpp> 17942 17943 // #include <nlohmann/detail/macro_scope.hpp> 17944 17945 // #include <nlohmann/detail/meta/cpp_future.hpp> 17946 17947 // #include <nlohmann/detail/output/binary_writer.hpp> 17948 17949 // #include <nlohmann/detail/output/output_adapters.hpp> 17950 17951 // #include <nlohmann/detail/string_concat.hpp> 17952 17953 // #include <nlohmann/detail/value_t.hpp> 17954 17955 17956 NLOHMANN_JSON_NAMESPACE_BEGIN 17957 namespace detail 17958 { 17959 17960 /////////////////// 17961 // serialization // 17962 /////////////////// 17963 17964 /// how to treat decoding errors 17965 enum class error_handler_t 17966 { 17967 strict, ///< throw a type_error exception in case of invalid UTF-8 17968 replace, ///< replace invalid UTF-8 sequences with U+FFFD 17969 ignore ///< ignore invalid UTF-8 sequences 17970 }; 17971 17972 template<typename BasicJsonType> 17973 class serializer 17974 { 17975 using string_t = typename BasicJsonType::string_t; 17976 using number_float_t = typename BasicJsonType::number_float_t; 17977 using number_integer_t = typename BasicJsonType::number_integer_t; 17978 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 17979 using binary_char_t = typename BasicJsonType::binary_t::value_type; 17980 static constexpr std::uint8_t UTF8_ACCEPT = 0; 17981 static constexpr std::uint8_t UTF8_REJECT = 1; 17982 17983 public: 17984 /*! 17985 @param[in] s output stream to serialize to 17986 @param[in] ichar indentation character to use 17987 @param[in] error_handler_ how to react on decoding errors 17988 */ 17989 serializer(output_adapter_t<char> s, const char ichar, 17990 error_handler_t error_handler_ = error_handler_t::strict) 17991 : o(std::move(s)) 17992 , loc(std::localeconv()) 17993 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep))) 17994 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point))) 17995 , indent_char(ichar) 17996 , indent_string(512, indent_char) 17997 , error_handler(error_handler_) 17998 {} 17999 18000 // delete because of pointer members 18001 serializer(const serializer&) = delete; 18002 serializer& operator=(const serializer&) = delete; 18003 serializer(serializer&&) = delete; 18004 serializer& operator=(serializer&&) = delete; 18005 ~serializer() = default; 18006 18007 /*! 18008 @brief internal implementation of the serialization function 18009 18010 This function is called by the public member function dump and organizes 18011 the serialization internally. The indentation level is propagated as 18012 additional parameter. In case of arrays and objects, the function is 18013 called recursively. 18014 18015 - strings and object keys are escaped using `escape_string()` 18016 - integer numbers are converted implicitly via `operator<<` 18017 - floating-point numbers are converted to a string using `"%g"` format 18018 - binary values are serialized as objects containing the subtype and the 18019 byte array 18020 18021 @param[in] val value to serialize 18022 @param[in] pretty_print whether the output shall be pretty-printed 18023 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters 18024 in the output are escaped with `\uXXXX` sequences, and the result consists 18025 of ASCII characters only. 18026 @param[in] indent_step the indent level 18027 @param[in] current_indent the current indent level (only used internally) 18028 */ 18029 void dump(const BasicJsonType& val, 18030 const bool pretty_print, 18031 const bool ensure_ascii, 18032 const unsigned int indent_step, 18033 const unsigned int current_indent = 0) 18034 { 18035 switch (val.m_type) 18036 { 18037 case value_t::object: 18038 { 18039 if (val.m_value.object->empty()) 18040 { 18041 o->write_characters("{}", 2); 18042 return; 18043 } 18044 18045 if (pretty_print) 18046 { 18047 o->write_characters("{\n", 2); 18048 18049 // variable to hold indentation for recursive calls 18050 const auto new_indent = current_indent + indent_step; 18051 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18052 { 18053 indent_string.resize(indent_string.size() * 2, ' '); 18054 } 18055 18056 // first n-1 elements 18057 auto i = val.m_value.object->cbegin(); 18058 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) 18059 { 18060 o->write_characters(indent_string.c_str(), new_indent); 18061 o->write_character('\"'); 18062 dump_escaped(i->first, ensure_ascii); 18063 o->write_characters("\": ", 3); 18064 dump(i->second, true, ensure_ascii, indent_step, new_indent); 18065 o->write_characters(",\n", 2); 18066 } 18067 18068 // last element 18069 JSON_ASSERT(i != val.m_value.object->cend()); 18070 JSON_ASSERT(std::next(i) == val.m_value.object->cend()); 18071 o->write_characters(indent_string.c_str(), new_indent); 18072 o->write_character('\"'); 18073 dump_escaped(i->first, ensure_ascii); 18074 o->write_characters("\": ", 3); 18075 dump(i->second, true, ensure_ascii, indent_step, new_indent); 18076 18077 o->write_character('\n'); 18078 o->write_characters(indent_string.c_str(), current_indent); 18079 o->write_character('}'); 18080 } 18081 else 18082 { 18083 o->write_character('{'); 18084 18085 // first n-1 elements 18086 auto i = val.m_value.object->cbegin(); 18087 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) 18088 { 18089 o->write_character('\"'); 18090 dump_escaped(i->first, ensure_ascii); 18091 o->write_characters("\":", 2); 18092 dump(i->second, false, ensure_ascii, indent_step, current_indent); 18093 o->write_character(','); 18094 } 18095 18096 // last element 18097 JSON_ASSERT(i != val.m_value.object->cend()); 18098 JSON_ASSERT(std::next(i) == val.m_value.object->cend()); 18099 o->write_character('\"'); 18100 dump_escaped(i->first, ensure_ascii); 18101 o->write_characters("\":", 2); 18102 dump(i->second, false, ensure_ascii, indent_step, current_indent); 18103 18104 o->write_character('}'); 18105 } 18106 18107 return; 18108 } 18109 18110 case value_t::array: 18111 { 18112 if (val.m_value.array->empty()) 18113 { 18114 o->write_characters("[]", 2); 18115 return; 18116 } 18117 18118 if (pretty_print) 18119 { 18120 o->write_characters("[\n", 2); 18121 18122 // variable to hold indentation for recursive calls 18123 const auto new_indent = current_indent + indent_step; 18124 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18125 { 18126 indent_string.resize(indent_string.size() * 2, ' '); 18127 } 18128 18129 // first n-1 elements 18130 for (auto i = val.m_value.array->cbegin(); 18131 i != val.m_value.array->cend() - 1; ++i) 18132 { 18133 o->write_characters(indent_string.c_str(), new_indent); 18134 dump(*i, true, ensure_ascii, indent_step, new_indent); 18135 o->write_characters(",\n", 2); 18136 } 18137 18138 // last element 18139 JSON_ASSERT(!val.m_value.array->empty()); 18140 o->write_characters(indent_string.c_str(), new_indent); 18141 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); 18142 18143 o->write_character('\n'); 18144 o->write_characters(indent_string.c_str(), current_indent); 18145 o->write_character(']'); 18146 } 18147 else 18148 { 18149 o->write_character('['); 18150 18151 // first n-1 elements 18152 for (auto i = val.m_value.array->cbegin(); 18153 i != val.m_value.array->cend() - 1; ++i) 18154 { 18155 dump(*i, false, ensure_ascii, indent_step, current_indent); 18156 o->write_character(','); 18157 } 18158 18159 // last element 18160 JSON_ASSERT(!val.m_value.array->empty()); 18161 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); 18162 18163 o->write_character(']'); 18164 } 18165 18166 return; 18167 } 18168 18169 case value_t::string: 18170 { 18171 o->write_character('\"'); 18172 dump_escaped(*val.m_value.string, ensure_ascii); 18173 o->write_character('\"'); 18174 return; 18175 } 18176 18177 case value_t::binary: 18178 { 18179 if (pretty_print) 18180 { 18181 o->write_characters("{\n", 2); 18182 18183 // variable to hold indentation for recursive calls 18184 const auto new_indent = current_indent + indent_step; 18185 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18186 { 18187 indent_string.resize(indent_string.size() * 2, ' '); 18188 } 18189 18190 o->write_characters(indent_string.c_str(), new_indent); 18191 18192 o->write_characters("\"bytes\": [", 10); 18193 18194 if (!val.m_value.binary->empty()) 18195 { 18196 for (auto i = val.m_value.binary->cbegin(); 18197 i != val.m_value.binary->cend() - 1; ++i) 18198 { 18199 dump_integer(*i); 18200 o->write_characters(", ", 2); 18201 } 18202 dump_integer(val.m_value.binary->back()); 18203 } 18204 18205 o->write_characters("],\n", 3); 18206 o->write_characters(indent_string.c_str(), new_indent); 18207 18208 o->write_characters("\"subtype\": ", 11); 18209 if (val.m_value.binary->has_subtype()) 18210 { 18211 dump_integer(val.m_value.binary->subtype()); 18212 } 18213 else 18214 { 18215 o->write_characters("null", 4); 18216 } 18217 o->write_character('\n'); 18218 o->write_characters(indent_string.c_str(), current_indent); 18219 o->write_character('}'); 18220 } 18221 else 18222 { 18223 o->write_characters("{\"bytes\":[", 10); 18224 18225 if (!val.m_value.binary->empty()) 18226 { 18227 for (auto i = val.m_value.binary->cbegin(); 18228 i != val.m_value.binary->cend() - 1; ++i) 18229 { 18230 dump_integer(*i); 18231 o->write_character(','); 18232 } 18233 dump_integer(val.m_value.binary->back()); 18234 } 18235 18236 o->write_characters("],\"subtype\":", 12); 18237 if (val.m_value.binary->has_subtype()) 18238 { 18239 dump_integer(val.m_value.binary->subtype()); 18240 o->write_character('}'); 18241 } 18242 else 18243 { 18244 o->write_characters("null}", 5); 18245 } 18246 } 18247 return; 18248 } 18249 18250 case value_t::boolean: 18251 { 18252 if (val.m_value.boolean) 18253 { 18254 o->write_characters("true", 4); 18255 } 18256 else 18257 { 18258 o->write_characters("false", 5); 18259 } 18260 return; 18261 } 18262 18263 case value_t::number_integer: 18264 { 18265 dump_integer(val.m_value.number_integer); 18266 return; 18267 } 18268 18269 case value_t::number_unsigned: 18270 { 18271 dump_integer(val.m_value.number_unsigned); 18272 return; 18273 } 18274 18275 case value_t::number_float: 18276 { 18277 dump_float(val.m_value.number_float); 18278 return; 18279 } 18280 18281 case value_t::discarded: 18282 { 18283 o->write_characters("<discarded>", 11); 18284 return; 18285 } 18286 18287 case value_t::null: 18288 { 18289 o->write_characters("null", 4); 18290 return; 18291 } 18292 18293 default: // LCOV_EXCL_LINE 18294 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18295 } 18296 } 18297 18298 JSON_PRIVATE_UNLESS_TESTED: 18299 /*! 18300 @brief dump escaped string 18301 18302 Escape a string by replacing certain special characters by a sequence of an 18303 escape character (backslash) and another character and other control 18304 characters by a sequence of "\u" followed by a four-digit hex 18305 representation. The escaped string is written to output stream @a o. 18306 18307 @param[in] s the string to escape 18308 @param[in] ensure_ascii whether to escape non-ASCII characters with 18309 \uXXXX sequences 18310 18311 @complexity Linear in the length of string @a s. 18312 */ 18313 void dump_escaped(const string_t& s, const bool ensure_ascii) 18314 { 18315 std::uint32_t codepoint{}; 18316 std::uint8_t state = UTF8_ACCEPT; 18317 std::size_t bytes = 0; // number of bytes written to string_buffer 18318 18319 // number of bytes written at the point of the last valid byte 18320 std::size_t bytes_after_last_accept = 0; 18321 std::size_t undumped_chars = 0; 18322 18323 for (std::size_t i = 0; i < s.size(); ++i) 18324 { 18325 const auto byte = static_cast<std::uint8_t>(s[i]); 18326 18327 switch (decode(state, codepoint, byte)) 18328 { 18329 case UTF8_ACCEPT: // decode found a new code point 18330 { 18331 switch (codepoint) 18332 { 18333 case 0x08: // backspace 18334 { 18335 string_buffer[bytes++] = '\\'; 18336 string_buffer[bytes++] = 'b'; 18337 break; 18338 } 18339 18340 case 0x09: // horizontal tab 18341 { 18342 string_buffer[bytes++] = '\\'; 18343 string_buffer[bytes++] = 't'; 18344 break; 18345 } 18346 18347 case 0x0A: // newline 18348 { 18349 string_buffer[bytes++] = '\\'; 18350 string_buffer[bytes++] = 'n'; 18351 break; 18352 } 18353 18354 case 0x0C: // formfeed 18355 { 18356 string_buffer[bytes++] = '\\'; 18357 string_buffer[bytes++] = 'f'; 18358 break; 18359 } 18360 18361 case 0x0D: // carriage return 18362 { 18363 string_buffer[bytes++] = '\\'; 18364 string_buffer[bytes++] = 'r'; 18365 break; 18366 } 18367 18368 case 0x22: // quotation mark 18369 { 18370 string_buffer[bytes++] = '\\'; 18371 string_buffer[bytes++] = '\"'; 18372 break; 18373 } 18374 18375 case 0x5C: // reverse solidus 18376 { 18377 string_buffer[bytes++] = '\\'; 18378 string_buffer[bytes++] = '\\'; 18379 break; 18380 } 18381 18382 default: 18383 { 18384 // escape control characters (0x00..0x1F) or, if 18385 // ensure_ascii parameter is used, non-ASCII characters 18386 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) 18387 { 18388 if (codepoint <= 0xFFFF) 18389 { 18390 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18391 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", 18392 static_cast<std::uint16_t>(codepoint))); 18393 bytes += 6; 18394 } 18395 else 18396 { 18397 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18398 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", 18399 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)), 18400 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)))); 18401 bytes += 12; 18402 } 18403 } 18404 else 18405 { 18406 // copy byte to buffer (all previous bytes 18407 // been copied have in default case above) 18408 string_buffer[bytes++] = s[i]; 18409 } 18410 break; 18411 } 18412 } 18413 18414 // write buffer and reset index; there must be 13 bytes 18415 // left, as this is the maximal number of bytes to be 18416 // written ("\uxxxx\uxxxx\0") for one code point 18417 if (string_buffer.size() - bytes < 13) 18418 { 18419 o->write_characters(string_buffer.data(), bytes); 18420 bytes = 0; 18421 } 18422 18423 // remember the byte position of this accept 18424 bytes_after_last_accept = bytes; 18425 undumped_chars = 0; 18426 break; 18427 } 18428 18429 case UTF8_REJECT: // decode found invalid UTF-8 byte 18430 { 18431 switch (error_handler) 18432 { 18433 case error_handler_t::strict: 18434 { 18435 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr)); 18436 } 18437 18438 case error_handler_t::ignore: 18439 case error_handler_t::replace: 18440 { 18441 // in case we saw this character the first time, we 18442 // would like to read it again, because the byte 18443 // may be OK for itself, but just not OK for the 18444 // previous sequence 18445 if (undumped_chars > 0) 18446 { 18447 --i; 18448 } 18449 18450 // reset length buffer to the last accepted index; 18451 // thus removing/ignoring the invalid characters 18452 bytes = bytes_after_last_accept; 18453 18454 if (error_handler == error_handler_t::replace) 18455 { 18456 // add a replacement character 18457 if (ensure_ascii) 18458 { 18459 string_buffer[bytes++] = '\\'; 18460 string_buffer[bytes++] = 'u'; 18461 string_buffer[bytes++] = 'f'; 18462 string_buffer[bytes++] = 'f'; 18463 string_buffer[bytes++] = 'f'; 18464 string_buffer[bytes++] = 'd'; 18465 } 18466 else 18467 { 18468 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF'); 18469 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF'); 18470 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD'); 18471 } 18472 18473 // write buffer and reset index; there must be 13 bytes 18474 // left, as this is the maximal number of bytes to be 18475 // written ("\uxxxx\uxxxx\0") for one code point 18476 if (string_buffer.size() - bytes < 13) 18477 { 18478 o->write_characters(string_buffer.data(), bytes); 18479 bytes = 0; 18480 } 18481 18482 bytes_after_last_accept = bytes; 18483 } 18484 18485 undumped_chars = 0; 18486 18487 // continue processing the string 18488 state = UTF8_ACCEPT; 18489 break; 18490 } 18491 18492 default: // LCOV_EXCL_LINE 18493 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18494 } 18495 break; 18496 } 18497 18498 default: // decode found yet incomplete multi-byte code point 18499 { 18500 if (!ensure_ascii) 18501 { 18502 // code point will not be escaped - copy byte to buffer 18503 string_buffer[bytes++] = s[i]; 18504 } 18505 ++undumped_chars; 18506 break; 18507 } 18508 } 18509 } 18510 18511 // we finished processing the string 18512 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) 18513 { 18514 // write buffer 18515 if (bytes > 0) 18516 { 18517 o->write_characters(string_buffer.data(), bytes); 18518 } 18519 } 18520 else 18521 { 18522 // we finish reading, but do not accept: string was incomplete 18523 switch (error_handler) 18524 { 18525 case error_handler_t::strict: 18526 { 18527 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr)); 18528 } 18529 18530 case error_handler_t::ignore: 18531 { 18532 // write all accepted bytes 18533 o->write_characters(string_buffer.data(), bytes_after_last_accept); 18534 break; 18535 } 18536 18537 case error_handler_t::replace: 18538 { 18539 // write all accepted bytes 18540 o->write_characters(string_buffer.data(), bytes_after_last_accept); 18541 // add a replacement character 18542 if (ensure_ascii) 18543 { 18544 o->write_characters("\\ufffd", 6); 18545 } 18546 else 18547 { 18548 o->write_characters("\xEF\xBF\xBD", 3); 18549 } 18550 break; 18551 } 18552 18553 default: // LCOV_EXCL_LINE 18554 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18555 } 18556 } 18557 } 18558 18559 private: 18560 /*! 18561 @brief count digits 18562 18563 Count the number of decimal (base 10) digits for an input unsigned integer. 18564 18565 @param[in] x unsigned integer number to count its digits 18566 @return number of decimal digits 18567 */ 18568 inline unsigned int count_digits(number_unsigned_t x) noexcept 18569 { 18570 unsigned int n_digits = 1; 18571 for (;;) 18572 { 18573 if (x < 10) 18574 { 18575 return n_digits; 18576 } 18577 if (x < 100) 18578 { 18579 return n_digits + 1; 18580 } 18581 if (x < 1000) 18582 { 18583 return n_digits + 2; 18584 } 18585 if (x < 10000) 18586 { 18587 return n_digits + 3; 18588 } 18589 x = x / 10000u; 18590 n_digits += 4; 18591 } 18592 } 18593 18594 /*! 18595 * @brief convert a byte to a uppercase hex representation 18596 * @param[in] byte byte to represent 18597 * @return representation ("00".."FF") 18598 */ 18599 static std::string hex_bytes(std::uint8_t byte) 18600 { 18601 std::string result = "FF"; 18602 constexpr const char* nibble_to_hex = "0123456789ABCDEF"; 18603 result[0] = nibble_to_hex[byte / 16]; 18604 result[1] = nibble_to_hex[byte % 16]; 18605 return result; 18606 } 18607 18608 // templates to avoid warnings about useless casts 18609 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0> 18610 bool is_negative_number(NumberType x) 18611 { 18612 return x < 0; 18613 } 18614 18615 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 > 18616 bool is_negative_number(NumberType /*unused*/) 18617 { 18618 return false; 18619 } 18620 18621 /*! 18622 @brief dump an integer 18623 18624 Dump a given integer to output stream @a o. Works internally with 18625 @a number_buffer. 18626 18627 @param[in] x integer number (signed or unsigned) to dump 18628 @tparam NumberType either @a number_integer_t or @a number_unsigned_t 18629 */ 18630 template < typename NumberType, detail::enable_if_t < 18631 std::is_integral<NumberType>::value || 18632 std::is_same<NumberType, number_unsigned_t>::value || 18633 std::is_same<NumberType, number_integer_t>::value || 18634 std::is_same<NumberType, binary_char_t>::value, 18635 int > = 0 > 18636 void dump_integer(NumberType x) 18637 { 18638 static constexpr std::array<std::array<char, 2>, 100> digits_to_99 18639 { 18640 { 18641 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, 18642 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, 18643 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, 18644 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, 18645 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, 18646 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, 18647 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, 18648 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, 18649 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, 18650 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, 18651 } 18652 }; 18653 18654 // special case for "0" 18655 if (x == 0) 18656 { 18657 o->write_character('0'); 18658 return; 18659 } 18660 18661 // use a pointer to fill the buffer 18662 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18663 18664 number_unsigned_t abs_value; 18665 18666 unsigned int n_chars{}; 18667 18668 if (is_negative_number(x)) 18669 { 18670 *buffer_ptr = '-'; 18671 abs_value = remove_sign(static_cast<number_integer_t>(x)); 18672 18673 // account one more byte for the minus sign 18674 n_chars = 1 + count_digits(abs_value); 18675 } 18676 else 18677 { 18678 abs_value = static_cast<number_unsigned_t>(x); 18679 n_chars = count_digits(abs_value); 18680 } 18681 18682 // spare 1 byte for '\0' 18683 JSON_ASSERT(n_chars < number_buffer.size() - 1); 18684 18685 // jump to the end to generate the string from backward, 18686 // so we later avoid reversing the result 18687 buffer_ptr += n_chars; 18688 18689 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu 18690 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg 18691 while (abs_value >= 100) 18692 { 18693 const auto digits_index = static_cast<unsigned>((abs_value % 100)); 18694 abs_value /= 100; 18695 *(--buffer_ptr) = digits_to_99[digits_index][1]; 18696 *(--buffer_ptr) = digits_to_99[digits_index][0]; 18697 } 18698 18699 if (abs_value >= 10) 18700 { 18701 const auto digits_index = static_cast<unsigned>(abs_value); 18702 *(--buffer_ptr) = digits_to_99[digits_index][1]; 18703 *(--buffer_ptr) = digits_to_99[digits_index][0]; 18704 } 18705 else 18706 { 18707 *(--buffer_ptr) = static_cast<char>('0' + abs_value); 18708 } 18709 18710 o->write_characters(number_buffer.data(), n_chars); 18711 } 18712 18713 /*! 18714 @brief dump a floating-point number 18715 18716 Dump a given floating-point number to output stream @a o. Works internally 18717 with @a number_buffer. 18718 18719 @param[in] x floating-point number to dump 18720 */ 18721 void dump_float(number_float_t x) 18722 { 18723 // NaN / inf 18724 if (!std::isfinite(x)) 18725 { 18726 o->write_characters("null", 4); 18727 return; 18728 } 18729 18730 // If number_float_t is an IEEE-754 single or double precision number, 18731 // use the Grisu2 algorithm to produce short numbers which are 18732 // guaranteed to round-trip, using strtof and strtod, resp. 18733 // 18734 // NB: The test below works if <long double> == <double>. 18735 static constexpr bool is_ieee_single_or_double 18736 = (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) || 18737 (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); 18738 18739 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>()); 18740 } 18741 18742 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) 18743 { 18744 auto* begin = number_buffer.data(); 18745 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); 18746 18747 o->write_characters(begin, static_cast<size_t>(end - begin)); 18748 } 18749 18750 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) 18751 { 18752 // get number of digits for a float -> text -> float round-trip 18753 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; 18754 18755 // the actual conversion 18756 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18757 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); 18758 18759 // negative value indicates an error 18760 JSON_ASSERT(len > 0); 18761 // check if buffer was large enough 18762 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size()); 18763 18764 // erase thousands separator 18765 if (thousands_sep != '\0') 18766 { 18767 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 18768 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); 18769 std::fill(end, number_buffer.end(), '\0'); 18770 JSON_ASSERT((end - number_buffer.begin()) <= len); 18771 len = (end - number_buffer.begin()); 18772 } 18773 18774 // convert decimal point to '.' 18775 if (decimal_point != '\0' && decimal_point != '.') 18776 { 18777 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 18778 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); 18779 if (dec_pos != number_buffer.end()) 18780 { 18781 *dec_pos = '.'; 18782 } 18783 } 18784 18785 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len)); 18786 18787 // determine if we need to append ".0" 18788 const bool value_is_int_like = 18789 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, 18790 [](char c) 18791 { 18792 return c == '.' || c == 'e'; 18793 }); 18794 18795 if (value_is_int_like) 18796 { 18797 o->write_characters(".0", 2); 18798 } 18799 } 18800 18801 /*! 18802 @brief check whether a string is UTF-8 encoded 18803 18804 The function checks each byte of a string whether it is UTF-8 encoded. The 18805 result of the check is stored in the @a state parameter. The function must 18806 be called initially with state 0 (accept). State 1 means the string must 18807 be rejected, because the current byte is not allowed. If the string is 18808 completely processed, but the state is non-zero, the string ended 18809 prematurely; that is, the last byte indicated more bytes should have 18810 followed. 18811 18812 @param[in,out] state the state of the decoding 18813 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) 18814 @param[in] byte next byte to decode 18815 @return new state 18816 18817 @note The function has been edited: a std::array is used. 18818 18819 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> 18820 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 18821 */ 18822 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept 18823 { 18824 static const std::array<std::uint8_t, 400> utf8d = 18825 { 18826 { 18827 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, 0, // 00..1F 18828 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, 0, // 20..3F 18829 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, 0, // 40..5F 18830 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, 0, // 60..7F 18831 1, 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 18832 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, 7, // A0..BF 18833 8, 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 18834 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF 18835 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF 18836 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 18837 1, 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 18838 1, 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 18839 1, 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 18840 1, 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 18841 } 18842 }; 18843 18844 JSON_ASSERT(byte < utf8d.size()); 18845 const std::uint8_t type = utf8d[byte]; 18846 18847 codep = (state != UTF8_ACCEPT) 18848 ? (byte & 0x3fu) | (codep << 6u) 18849 : (0xFFu >> type) & (byte); 18850 18851 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type); 18852 JSON_ASSERT(index < utf8d.size()); 18853 state = utf8d[index]; 18854 return state; 18855 } 18856 18857 /* 18858 * Overload to make the compiler happy while it is instantiating 18859 * dump_integer for number_unsigned_t. 18860 * Must never be called. 18861 */ 18862 number_unsigned_t remove_sign(number_unsigned_t x) 18863 { 18864 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18865 return x; // LCOV_EXCL_LINE 18866 } 18867 18868 /* 18869 * Helper function for dump_integer 18870 * 18871 * This function takes a negative signed integer and returns its absolute 18872 * value as unsigned integer. The plus/minus shuffling is necessary as we can 18873 * not directly remove the sign of an arbitrary signed integer as the 18874 * absolute values of INT_MIN and INT_MAX are usually not the same. See 18875 * #1708 for details. 18876 */ 18877 inline number_unsigned_t remove_sign(number_integer_t x) noexcept 18878 { 18879 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression) 18880 return static_cast<number_unsigned_t>(-(x + 1)) + 1; 18881 } 18882 18883 private: 18884 /// the output of the serializer 18885 output_adapter_t<char> o = nullptr; 18886 18887 /// a (hopefully) large enough character buffer 18888 std::array<char, 64> number_buffer{{}}; 18889 18890 /// the locale 18891 const std::lconv* loc = nullptr; 18892 /// the locale's thousand separator character 18893 const char thousands_sep = '\0'; 18894 /// the locale's decimal point character 18895 const char decimal_point = '\0'; 18896 18897 /// string buffer 18898 std::array<char, 512> string_buffer{{}}; 18899 18900 /// the indentation character 18901 const char indent_char; 18902 /// the indentation string 18903 string_t indent_string; 18904 18905 /// error_handler how to react on decoding errors 18906 const error_handler_t error_handler; 18907 }; 18908 18909 } // namespace detail 18910 NLOHMANN_JSON_NAMESPACE_END 18911 18912 // #include <nlohmann/detail/value_t.hpp> 18913 18914 // #include <nlohmann/json_fwd.hpp> 18915 18916 // #include <nlohmann/ordered_map.hpp> 18917 // __ _____ _____ _____ 18918 // __| | __| | | | JSON for Modern C++ 18919 // | | |__ | | | | | | version 3.11.2 18920 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 18921 // 18922 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 18923 // SPDX-License-Identifier: MIT 18924 18925 18926 18927 #include <functional> // equal_to, less 18928 #include <initializer_list> // initializer_list 18929 #include <iterator> // input_iterator_tag, iterator_traits 18930 #include <memory> // allocator 18931 #include <stdexcept> // for out_of_range 18932 #include <type_traits> // enable_if, is_convertible 18933 #include <utility> // pair 18934 #include <vector> // vector 18935 18936 // #include <nlohmann/detail/macro_scope.hpp> 18937 18938 // #include <nlohmann/detail/meta/type_traits.hpp> 18939 18940 18941 NLOHMANN_JSON_NAMESPACE_BEGIN 18942 18943 /// ordered_map: a minimal map-like container that preserves insertion order 18944 /// for use within nlohmann::basic_json<ordered_map> 18945 template <class Key, class T, class IgnoredLess = std::less<Key>, 18946 class Allocator = std::allocator<std::pair<const Key, T>>> 18947 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> 18948 { 18949 using key_type = Key; 18950 using mapped_type = T; 18951 using Container = std::vector<std::pair<const Key, T>, Allocator>; 18952 using iterator = typename Container::iterator; 18953 using const_iterator = typename Container::const_iterator; 18954 using size_type = typename Container::size_type; 18955 using value_type = typename Container::value_type; 18956 #ifdef JSON_HAS_CPP_14 18957 using key_compare = std::equal_to<>; 18958 #else 18959 using key_compare = std::equal_to<Key>; 18960 #endif 18961 18962 // Explicit constructors instead of `using Container::Container` 18963 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) 18964 ordered_map() noexcept(noexcept(Container())) : Container{} {} 18965 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {} 18966 template <class It> 18967 ordered_map(It first, It last, const Allocator& alloc = Allocator()) 18968 : Container{first, last, alloc} {} 18969 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) 18970 : Container{init, alloc} {} 18971 18972 std::pair<iterator, bool> emplace(const key_type& key, T&& t) 18973 { 18974 for (auto it = this->begin(); it != this->end(); ++it) 18975 { 18976 if (m_compare(it->first, key)) 18977 { 18978 return {it, false}; 18979 } 18980 } 18981 Container::emplace_back(key, std::forward<T>(t)); 18982 return {std::prev(this->end()), true}; 18983 } 18984 18985 template<class KeyType, detail::enable_if_t< 18986 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 18987 std::pair<iterator, bool> emplace(KeyType && key, T && t) 18988 { 18989 for (auto it = this->begin(); it != this->end(); ++it) 18990 { 18991 if (m_compare(it->first, key)) 18992 { 18993 return {it, false}; 18994 } 18995 } 18996 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t)); 18997 return {std::prev(this->end()), true}; 18998 } 18999 19000 T& operator[](const key_type& key) 19001 { 19002 return emplace(key, T{}).first->second; 19003 } 19004 19005 template<class KeyType, detail::enable_if_t< 19006 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19007 T & operator[](KeyType && key) 19008 { 19009 return emplace(std::forward<KeyType>(key), T{}).first->second; 19010 } 19011 19012 const T& operator[](const key_type& key) const 19013 { 19014 return at(key); 19015 } 19016 19017 template<class KeyType, detail::enable_if_t< 19018 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19019 const T & operator[](KeyType && key) const 19020 { 19021 return at(std::forward<KeyType>(key)); 19022 } 19023 19024 T& at(const key_type& key) 19025 { 19026 for (auto it = this->begin(); it != this->end(); ++it) 19027 { 19028 if (m_compare(it->first, key)) 19029 { 19030 return it->second; 19031 } 19032 } 19033 19034 JSON_THROW(std::out_of_range("key not found")); 19035 } 19036 19037 template<class KeyType, detail::enable_if_t< 19038 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19039 T & at(KeyType && key) 19040 { 19041 for (auto it = this->begin(); it != this->end(); ++it) 19042 { 19043 if (m_compare(it->first, key)) 19044 { 19045 return it->second; 19046 } 19047 } 19048 19049 JSON_THROW(std::out_of_range("key not found")); 19050 } 19051 19052 const T& at(const key_type& key) const 19053 { 19054 for (auto it = this->begin(); it != this->end(); ++it) 19055 { 19056 if (m_compare(it->first, key)) 19057 { 19058 return it->second; 19059 } 19060 } 19061 19062 JSON_THROW(std::out_of_range("key not found")); 19063 } 19064 19065 template<class KeyType, detail::enable_if_t< 19066 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19067 const T & at(KeyType && key) const 19068 { 19069 for (auto it = this->begin(); it != this->end(); ++it) 19070 { 19071 if (m_compare(it->first, key)) 19072 { 19073 return it->second; 19074 } 19075 } 19076 19077 JSON_THROW(std::out_of_range("key not found")); 19078 } 19079 19080 size_type erase(const key_type& key) 19081 { 19082 for (auto it = this->begin(); it != this->end(); ++it) 19083 { 19084 if (m_compare(it->first, key)) 19085 { 19086 // Since we cannot move const Keys, re-construct them in place 19087 for (auto next = it; ++next != this->end(); ++it) 19088 { 19089 it->~value_type(); // Destroy but keep allocation 19090 new (&*it) value_type{std::move(*next)}; 19091 } 19092 Container::pop_back(); 19093 return 1; 19094 } 19095 } 19096 return 0; 19097 } 19098 19099 template<class KeyType, detail::enable_if_t< 19100 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19101 size_type erase(KeyType && key) 19102 { 19103 for (auto it = this->begin(); it != this->end(); ++it) 19104 { 19105 if (m_compare(it->first, key)) 19106 { 19107 // Since we cannot move const Keys, re-construct them in place 19108 for (auto next = it; ++next != this->end(); ++it) 19109 { 19110 it->~value_type(); // Destroy but keep allocation 19111 new (&*it) value_type{std::move(*next)}; 19112 } 19113 Container::pop_back(); 19114 return 1; 19115 } 19116 } 19117 return 0; 19118 } 19119 19120 iterator erase(iterator pos) 19121 { 19122 return erase(pos, std::next(pos)); 19123 } 19124 19125 iterator erase(iterator first, iterator last) 19126 { 19127 if (first == last) 19128 { 19129 return first; 19130 } 19131 19132 const auto elements_affected = std::distance(first, last); 19133 const auto offset = std::distance(Container::begin(), first); 19134 19135 // This is the start situation. We need to delete elements_affected 19136 // elements (3 in this example: e, f, g), and need to return an 19137 // iterator past the last deleted element (h in this example). 19138 // Note that offset is the distance from the start of the vector 19139 // to first. We will need this later. 19140 19141 // [ a, b, c, d, e, f, g, h, i, j ] 19142 // ^ ^ 19143 // first last 19144 19145 // Since we cannot move const Keys, we re-construct them in place. 19146 // We start at first and re-construct (viz. copy) the elements from 19147 // the back of the vector. Example for first iteration: 19148 19149 // ,--------. 19150 // v | destroy e and re-construct with h 19151 // [ a, b, c, d, e, f, g, h, i, j ] 19152 // ^ ^ 19153 // it it + elements_affected 19154 19155 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) 19156 { 19157 it->~value_type(); // destroy but keep allocation 19158 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it 19159 } 19160 19161 // [ a, b, c, d, h, i, j, h, i, j ] 19162 // ^ ^ 19163 // first last 19164 19165 // remove the unneeded elements at the end of the vector 19166 Container::resize(this->size() - static_cast<size_type>(elements_affected)); 19167 19168 // [ a, b, c, d, h, i, j ] 19169 // ^ ^ 19170 // first last 19171 19172 // first is now pointing past the last deleted element, but we cannot 19173 // use this iterator, because it may have been invalidated by the 19174 // resize call. Instead, we can return begin() + offset. 19175 return Container::begin() + offset; 19176 } 19177 19178 size_type count(const key_type& key) const 19179 { 19180 for (auto it = this->begin(); it != this->end(); ++it) 19181 { 19182 if (m_compare(it->first, key)) 19183 { 19184 return 1; 19185 } 19186 } 19187 return 0; 19188 } 19189 19190 template<class KeyType, detail::enable_if_t< 19191 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19192 size_type count(KeyType && key) const 19193 { 19194 for (auto it = this->begin(); it != this->end(); ++it) 19195 { 19196 if (m_compare(it->first, key)) 19197 { 19198 return 1; 19199 } 19200 } 19201 return 0; 19202 } 19203 19204 iterator find(const key_type& key) 19205 { 19206 for (auto it = this->begin(); it != this->end(); ++it) 19207 { 19208 if (m_compare(it->first, key)) 19209 { 19210 return it; 19211 } 19212 } 19213 return Container::end(); 19214 } 19215 19216 template<class KeyType, detail::enable_if_t< 19217 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19218 iterator find(KeyType && key) 19219 { 19220 for (auto it = this->begin(); it != this->end(); ++it) 19221 { 19222 if (m_compare(it->first, key)) 19223 { 19224 return it; 19225 } 19226 } 19227 return Container::end(); 19228 } 19229 19230 const_iterator find(const key_type& key) const 19231 { 19232 for (auto it = this->begin(); it != this->end(); ++it) 19233 { 19234 if (m_compare(it->first, key)) 19235 { 19236 return it; 19237 } 19238 } 19239 return Container::end(); 19240 } 19241 19242 std::pair<iterator, bool> insert( value_type&& value ) 19243 { 19244 return emplace(value.first, std::move(value.second)); 19245 } 19246 19247 std::pair<iterator, bool> insert( const value_type& value ) 19248 { 19249 for (auto it = this->begin(); it != this->end(); ++it) 19250 { 19251 if (m_compare(it->first, value.first)) 19252 { 19253 return {it, false}; 19254 } 19255 } 19256 Container::push_back(value); 19257 return {--this->end(), true}; 19258 } 19259 19260 template<typename InputIt> 19261 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, 19262 std::input_iterator_tag>::value>::type; 19263 19264 template<typename InputIt, typename = require_input_iter<InputIt>> 19265 void insert(InputIt first, InputIt last) 19266 { 19267 for (auto it = first; it != last; ++it) 19268 { 19269 insert(*it); 19270 } 19271 } 19272 19273 private: 19274 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare(); 19275 }; 19276 19277 NLOHMANN_JSON_NAMESPACE_END 19278 19279 19280 #if defined(JSON_HAS_CPP_17) 19281 #include <any> 19282 #include <string_view> 19283 #endif 19284 19285 /*! 19286 @brief namespace for Niels Lohmann 19287 @see https://github.com/nlohmann 19288 @since version 1.0.0 19289 */ 19290 NLOHMANN_JSON_NAMESPACE_BEGIN 19291 19292 /*! 19293 @brief a class to store JSON values 19294 19295 @internal 19296 @invariant The member variables @a m_value and @a m_type have the following 19297 relationship: 19298 - If `m_type == value_t::object`, then `m_value.object != nullptr`. 19299 - If `m_type == value_t::array`, then `m_value.array != nullptr`. 19300 - If `m_type == value_t::string`, then `m_value.string != nullptr`. 19301 The invariants are checked by member function assert_invariant(). 19302 19303 @note ObjectType trick from https://stackoverflow.com/a/9860911 19304 @endinternal 19305 19306 @since version 1.0.0 19307 19308 @nosubgrouping 19309 */ 19310 NLOHMANN_BASIC_JSON_TPL_DECLARATION 19311 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 19312 : public ::nlohmann::detail::json_base_class<CustomBaseClass> 19313 { 19314 private: 19315 template<detail::value_t> friend struct detail::external_constructor; 19316 19317 template<typename> 19318 friend class ::nlohmann::json_pointer; 19319 // can be restored when json_pointer backwards compatibility is removed 19320 // friend ::nlohmann::json_pointer<StringType>; 19321 19322 template<typename BasicJsonType, typename InputType> 19323 friend class ::nlohmann::detail::parser; 19324 friend ::nlohmann::detail::serializer<basic_json>; 19325 template<typename BasicJsonType> 19326 friend class ::nlohmann::detail::iter_impl; 19327 template<typename BasicJsonType, typename CharType> 19328 friend class ::nlohmann::detail::binary_writer; 19329 template<typename BasicJsonType, typename InputType, typename SAX> 19330 friend class ::nlohmann::detail::binary_reader; 19331 template<typename BasicJsonType> 19332 friend class ::nlohmann::detail::json_sax_dom_parser; 19333 template<typename BasicJsonType> 19334 friend class ::nlohmann::detail::json_sax_dom_callback_parser; 19335 friend class ::nlohmann::detail::exception; 19336 19337 /// workaround type for MSVC 19338 using basic_json_t = NLOHMANN_BASIC_JSON_TPL; 19339 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>; 19340 19341 JSON_PRIVATE_UNLESS_TESTED: 19342 // convenience aliases for types residing in namespace detail; 19343 using lexer = ::nlohmann::detail::lexer_base<basic_json>; 19344 19345 template<typename InputAdapterType> 19346 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser( 19347 InputAdapterType adapter, 19348 detail::parser_callback_t<basic_json>cb = nullptr, 19349 const bool allow_exceptions = true, 19350 const bool ignore_comments = false 19351 ) 19352 { 19353 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter), 19354 std::move(cb), allow_exceptions, ignore_comments); 19355 } 19356 19357 private: 19358 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; 19359 template<typename BasicJsonType> 19360 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; 19361 template<typename BasicJsonType> 19362 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; 19363 template<typename Iterator> 19364 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; 19365 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; 19366 19367 template<typename CharType> 19368 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; 19369 19370 template<typename InputType> 19371 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>; 19372 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>; 19373 19374 JSON_PRIVATE_UNLESS_TESTED: 19375 using serializer = ::nlohmann::detail::serializer<basic_json>; 19376 19377 public: 19378 using value_t = detail::value_t; 19379 /// JSON Pointer, see @ref nlohmann::json_pointer 19380 using json_pointer = ::nlohmann::json_pointer<StringType>; 19381 template<typename T, typename SFINAE> 19382 using json_serializer = JSONSerializer<T, SFINAE>; 19383 /// how to treat decoding errors 19384 using error_handler_t = detail::error_handler_t; 19385 /// how to treat CBOR tags 19386 using cbor_tag_handler_t = detail::cbor_tag_handler_t; 19387 /// helper type for initializer lists of basic_json values 19388 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; 19389 19390 using input_format_t = detail::input_format_t; 19391 /// SAX interface type, see @ref nlohmann::json_sax 19392 using json_sax_t = json_sax<basic_json>; 19393 19394 //////////////// 19395 // exceptions // 19396 //////////////// 19397 19398 /// @name exceptions 19399 /// Classes to implement user-defined exceptions. 19400 /// @{ 19401 19402 using exception = detail::exception; 19403 using parse_error = detail::parse_error; 19404 using invalid_iterator = detail::invalid_iterator; 19405 using type_error = detail::type_error; 19406 using out_of_range = detail::out_of_range; 19407 using other_error = detail::other_error; 19408 19409 /// @} 19410 19411 19412 ///////////////////// 19413 // container types // 19414 ///////////////////// 19415 19416 /// @name container types 19417 /// The canonic container types to use @ref basic_json like any other STL 19418 /// container. 19419 /// @{ 19420 19421 /// the type of elements in a basic_json container 19422 using value_type = basic_json; 19423 19424 /// the type of an element reference 19425 using reference = value_type&; 19426 /// the type of an element const reference 19427 using const_reference = const value_type&; 19428 19429 /// a type to represent differences between iterators 19430 using difference_type = std::ptrdiff_t; 19431 /// a type to represent container sizes 19432 using size_type = std::size_t; 19433 19434 /// the allocator type 19435 using allocator_type = AllocatorType<basic_json>; 19436 19437 /// the type of an element pointer 19438 using pointer = typename std::allocator_traits<allocator_type>::pointer; 19439 /// the type of an element const pointer 19440 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; 19441 19442 /// an iterator for a basic_json container 19443 using iterator = iter_impl<basic_json>; 19444 /// a const iterator for a basic_json container 19445 using const_iterator = iter_impl<const basic_json>; 19446 /// a reverse iterator for a basic_json container 19447 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; 19448 /// a const reverse iterator for a basic_json container 19449 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; 19450 19451 /// @} 19452 19453 19454 /// @brief returns the allocator associated with the container 19455 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ 19456 static allocator_type get_allocator() 19457 { 19458 return allocator_type(); 19459 } 19460 19461 /// @brief returns version information on the library 19462 /// @sa https://json.nlohmann.me/api/basic_json/meta/ 19463 JSON_HEDLEY_WARN_UNUSED_RESULT 19464 static basic_json meta() 19465 { 19466 basic_json result; 19467 19468 result["copyright"] = "(C) 2013-2022 Niels Lohmann"; 19469 result["name"] = "JSON for Modern C++"; 19470 result["url"] = "https://github.com/nlohmann/json"; 19471 result["version"]["string"] = 19472 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.', 19473 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.', 19474 std::to_string(NLOHMANN_JSON_VERSION_PATCH)); 19475 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; 19476 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; 19477 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; 19478 19479 #ifdef _WIN32 19480 result["platform"] = "win32"; 19481 #elif defined __linux__ 19482 result["platform"] = "linux"; 19483 #elif defined __APPLE__ 19484 result["platform"] = "apple"; 19485 #elif defined __unix__ 19486 result["platform"] = "unix"; 19487 #else 19488 result["platform"] = "unknown"; 19489 #endif 19490 19491 #if defined(__ICC) || defined(__INTEL_COMPILER) 19492 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; 19493 #elif defined(__clang__) 19494 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; 19495 #elif defined(__GNUC__) || defined(__GNUG__) 19496 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat( 19497 std::to_string(__GNUC__), '.', 19498 std::to_string(__GNUC_MINOR__), '.', 19499 std::to_string(__GNUC_PATCHLEVEL__)) 19500 } 19501 }; 19502 #elif defined(__HP_cc) || defined(__HP_aCC) 19503 result["compiler"] = "hp" 19504 #elif defined(__IBMCPP__) 19505 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; 19506 #elif defined(_MSC_VER) 19507 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; 19508 #elif defined(__PGI) 19509 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; 19510 #elif defined(__SUNPRO_CC) 19511 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; 19512 #else 19513 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; 19514 #endif 19515 19516 19517 #if defined(_MSVC_LANG) 19518 result["compiler"]["c++"] = std::to_string(_MSVC_LANG); 19519 #elif defined(__cplusplus) 19520 result["compiler"]["c++"] = std::to_string(__cplusplus); 19521 #else 19522 result["compiler"]["c++"] = "unknown"; 19523 #endif 19524 return result; 19525 } 19526 19527 19528 /////////////////////////// 19529 // JSON value data types // 19530 /////////////////////////// 19531 19532 /// @name JSON value data types 19533 /// The data types to store a JSON value. These types are derived from 19534 /// the template arguments passed to class @ref basic_json. 19535 /// @{ 19536 19537 /// @brief default object key comparator type 19538 /// The actual object key comparator type (@ref object_comparator_t) may be 19539 /// different. 19540 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/ 19541 #if defined(JSON_HAS_CPP_14) 19542 // use of transparent comparator avoids unnecessary repeated construction of temporaries 19543 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType) 19544 using default_object_comparator_t = std::less<>; 19545 #else 19546 using default_object_comparator_t = std::less<StringType>; 19547 #endif 19548 19549 /// @brief a type for an object 19550 /// @sa https://json.nlohmann.me/api/basic_json/object_t/ 19551 using object_t = ObjectType<StringType, 19552 basic_json, 19553 default_object_comparator_t, 19554 AllocatorType<std::pair<const StringType, 19555 basic_json>>>; 19556 19557 /// @brief a type for an array 19558 /// @sa https://json.nlohmann.me/api/basic_json/array_t/ 19559 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; 19560 19561 /// @brief a type for a string 19562 /// @sa https://json.nlohmann.me/api/basic_json/string_t/ 19563 using string_t = StringType; 19564 19565 /// @brief a type for a boolean 19566 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ 19567 using boolean_t = BooleanType; 19568 19569 /// @brief a type for a number (integer) 19570 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ 19571 using number_integer_t = NumberIntegerType; 19572 19573 /// @brief a type for a number (unsigned) 19574 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ 19575 using number_unsigned_t = NumberUnsignedType; 19576 19577 /// @brief a type for a number (floating-point) 19578 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ 19579 using number_float_t = NumberFloatType; 19580 19581 /// @brief a type for a packed binary type 19582 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/ 19583 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>; 19584 19585 /// @brief object key comparator type 19586 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ 19587 using object_comparator_t = detail::actual_object_comparator_t<basic_json>; 19588 19589 /// @} 19590 19591 private: 19592 19593 /// helper for exception-safe object creation 19594 template<typename T, typename... Args> 19595 JSON_HEDLEY_RETURNS_NON_NULL 19596 static T* create(Args&& ... args) 19597 { 19598 AllocatorType<T> alloc; 19599 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>; 19600 19601 auto deleter = [&](T * obj) 19602 { 19603 AllocatorTraits::deallocate(alloc, obj, 1); 19604 }; 19605 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter); 19606 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...); 19607 JSON_ASSERT(obj != nullptr); 19608 return obj.release(); 19609 } 19610 19611 //////////////////////// 19612 // JSON value storage // 19613 //////////////////////// 19614 19615 JSON_PRIVATE_UNLESS_TESTED: 19616 /*! 19617 @brief a JSON value 19618 19619 The actual storage for a JSON value of the @ref basic_json class. This 19620 union combines the different storage types for the JSON value types 19621 defined in @ref value_t. 19622 19623 JSON type | value_t type | used type 19624 --------- | --------------- | ------------------------ 19625 object | object | pointer to @ref object_t 19626 array | array | pointer to @ref array_t 19627 string | string | pointer to @ref string_t 19628 boolean | boolean | @ref boolean_t 19629 number | number_integer | @ref number_integer_t 19630 number | number_unsigned | @ref number_unsigned_t 19631 number | number_float | @ref number_float_t 19632 binary | binary | pointer to @ref binary_t 19633 null | null | *no value is stored* 19634 19635 @note Variable-length types (objects, arrays, and strings) are stored as 19636 pointers. The size of the union should not exceed 64 bits if the default 19637 value types are used. 19638 19639 @since version 1.0.0 19640 */ 19641 union json_value 19642 { 19643 /// object (stored with pointer to save storage) 19644 object_t* object; 19645 /// array (stored with pointer to save storage) 19646 array_t* array; 19647 /// string (stored with pointer to save storage) 19648 string_t* string; 19649 /// binary (stored with pointer to save storage) 19650 binary_t* binary; 19651 /// boolean 19652 boolean_t boolean; 19653 /// number (integer) 19654 number_integer_t number_integer; 19655 /// number (unsigned integer) 19656 number_unsigned_t number_unsigned; 19657 /// number (floating-point) 19658 number_float_t number_float; 19659 19660 /// default constructor (for null values) 19661 json_value() = default; 19662 /// constructor for booleans 19663 json_value(boolean_t v) noexcept : boolean(v) {} 19664 /// constructor for numbers (integer) 19665 json_value(number_integer_t v) noexcept : number_integer(v) {} 19666 /// constructor for numbers (unsigned) 19667 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} 19668 /// constructor for numbers (floating-point) 19669 json_value(number_float_t v) noexcept : number_float(v) {} 19670 /// constructor for empty values of a given type 19671 json_value(value_t t) 19672 { 19673 switch (t) 19674 { 19675 case value_t::object: 19676 { 19677 object = create<object_t>(); 19678 break; 19679 } 19680 19681 case value_t::array: 19682 { 19683 array = create<array_t>(); 19684 break; 19685 } 19686 19687 case value_t::string: 19688 { 19689 string = create<string_t>(""); 19690 break; 19691 } 19692 19693 case value_t::binary: 19694 { 19695 binary = create<binary_t>(); 19696 break; 19697 } 19698 19699 case value_t::boolean: 19700 { 19701 boolean = static_cast<boolean_t>(false); 19702 break; 19703 } 19704 19705 case value_t::number_integer: 19706 { 19707 number_integer = static_cast<number_integer_t>(0); 19708 break; 19709 } 19710 19711 case value_t::number_unsigned: 19712 { 19713 number_unsigned = static_cast<number_unsigned_t>(0); 19714 break; 19715 } 19716 19717 case value_t::number_float: 19718 { 19719 number_float = static_cast<number_float_t>(0.0); 19720 break; 19721 } 19722 19723 case value_t::null: 19724 { 19725 object = nullptr; // silence warning, see #821 19726 break; 19727 } 19728 19729 case value_t::discarded: 19730 default: 19731 { 19732 object = nullptr; // silence warning, see #821 19733 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) 19734 { 19735 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE 19736 } 19737 break; 19738 } 19739 } 19740 } 19741 19742 /// constructor for strings 19743 json_value(const string_t& value) : string(create<string_t>(value)) {} 19744 19745 /// constructor for rvalue strings 19746 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {} 19747 19748 /// constructor for objects 19749 json_value(const object_t& value) : object(create<object_t>(value)) {} 19750 19751 /// constructor for rvalue objects 19752 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {} 19753 19754 /// constructor for arrays 19755 json_value(const array_t& value) : array(create<array_t>(value)) {} 19756 19757 /// constructor for rvalue arrays 19758 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {} 19759 19760 /// constructor for binary arrays 19761 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {} 19762 19763 /// constructor for rvalue binary arrays 19764 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {} 19765 19766 /// constructor for binary arrays (internal type) 19767 json_value(const binary_t& value) : binary(create<binary_t>(value)) {} 19768 19769 /// constructor for rvalue binary arrays (internal type) 19770 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {} 19771 19772 void destroy(value_t t) 19773 { 19774 if (t == value_t::array || t == value_t::object) 19775 { 19776 // flatten the current json_value to a heap-allocated stack 19777 std::vector<basic_json> stack; 19778 19779 // move the top-level items to stack 19780 if (t == value_t::array) 19781 { 19782 stack.reserve(array->size()); 19783 std::move(array->begin(), array->end(), std::back_inserter(stack)); 19784 } 19785 else 19786 { 19787 stack.reserve(object->size()); 19788 for (auto&& it : *object) 19789 { 19790 stack.push_back(std::move(it.second)); 19791 } 19792 } 19793 19794 while (!stack.empty()) 19795 { 19796 // move the last item to local variable to be processed 19797 basic_json current_item(std::move(stack.back())); 19798 stack.pop_back(); 19799 19800 // if current_item is array/object, move 19801 // its children to the stack to be processed later 19802 if (current_item.is_array()) 19803 { 19804 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); 19805 19806 current_item.m_value.array->clear(); 19807 } 19808 else if (current_item.is_object()) 19809 { 19810 for (auto&& it : *current_item.m_value.object) 19811 { 19812 stack.push_back(std::move(it.second)); 19813 } 19814 19815 current_item.m_value.object->clear(); 19816 } 19817 19818 // it's now safe that current_item get destructed 19819 // since it doesn't have any children 19820 } 19821 } 19822 19823 switch (t) 19824 { 19825 case value_t::object: 19826 { 19827 AllocatorType<object_t> alloc; 19828 std::allocator_traits<decltype(alloc)>::destroy(alloc, object); 19829 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); 19830 break; 19831 } 19832 19833 case value_t::array: 19834 { 19835 AllocatorType<array_t> alloc; 19836 std::allocator_traits<decltype(alloc)>::destroy(alloc, array); 19837 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1); 19838 break; 19839 } 19840 19841 case value_t::string: 19842 { 19843 AllocatorType<string_t> alloc; 19844 std::allocator_traits<decltype(alloc)>::destroy(alloc, string); 19845 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1); 19846 break; 19847 } 19848 19849 case value_t::binary: 19850 { 19851 AllocatorType<binary_t> alloc; 19852 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary); 19853 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1); 19854 break; 19855 } 19856 19857 case value_t::null: 19858 case value_t::boolean: 19859 case value_t::number_integer: 19860 case value_t::number_unsigned: 19861 case value_t::number_float: 19862 case value_t::discarded: 19863 default: 19864 { 19865 break; 19866 } 19867 } 19868 } 19869 }; 19870 19871 private: 19872 /*! 19873 @brief checks the class invariants 19874 19875 This function asserts the class invariants. It needs to be called at the 19876 end of every constructor to make sure that created objects respect the 19877 invariant. Furthermore, it has to be called each time the type of a JSON 19878 value is changed, because the invariant expresses a relationship between 19879 @a m_type and @a m_value. 19880 19881 Furthermore, the parent relation is checked for arrays and objects: If 19882 @a check_parents true and the value is an array or object, then the 19883 container's elements must have the current value as parent. 19884 19885 @param[in] check_parents whether the parent relation should be checked. 19886 The value is true by default and should only be set to false 19887 during destruction of objects when the invariant does not 19888 need to hold. 19889 */ 19890 void assert_invariant(bool check_parents = true) const noexcept 19891 { 19892 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); 19893 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); 19894 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); 19895 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); 19896 19897 #if JSON_DIAGNOSTICS 19898 JSON_TRY 19899 { 19900 // cppcheck-suppress assertWithSideEffect 19901 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) 19902 { 19903 return j.m_parent == this; 19904 })); 19905 } 19906 JSON_CATCH(...) {} // LCOV_EXCL_LINE 19907 #endif 19908 static_cast<void>(check_parents); 19909 } 19910 19911 void set_parents() 19912 { 19913 #if JSON_DIAGNOSTICS 19914 switch (m_type) 19915 { 19916 case value_t::array: 19917 { 19918 for (auto& element : *m_value.array) 19919 { 19920 element.m_parent = this; 19921 } 19922 break; 19923 } 19924 19925 case value_t::object: 19926 { 19927 for (auto& element : *m_value.object) 19928 { 19929 element.second.m_parent = this; 19930 } 19931 break; 19932 } 19933 19934 case value_t::null: 19935 case value_t::string: 19936 case value_t::boolean: 19937 case value_t::number_integer: 19938 case value_t::number_unsigned: 19939 case value_t::number_float: 19940 case value_t::binary: 19941 case value_t::discarded: 19942 default: 19943 break; 19944 } 19945 #endif 19946 } 19947 19948 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) 19949 { 19950 #if JSON_DIAGNOSTICS 19951 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) 19952 { 19953 (it + i)->m_parent = this; 19954 } 19955 #else 19956 static_cast<void>(count_set_parents); 19957 #endif 19958 return it; 19959 } 19960 19961 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1)) 19962 { 19963 #if JSON_DIAGNOSTICS 19964 if (old_capacity != static_cast<std::size_t>(-1)) 19965 { 19966 // see https://github.com/nlohmann/json/issues/2838 19967 JSON_ASSERT(type() == value_t::array); 19968 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) 19969 { 19970 // capacity has changed: update all parents 19971 set_parents(); 19972 return j; 19973 } 19974 } 19975 19976 // ordered_json uses a vector internally, so pointers could have 19977 // been invalidated; see https://github.com/nlohmann/json/issues/2962 19978 #ifdef JSON_HEDLEY_MSVC_VERSION 19979 #pragma warning(push ) 19980 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr 19981 #endif 19982 if (detail::is_ordered_map<object_t>::value) 19983 { 19984 set_parents(); 19985 return j; 19986 } 19987 #ifdef JSON_HEDLEY_MSVC_VERSION 19988 #pragma warning( pop ) 19989 #endif 19990 19991 j.m_parent = this; 19992 #else 19993 static_cast<void>(j); 19994 static_cast<void>(old_capacity); 19995 #endif 19996 return j; 19997 } 19998 19999 public: 20000 ////////////////////////// 20001 // JSON parser callback // 20002 ////////////////////////// 20003 20004 /// @brief parser event types 20005 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ 20006 using parse_event_t = detail::parse_event_t; 20007 20008 /// @brief per-element parser callback type 20009 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ 20010 using parser_callback_t = detail::parser_callback_t<basic_json>; 20011 20012 ////////////////// 20013 // constructors // 20014 ////////////////// 20015 20016 /// @name constructors and destructors 20017 /// Constructors of class @ref basic_json, copy/move constructor, copy 20018 /// assignment, static functions creating objects, and the destructor. 20019 /// @{ 20020 20021 /// @brief create an empty value with a given type 20022 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20023 basic_json(const value_t v) 20024 : m_type(v), m_value(v) 20025 { 20026 assert_invariant(); 20027 } 20028 20029 /// @brief create a null object 20030 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20031 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape) 20032 : basic_json(value_t::null) 20033 { 20034 assert_invariant(); 20035 } 20036 20037 /// @brief create a JSON value from compatible types 20038 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20039 template < typename CompatibleType, 20040 typename U = detail::uncvref_t<CompatibleType>, 20041 detail::enable_if_t < 20042 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 > 20043 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) 20044 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), 20045 std::forward<CompatibleType>(val)))) 20046 { 20047 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val)); 20048 set_parents(); 20049 assert_invariant(); 20050 } 20051 20052 /// @brief create a JSON value from an existing one 20053 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20054 template < typename BasicJsonType, 20055 detail::enable_if_t < 20056 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 > 20057 basic_json(const BasicJsonType& val) 20058 { 20059 using other_boolean_t = typename BasicJsonType::boolean_t; 20060 using other_number_float_t = typename BasicJsonType::number_float_t; 20061 using other_number_integer_t = typename BasicJsonType::number_integer_t; 20062 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; 20063 using other_string_t = typename BasicJsonType::string_t; 20064 using other_object_t = typename BasicJsonType::object_t; 20065 using other_array_t = typename BasicJsonType::array_t; 20066 using other_binary_t = typename BasicJsonType::binary_t; 20067 20068 switch (val.type()) 20069 { 20070 case value_t::boolean: 20071 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>()); 20072 break; 20073 case value_t::number_float: 20074 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>()); 20075 break; 20076 case value_t::number_integer: 20077 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>()); 20078 break; 20079 case value_t::number_unsigned: 20080 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>()); 20081 break; 20082 case value_t::string: 20083 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>()); 20084 break; 20085 case value_t::object: 20086 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>()); 20087 break; 20088 case value_t::array: 20089 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>()); 20090 break; 20091 case value_t::binary: 20092 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>()); 20093 break; 20094 case value_t::null: 20095 *this = nullptr; 20096 break; 20097 case value_t::discarded: 20098 m_type = value_t::discarded; 20099 break; 20100 default: // LCOV_EXCL_LINE 20101 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 20102 } 20103 JSON_ASSERT(m_type == val.type()); 20104 set_parents(); 20105 assert_invariant(); 20106 } 20107 20108 /// @brief create a container (array or object) from an initializer list 20109 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20110 basic_json(initializer_list_t init, 20111 bool type_deduction = true, 20112 value_t manual_type = value_t::array) 20113 { 20114 // check if each element is an array with two elements whose first 20115 // element is a string 20116 bool is_an_object = std::all_of(init.begin(), init.end(), 20117 [](const detail::json_ref<basic_json>& element_ref) 20118 { 20119 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); 20120 }); 20121 20122 // adjust type if type deduction is not wanted 20123 if (!type_deduction) 20124 { 20125 // if array is wanted, do not create an object though possible 20126 if (manual_type == value_t::array) 20127 { 20128 is_an_object = false; 20129 } 20130 20131 // if object is wanted but impossible, throw an exception 20132 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) 20133 { 20134 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr)); 20135 } 20136 } 20137 20138 if (is_an_object) 20139 { 20140 // the initializer list is a list of pairs -> create object 20141 m_type = value_t::object; 20142 m_value = value_t::object; 20143 20144 for (auto& element_ref : init) 20145 { 20146 auto element = element_ref.moved_or_copied(); 20147 m_value.object->emplace( 20148 std::move(*((*element.m_value.array)[0].m_value.string)), 20149 std::move((*element.m_value.array)[1])); 20150 } 20151 } 20152 else 20153 { 20154 // the initializer list describes an array -> create array 20155 m_type = value_t::array; 20156 m_value.array = create<array_t>(init.begin(), init.end()); 20157 } 20158 20159 set_parents(); 20160 assert_invariant(); 20161 } 20162 20163 /// @brief explicitly create a binary array (without subtype) 20164 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20165 JSON_HEDLEY_WARN_UNUSED_RESULT 20166 static basic_json binary(const typename binary_t::container_type& init) 20167 { 20168 auto res = basic_json(); 20169 res.m_type = value_t::binary; 20170 res.m_value = init; 20171 return res; 20172 } 20173 20174 /// @brief explicitly create a binary array (with subtype) 20175 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20176 JSON_HEDLEY_WARN_UNUSED_RESULT 20177 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) 20178 { 20179 auto res = basic_json(); 20180 res.m_type = value_t::binary; 20181 res.m_value = binary_t(init, subtype); 20182 return res; 20183 } 20184 20185 /// @brief explicitly create a binary array 20186 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20187 JSON_HEDLEY_WARN_UNUSED_RESULT 20188 static basic_json binary(typename binary_t::container_type&& init) 20189 { 20190 auto res = basic_json(); 20191 res.m_type = value_t::binary; 20192 res.m_value = std::move(init); 20193 return res; 20194 } 20195 20196 /// @brief explicitly create a binary array (with subtype) 20197 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20198 JSON_HEDLEY_WARN_UNUSED_RESULT 20199 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) 20200 { 20201 auto res = basic_json(); 20202 res.m_type = value_t::binary; 20203 res.m_value = binary_t(std::move(init), subtype); 20204 return res; 20205 } 20206 20207 /// @brief explicitly create an array from an initializer list 20208 /// @sa https://json.nlohmann.me/api/basic_json/array/ 20209 JSON_HEDLEY_WARN_UNUSED_RESULT 20210 static basic_json array(initializer_list_t init = {}) 20211 { 20212 return basic_json(init, false, value_t::array); 20213 } 20214 20215 /// @brief explicitly create an object from an initializer list 20216 /// @sa https://json.nlohmann.me/api/basic_json/object/ 20217 JSON_HEDLEY_WARN_UNUSED_RESULT 20218 static basic_json object(initializer_list_t init = {}) 20219 { 20220 return basic_json(init, false, value_t::object); 20221 } 20222 20223 /// @brief construct an array with count copies of given value 20224 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20225 basic_json(size_type cnt, const basic_json& val) 20226 : m_type(value_t::array) 20227 { 20228 m_value.array = create<array_t>(cnt, val); 20229 set_parents(); 20230 assert_invariant(); 20231 } 20232 20233 /// @brief construct a JSON container given an iterator range 20234 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20235 template < class InputIT, typename std::enable_if < 20236 std::is_same<InputIT, typename basic_json_t::iterator>::value || 20237 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 > 20238 basic_json(InputIT first, InputIT last) 20239 { 20240 JSON_ASSERT(first.m_object != nullptr); 20241 JSON_ASSERT(last.m_object != nullptr); 20242 20243 // make sure iterator fits the current value 20244 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 20245 { 20246 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr)); 20247 } 20248 20249 // copy type from first iterator 20250 m_type = first.m_object->m_type; 20251 20252 // check if iterator range is complete for primitive values 20253 switch (m_type) 20254 { 20255 case value_t::boolean: 20256 case value_t::number_float: 20257 case value_t::number_integer: 20258 case value_t::number_unsigned: 20259 case value_t::string: 20260 { 20261 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() 20262 || !last.m_it.primitive_iterator.is_end())) 20263 { 20264 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object)); 20265 } 20266 break; 20267 } 20268 20269 case value_t::null: 20270 case value_t::object: 20271 case value_t::array: 20272 case value_t::binary: 20273 case value_t::discarded: 20274 default: 20275 break; 20276 } 20277 20278 switch (m_type) 20279 { 20280 case value_t::number_integer: 20281 { 20282 m_value.number_integer = first.m_object->m_value.number_integer; 20283 break; 20284 } 20285 20286 case value_t::number_unsigned: 20287 { 20288 m_value.number_unsigned = first.m_object->m_value.number_unsigned; 20289 break; 20290 } 20291 20292 case value_t::number_float: 20293 { 20294 m_value.number_float = first.m_object->m_value.number_float; 20295 break; 20296 } 20297 20298 case value_t::boolean: 20299 { 20300 m_value.boolean = first.m_object->m_value.boolean; 20301 break; 20302 } 20303 20304 case value_t::string: 20305 { 20306 m_value = *first.m_object->m_value.string; 20307 break; 20308 } 20309 20310 case value_t::object: 20311 { 20312 m_value.object = create<object_t>(first.m_it.object_iterator, 20313 last.m_it.object_iterator); 20314 break; 20315 } 20316 20317 case value_t::array: 20318 { 20319 m_value.array = create<array_t>(first.m_it.array_iterator, 20320 last.m_it.array_iterator); 20321 break; 20322 } 20323 20324 case value_t::binary: 20325 { 20326 m_value = *first.m_object->m_value.binary; 20327 break; 20328 } 20329 20330 case value_t::null: 20331 case value_t::discarded: 20332 default: 20333 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object)); 20334 } 20335 20336 set_parents(); 20337 assert_invariant(); 20338 } 20339 20340 20341 /////////////////////////////////////// 20342 // other constructors and destructor // 20343 /////////////////////////////////////// 20344 20345 template<typename JsonRef, 20346 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>, 20347 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 > 20348 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} 20349 20350 /// @brief copy constructor 20351 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20352 basic_json(const basic_json& other) 20353 : json_base_class_t(other), 20354 m_type(other.m_type) 20355 { 20356 // check of passed value is valid 20357 other.assert_invariant(); 20358 20359 switch (m_type) 20360 { 20361 case value_t::object: 20362 { 20363 m_value = *other.m_value.object; 20364 break; 20365 } 20366 20367 case value_t::array: 20368 { 20369 m_value = *other.m_value.array; 20370 break; 20371 } 20372 20373 case value_t::string: 20374 { 20375 m_value = *other.m_value.string; 20376 break; 20377 } 20378 20379 case value_t::boolean: 20380 { 20381 m_value = other.m_value.boolean; 20382 break; 20383 } 20384 20385 case value_t::number_integer: 20386 { 20387 m_value = other.m_value.number_integer; 20388 break; 20389 } 20390 20391 case value_t::number_unsigned: 20392 { 20393 m_value = other.m_value.number_unsigned; 20394 break; 20395 } 20396 20397 case value_t::number_float: 20398 { 20399 m_value = other.m_value.number_float; 20400 break; 20401 } 20402 20403 case value_t::binary: 20404 { 20405 m_value = *other.m_value.binary; 20406 break; 20407 } 20408 20409 case value_t::null: 20410 case value_t::discarded: 20411 default: 20412 break; 20413 } 20414 20415 set_parents(); 20416 assert_invariant(); 20417 } 20418 20419 /// @brief move constructor 20420 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20421 basic_json(basic_json&& other) noexcept 20422 : json_base_class_t(std::move(other)), 20423 m_type(std::move(other.m_type)), 20424 m_value(std::move(other.m_value)) 20425 { 20426 // check that passed value is valid 20427 other.assert_invariant(false); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) 20428 20429 // invalidate payload 20430 other.m_type = value_t::null; 20431 other.m_value = {}; 20432 20433 set_parents(); 20434 assert_invariant(); 20435 } 20436 20437 /// @brief copy assignment 20438 /// @sa https://json.nlohmann.me/api/basic_json/operator=/ 20439 basic_json& operator=(basic_json other) noexcept ( 20440 std::is_nothrow_move_constructible<value_t>::value&& 20441 std::is_nothrow_move_assignable<value_t>::value&& 20442 std::is_nothrow_move_constructible<json_value>::value&& 20443 std::is_nothrow_move_assignable<json_value>::value&& 20444 std::is_nothrow_move_assignable<json_base_class_t>::value 20445 ) 20446 { 20447 // check that passed value is valid 20448 other.assert_invariant(); 20449 20450 using std::swap; 20451 swap(m_type, other.m_type); 20452 swap(m_value, other.m_value); 20453 json_base_class_t::operator=(std::move(other)); 20454 20455 set_parents(); 20456 assert_invariant(); 20457 return *this; 20458 } 20459 20460 /// @brief destructor 20461 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ 20462 ~basic_json() noexcept 20463 { 20464 assert_invariant(false); 20465 m_value.destroy(m_type); 20466 } 20467 20468 /// @} 20469 20470 public: 20471 /////////////////////// 20472 // object inspection // 20473 /////////////////////// 20474 20475 /// @name object inspection 20476 /// Functions to inspect the type of a JSON value. 20477 /// @{ 20478 20479 /// @brief serialization 20480 /// @sa https://json.nlohmann.me/api/basic_json/dump/ 20481 string_t dump(const int indent = -1, 20482 const char indent_char = ' ', 20483 const bool ensure_ascii = false, 20484 const error_handler_t error_handler = error_handler_t::strict) const 20485 { 20486 string_t result; 20487 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler); 20488 20489 if (indent >= 0) 20490 { 20491 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent)); 20492 } 20493 else 20494 { 20495 s.dump(*this, false, ensure_ascii, 0); 20496 } 20497 20498 return result; 20499 } 20500 20501 /// @brief return the type of the JSON value (explicit) 20502 /// @sa https://json.nlohmann.me/api/basic_json/type/ 20503 constexpr value_t type() const noexcept 20504 { 20505 return m_type; 20506 } 20507 20508 /// @brief return whether type is primitive 20509 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ 20510 constexpr bool is_primitive() const noexcept 20511 { 20512 return is_null() || is_string() || is_boolean() || is_number() || is_binary(); 20513 } 20514 20515 /// @brief return whether type is structured 20516 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/ 20517 constexpr bool is_structured() const noexcept 20518 { 20519 return is_array() || is_object(); 20520 } 20521 20522 /// @brief return whether value is null 20523 /// @sa https://json.nlohmann.me/api/basic_json/is_null/ 20524 constexpr bool is_null() const noexcept 20525 { 20526 return m_type == value_t::null; 20527 } 20528 20529 /// @brief return whether value is a boolean 20530 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ 20531 constexpr bool is_boolean() const noexcept 20532 { 20533 return m_type == value_t::boolean; 20534 } 20535 20536 /// @brief return whether value is a number 20537 /// @sa https://json.nlohmann.me/api/basic_json/is_number/ 20538 constexpr bool is_number() const noexcept 20539 { 20540 return is_number_integer() || is_number_float(); 20541 } 20542 20543 /// @brief return whether value is an integer number 20544 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ 20545 constexpr bool is_number_integer() const noexcept 20546 { 20547 return m_type == value_t::number_integer || m_type == value_t::number_unsigned; 20548 } 20549 20550 /// @brief return whether value is an unsigned integer number 20551 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ 20552 constexpr bool is_number_unsigned() const noexcept 20553 { 20554 return m_type == value_t::number_unsigned; 20555 } 20556 20557 /// @brief return whether value is a floating-point number 20558 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ 20559 constexpr bool is_number_float() const noexcept 20560 { 20561 return m_type == value_t::number_float; 20562 } 20563 20564 /// @brief return whether value is an object 20565 /// @sa https://json.nlohmann.me/api/basic_json/is_object/ 20566 constexpr bool is_object() const noexcept 20567 { 20568 return m_type == value_t::object; 20569 } 20570 20571 /// @brief return whether value is an array 20572 /// @sa https://json.nlohmann.me/api/basic_json/is_array/ 20573 constexpr bool is_array() const noexcept 20574 { 20575 return m_type == value_t::array; 20576 } 20577 20578 /// @brief return whether value is a string 20579 /// @sa https://json.nlohmann.me/api/basic_json/is_string/ 20580 constexpr bool is_string() const noexcept 20581 { 20582 return m_type == value_t::string; 20583 } 20584 20585 /// @brief return whether value is a binary array 20586 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ 20587 constexpr bool is_binary() const noexcept 20588 { 20589 return m_type == value_t::binary; 20590 } 20591 20592 /// @brief return whether value is discarded 20593 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ 20594 constexpr bool is_discarded() const noexcept 20595 { 20596 return m_type == value_t::discarded; 20597 } 20598 20599 /// @brief return the type of the JSON value (implicit) 20600 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ 20601 constexpr operator value_t() const noexcept 20602 { 20603 return m_type; 20604 } 20605 20606 /// @} 20607 20608 private: 20609 ////////////////// 20610 // value access // 20611 ////////////////// 20612 20613 /// get a boolean (explicit) 20614 boolean_t get_impl(boolean_t* /*unused*/) const 20615 { 20616 if (JSON_HEDLEY_LIKELY(is_boolean())) 20617 { 20618 return m_value.boolean; 20619 } 20620 20621 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); 20622 } 20623 20624 /// get a pointer to the value (object) 20625 object_t* get_impl_ptr(object_t* /*unused*/) noexcept 20626 { 20627 return is_object() ? m_value.object : nullptr; 20628 } 20629 20630 /// get a pointer to the value (object) 20631 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept 20632 { 20633 return is_object() ? m_value.object : nullptr; 20634 } 20635 20636 /// get a pointer to the value (array) 20637 array_t* get_impl_ptr(array_t* /*unused*/) noexcept 20638 { 20639 return is_array() ? m_value.array : nullptr; 20640 } 20641 20642 /// get a pointer to the value (array) 20643 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept 20644 { 20645 return is_array() ? m_value.array : nullptr; 20646 } 20647 20648 /// get a pointer to the value (string) 20649 string_t* get_impl_ptr(string_t* /*unused*/) noexcept 20650 { 20651 return is_string() ? m_value.string : nullptr; 20652 } 20653 20654 /// get a pointer to the value (string) 20655 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept 20656 { 20657 return is_string() ? m_value.string : nullptr; 20658 } 20659 20660 /// get a pointer to the value (boolean) 20661 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept 20662 { 20663 return is_boolean() ? &m_value.boolean : nullptr; 20664 } 20665 20666 /// get a pointer to the value (boolean) 20667 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept 20668 { 20669 return is_boolean() ? &m_value.boolean : nullptr; 20670 } 20671 20672 /// get a pointer to the value (integer number) 20673 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept 20674 { 20675 return is_number_integer() ? &m_value.number_integer : nullptr; 20676 } 20677 20678 /// get a pointer to the value (integer number) 20679 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept 20680 { 20681 return is_number_integer() ? &m_value.number_integer : nullptr; 20682 } 20683 20684 /// get a pointer to the value (unsigned number) 20685 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept 20686 { 20687 return is_number_unsigned() ? &m_value.number_unsigned : nullptr; 20688 } 20689 20690 /// get a pointer to the value (unsigned number) 20691 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept 20692 { 20693 return is_number_unsigned() ? &m_value.number_unsigned : nullptr; 20694 } 20695 20696 /// get a pointer to the value (floating-point number) 20697 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept 20698 { 20699 return is_number_float() ? &m_value.number_float : nullptr; 20700 } 20701 20702 /// get a pointer to the value (floating-point number) 20703 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept 20704 { 20705 return is_number_float() ? &m_value.number_float : nullptr; 20706 } 20707 20708 /// get a pointer to the value (binary) 20709 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept 20710 { 20711 return is_binary() ? m_value.binary : nullptr; 20712 } 20713 20714 /// get a pointer to the value (binary) 20715 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept 20716 { 20717 return is_binary() ? m_value.binary : nullptr; 20718 } 20719 20720 /*! 20721 @brief helper function to implement get_ref() 20722 20723 This function helps to implement get_ref() without code duplication for 20724 const and non-const overloads 20725 20726 @tparam ThisType will be deduced as `basic_json` or `const basic_json` 20727 20728 @throw type_error.303 if ReferenceType does not match underlying value 20729 type of the current JSON 20730 */ 20731 template<typename ReferenceType, typename ThisType> 20732 static ReferenceType get_ref_impl(ThisType& obj) 20733 { 20734 // delegate the call to get_ptr<>() 20735 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>(); 20736 20737 if (JSON_HEDLEY_LIKELY(ptr != nullptr)) 20738 { 20739 return *ptr; 20740 } 20741 20742 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj)); 20743 } 20744 20745 public: 20746 /// @name value access 20747 /// Direct access to the stored value of a JSON value. 20748 /// @{ 20749 20750 /// @brief get a pointer value (implicit) 20751 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 20752 template<typename PointerType, typename std::enable_if< 20753 std::is_pointer<PointerType>::value, int>::type = 0> 20754 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 20755 { 20756 // delegate the call to get_impl_ptr<>() 20757 return get_impl_ptr(static_cast<PointerType>(nullptr)); 20758 } 20759 20760 /// @brief get a pointer value (implicit) 20761 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 20762 template < typename PointerType, typename std::enable_if < 20763 std::is_pointer<PointerType>::value&& 20764 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 > 20765 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 20766 { 20767 // delegate the call to get_impl_ptr<>() const 20768 return get_impl_ptr(static_cast<PointerType>(nullptr)); 20769 } 20770 20771 private: 20772 /*! 20773 @brief get a value (explicit) 20774 20775 Explicit type conversion between the JSON value and a compatible value 20776 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 20777 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 20778 The value is converted by calling the @ref json_serializer<ValueType> 20779 `from_json()` method. 20780 20781 The function is equivalent to executing 20782 @code {.cpp} 20783 ValueType ret; 20784 JSONSerializer<ValueType>::from_json(*this, ret); 20785 return ret; 20786 @endcode 20787 20788 This overloads is chosen if: 20789 - @a ValueType is not @ref basic_json, 20790 - @ref json_serializer<ValueType> has a `from_json()` method of the form 20791 `void from_json(const basic_json&, ValueType&)`, and 20792 - @ref json_serializer<ValueType> does not have a `from_json()` method of 20793 the form `ValueType from_json(const basic_json&)` 20794 20795 @tparam ValueType the returned value type 20796 20797 @return copy of the JSON value, converted to @a ValueType 20798 20799 @throw what @ref json_serializer<ValueType> `from_json()` method throws 20800 20801 @liveexample{The example below shows several conversions from JSON values 20802 to other types. There a few things to note: (1) Floating-point numbers can 20803 be converted to integers\, (2) A JSON array can be converted to a standard 20804 `std::vector<short>`\, (3) A JSON object can be converted to C++ 20805 associative containers such as `std::unordered_map<std::string\, 20806 json>`.,get__ValueType_const} 20807 20808 @since version 2.1.0 20809 */ 20810 template < typename ValueType, 20811 detail::enable_if_t < 20812 detail::is_default_constructible<ValueType>::value&& 20813 detail::has_from_json<basic_json_t, ValueType>::value, 20814 int > = 0 > 20815 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( 20816 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) 20817 { 20818 auto ret = ValueType(); 20819 JSONSerializer<ValueType>::from_json(*this, ret); 20820 return ret; 20821 } 20822 20823 /*! 20824 @brief get a value (explicit); special case 20825 20826 Explicit type conversion between the JSON value and a compatible value 20827 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 20828 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 20829 The value is converted by calling the @ref json_serializer<ValueType> 20830 `from_json()` method. 20831 20832 The function is equivalent to executing 20833 @code {.cpp} 20834 return JSONSerializer<ValueType>::from_json(*this); 20835 @endcode 20836 20837 This overloads is chosen if: 20838 - @a ValueType is not @ref basic_json and 20839 - @ref json_serializer<ValueType> has a `from_json()` method of the form 20840 `ValueType from_json(const basic_json&)` 20841 20842 @note If @ref json_serializer<ValueType> has both overloads of 20843 `from_json()`, this one is chosen. 20844 20845 @tparam ValueType the returned value type 20846 20847 @return copy of the JSON value, converted to @a ValueType 20848 20849 @throw what @ref json_serializer<ValueType> `from_json()` method throws 20850 20851 @since version 2.1.0 20852 */ 20853 template < typename ValueType, 20854 detail::enable_if_t < 20855 detail::has_non_default_from_json<basic_json_t, ValueType>::value, 20856 int > = 0 > 20857 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( 20858 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) 20859 { 20860 return JSONSerializer<ValueType>::from_json(*this); 20861 } 20862 20863 /*! 20864 @brief get special-case overload 20865 20866 This overloads converts the current @ref basic_json in a different 20867 @ref basic_json type 20868 20869 @tparam BasicJsonType == @ref basic_json 20870 20871 @return a copy of *this, converted into @a BasicJsonType 20872 20873 @complexity Depending on the implementation of the called `from_json()` 20874 method. 20875 20876 @since version 3.2.0 20877 */ 20878 template < typename BasicJsonType, 20879 detail::enable_if_t < 20880 detail::is_basic_json<BasicJsonType>::value, 20881 int > = 0 > 20882 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const 20883 { 20884 return *this; 20885 } 20886 20887 /*! 20888 @brief get special-case overload 20889 20890 This overloads avoids a lot of template boilerplate, it can be seen as the 20891 identity method 20892 20893 @tparam BasicJsonType == @ref basic_json 20894 20895 @return a copy of *this 20896 20897 @complexity Constant. 20898 20899 @since version 2.1.0 20900 */ 20901 template<typename BasicJsonType, 20902 detail::enable_if_t< 20903 std::is_same<BasicJsonType, basic_json_t>::value, 20904 int> = 0> 20905 basic_json get_impl(detail::priority_tag<3> /*unused*/) const 20906 { 20907 return *this; 20908 } 20909 20910 /*! 20911 @brief get a pointer value (explicit) 20912 @copydoc get() 20913 */ 20914 template<typename PointerType, 20915 detail::enable_if_t< 20916 std::is_pointer<PointerType>::value, 20917 int> = 0> 20918 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept 20919 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) 20920 { 20921 // delegate the call to get_ptr 20922 return get_ptr<PointerType>(); 20923 } 20924 20925 public: 20926 /*! 20927 @brief get a (pointer) value (explicit) 20928 20929 Performs explicit type conversion between the JSON value and a compatible value if required. 20930 20931 - If the requested type is a pointer to the internally stored JSON value that pointer is returned. 20932 No copies are made. 20933 20934 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible 20935 from the current @ref basic_json. 20936 20937 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()` 20938 method. 20939 20940 @tparam ValueTypeCV the provided value type 20941 @tparam ValueType the returned value type 20942 20943 @return copy of the JSON value, converted to @tparam ValueType if necessary 20944 20945 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required 20946 20947 @since version 2.1.0 20948 */ 20949 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>> 20950 #if defined(JSON_HAS_CPP_14) 20951 constexpr 20952 #endif 20953 auto get() const noexcept( 20954 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))) 20955 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})) 20956 { 20957 // we cannot static_assert on ValueTypeCV being non-const, because 20958 // there is support for get<const basic_json_t>(), which is why we 20959 // still need the uncvref 20960 static_assert(!std::is_reference<ValueTypeCV>::value, 20961 "get() cannot be used with reference types, you might want to use get_ref()"); 20962 return get_impl<ValueType>(detail::priority_tag<4> {}); 20963 } 20964 20965 /*! 20966 @brief get a pointer value (explicit) 20967 20968 Explicit pointer access to the internally stored JSON value. No copies are 20969 made. 20970 20971 @warning The pointer becomes invalid if the underlying JSON object 20972 changes. 20973 20974 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref 20975 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 20976 @ref number_unsigned_t, or @ref number_float_t. 20977 20978 @return pointer to the internally stored JSON value if the requested 20979 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise 20980 20981 @complexity Constant. 20982 20983 @liveexample{The example below shows how pointers to internal values of a 20984 JSON value can be requested. Note that no type conversions are made and a 20985 `nullptr` is returned if the value and the requested pointer type does not 20986 match.,get__PointerType} 20987 20988 @sa see @ref get_ptr() for explicit pointer-member access 20989 20990 @since version 1.0.0 20991 */ 20992 template<typename PointerType, typename std::enable_if< 20993 std::is_pointer<PointerType>::value, int>::type = 0> 20994 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) 20995 { 20996 // delegate the call to get_ptr 20997 return get_ptr<PointerType>(); 20998 } 20999 21000 /// @brief get a value (explicit) 21001 /// @sa https://json.nlohmann.me/api/basic_json/get_to/ 21002 template < typename ValueType, 21003 detail::enable_if_t < 21004 !detail::is_basic_json<ValueType>::value&& 21005 detail::has_from_json<basic_json_t, ValueType>::value, 21006 int > = 0 > 21007 ValueType & get_to(ValueType& v) const noexcept(noexcept( 21008 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) 21009 { 21010 JSONSerializer<ValueType>::from_json(*this, v); 21011 return v; 21012 } 21013 21014 // specialization to allow calling get_to with a basic_json value 21015 // see https://github.com/nlohmann/json/issues/2175 21016 template<typename ValueType, 21017 detail::enable_if_t < 21018 detail::is_basic_json<ValueType>::value, 21019 int> = 0> 21020 ValueType & get_to(ValueType& v) const 21021 { 21022 v = *this; 21023 return v; 21024 } 21025 21026 template < 21027 typename T, std::size_t N, 21028 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21029 detail::enable_if_t < 21030 detail::has_from_json<basic_json_t, Array>::value, int > = 0 > 21031 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21032 noexcept(noexcept(JSONSerializer<Array>::from_json( 21033 std::declval<const basic_json_t&>(), v))) 21034 { 21035 JSONSerializer<Array>::from_json(*this, v); 21036 return v; 21037 } 21038 21039 /// @brief get a reference value (implicit) 21040 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21041 template<typename ReferenceType, typename std::enable_if< 21042 std::is_reference<ReferenceType>::value, int>::type = 0> 21043 ReferenceType get_ref() 21044 { 21045 // delegate call to get_ref_impl 21046 return get_ref_impl<ReferenceType>(*this); 21047 } 21048 21049 /// @brief get a reference value (implicit) 21050 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21051 template < typename ReferenceType, typename std::enable_if < 21052 std::is_reference<ReferenceType>::value&& 21053 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 > 21054 ReferenceType get_ref() const 21055 { 21056 // delegate call to get_ref_impl 21057 return get_ref_impl<ReferenceType>(*this); 21058 } 21059 21060 /*! 21061 @brief get a value (implicit) 21062 21063 Implicit type conversion between the JSON value and a compatible value. 21064 The call is realized by calling @ref get() const. 21065 21066 @tparam ValueType non-pointer type compatible to the JSON value, for 21067 instance `int` for JSON integer numbers, `bool` for JSON booleans, or 21068 `std::vector` types for JSON arrays. The character type of @ref string_t 21069 as well as an initializer list of this type is excluded to avoid 21070 ambiguities as these types implicitly convert to `std::string`. 21071 21072 @return copy of the JSON value, converted to type @a ValueType 21073 21074 @throw type_error.302 in case passed type @a ValueType is incompatible 21075 to the JSON value type (e.g., the JSON value is of type boolean, but a 21076 string is requested); see example below 21077 21078 @complexity Linear in the size of the JSON value. 21079 21080 @liveexample{The example below shows several conversions from JSON values 21081 to other types. There a few things to note: (1) Floating-point numbers can 21082 be converted to integers\, (2) A JSON array can be converted to a standard 21083 `std::vector<short>`\, (3) A JSON object can be converted to C++ 21084 associative containers such as `std::unordered_map<std::string\, 21085 json>`.,operator__ValueType} 21086 21087 @since version 1.0.0 21088 */ 21089 template < typename ValueType, typename std::enable_if < 21090 detail::conjunction < 21091 detail::negation<std::is_pointer<ValueType>>, 21092 detail::negation<std::is_same<ValueType, std::nullptr_t>>, 21093 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>, 21094 detail::negation<std::is_same<ValueType, typename string_t::value_type>>, 21095 detail::negation<detail::is_basic_json<ValueType>>, 21096 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>, 21097 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) 21098 detail::negation<std::is_same<ValueType, std::string_view>>, 21099 #endif 21100 #if defined(JSON_HAS_CPP_17) 21101 detail::negation<std::is_same<ValueType, std::any>>, 21102 #endif 21103 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType> 21104 >::value, int >::type = 0 > 21105 JSON_EXPLICIT operator ValueType() const 21106 { 21107 // delegate the call to get<>() const 21108 return get<ValueType>(); 21109 } 21110 21111 /// @brief get a binary value 21112 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21113 binary_t& get_binary() 21114 { 21115 if (!is_binary()) 21116 { 21117 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 21118 } 21119 21120 return *get_ptr<binary_t*>(); 21121 } 21122 21123 /// @brief get a binary value 21124 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21125 const binary_t& get_binary() const 21126 { 21127 if (!is_binary()) 21128 { 21129 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 21130 } 21131 21132 return *get_ptr<const binary_t*>(); 21133 } 21134 21135 /// @} 21136 21137 21138 //////////////////// 21139 // element access // 21140 //////////////////// 21141 21142 /// @name element access 21143 /// Access to the JSON value. 21144 /// @{ 21145 21146 /// @brief access specified array element with bounds checking 21147 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21148 reference at(size_type idx) 21149 { 21150 // at only works for arrays 21151 if (JSON_HEDLEY_LIKELY(is_array())) 21152 { 21153 JSON_TRY 21154 { 21155 return set_parent(m_value.array->at(idx)); 21156 } 21157 JSON_CATCH (std::out_of_range&) 21158 { 21159 // create better exception explanation 21160 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21161 } 21162 } 21163 else 21164 { 21165 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21166 } 21167 } 21168 21169 /// @brief access specified array element with bounds checking 21170 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21171 const_reference at(size_type idx) const 21172 { 21173 // at only works for arrays 21174 if (JSON_HEDLEY_LIKELY(is_array())) 21175 { 21176 JSON_TRY 21177 { 21178 return m_value.array->at(idx); 21179 } 21180 JSON_CATCH (std::out_of_range&) 21181 { 21182 // create better exception explanation 21183 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21184 } 21185 } 21186 else 21187 { 21188 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21189 } 21190 } 21191 21192 /// @brief access specified object element with bounds checking 21193 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21194 reference at(const typename object_t::key_type& key) 21195 { 21196 // at only works for objects 21197 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21198 { 21199 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21200 } 21201 21202 auto it = m_value.object->find(key); 21203 if (it == m_value.object->end()) 21204 { 21205 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 21206 } 21207 return set_parent(it->second); 21208 } 21209 21210 /// @brief access specified object element with bounds checking 21211 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21212 template<class KeyType, detail::enable_if_t< 21213 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21214 reference at(KeyType && key) 21215 { 21216 // at only works for objects 21217 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21218 { 21219 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21220 } 21221 21222 auto it = m_value.object->find(std::forward<KeyType>(key)); 21223 if (it == m_value.object->end()) 21224 { 21225 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 21226 } 21227 return set_parent(it->second); 21228 } 21229 21230 /// @brief access specified object element with bounds checking 21231 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21232 const_reference at(const typename object_t::key_type& key) const 21233 { 21234 // at only works for objects 21235 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21236 { 21237 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21238 } 21239 21240 auto it = m_value.object->find(key); 21241 if (it == m_value.object->end()) 21242 { 21243 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 21244 } 21245 return it->second; 21246 } 21247 21248 /// @brief access specified object element with bounds checking 21249 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21250 template<class KeyType, detail::enable_if_t< 21251 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21252 const_reference at(KeyType && key) const 21253 { 21254 // at only works for objects 21255 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21256 { 21257 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21258 } 21259 21260 auto it = m_value.object->find(std::forward<KeyType>(key)); 21261 if (it == m_value.object->end()) 21262 { 21263 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 21264 } 21265 return it->second; 21266 } 21267 21268 /// @brief access specified array element 21269 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21270 reference operator[](size_type idx) 21271 { 21272 // implicitly convert null value to an empty array 21273 if (is_null()) 21274 { 21275 m_type = value_t::array; 21276 m_value.array = create<array_t>(); 21277 assert_invariant(); 21278 } 21279 21280 // operator[] only works for arrays 21281 if (JSON_HEDLEY_LIKELY(is_array())) 21282 { 21283 // fill up array with null values if given idx is outside range 21284 if (idx >= m_value.array->size()) 21285 { 21286 #if JSON_DIAGNOSTICS 21287 // remember array size & capacity before resizing 21288 const auto old_size = m_value.array->size(); 21289 const auto old_capacity = m_value.array->capacity(); 21290 #endif 21291 m_value.array->resize(idx + 1); 21292 21293 #if JSON_DIAGNOSTICS 21294 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) 21295 { 21296 // capacity has changed: update all parents 21297 set_parents(); 21298 } 21299 else 21300 { 21301 // set parent for values added above 21302 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size)); 21303 } 21304 #endif 21305 assert_invariant(); 21306 } 21307 21308 return m_value.array->operator[](idx); 21309 } 21310 21311 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 21312 } 21313 21314 /// @brief access specified array element 21315 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21316 const_reference operator[](size_type idx) const 21317 { 21318 // const operator[] only works for arrays 21319 if (JSON_HEDLEY_LIKELY(is_array())) 21320 { 21321 return m_value.array->operator[](idx); 21322 } 21323 21324 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 21325 } 21326 21327 /// @brief access specified object element 21328 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21329 reference operator[](typename object_t::key_type key) 21330 { 21331 // implicitly convert null value to an empty object 21332 if (is_null()) 21333 { 21334 m_type = value_t::object; 21335 m_value.object = create<object_t>(); 21336 assert_invariant(); 21337 } 21338 21339 // operator[] only works for objects 21340 if (JSON_HEDLEY_LIKELY(is_object())) 21341 { 21342 auto result = m_value.object->emplace(std::move(key), nullptr); 21343 return set_parent(result.first->second); 21344 } 21345 21346 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21347 } 21348 21349 /// @brief access specified object element 21350 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21351 const_reference operator[](const typename object_t::key_type& key) const 21352 { 21353 // const operator[] only works for objects 21354 if (JSON_HEDLEY_LIKELY(is_object())) 21355 { 21356 auto it = m_value.object->find(key); 21357 JSON_ASSERT(it != m_value.object->end()); 21358 return it->second; 21359 } 21360 21361 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21362 } 21363 21364 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC 21365 // (they seemingly cannot be constrained to resolve the ambiguity) 21366 template<typename T> 21367 reference operator[](T* key) 21368 { 21369 return operator[](typename object_t::key_type(key)); 21370 } 21371 21372 template<typename T> 21373 const_reference operator[](T* key) const 21374 { 21375 return operator[](typename object_t::key_type(key)); 21376 } 21377 21378 /// @brief access specified object element 21379 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21380 template<class KeyType, detail::enable_if_t< 21381 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 21382 reference operator[](KeyType && key) 21383 { 21384 // implicitly convert null value to an empty object 21385 if (is_null()) 21386 { 21387 m_type = value_t::object; 21388 m_value.object = create<object_t>(); 21389 assert_invariant(); 21390 } 21391 21392 // operator[] only works for objects 21393 if (JSON_HEDLEY_LIKELY(is_object())) 21394 { 21395 auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr); 21396 return set_parent(result.first->second); 21397 } 21398 21399 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21400 } 21401 21402 /// @brief access specified object element 21403 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21404 template<class KeyType, detail::enable_if_t< 21405 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 21406 const_reference operator[](KeyType && key) const 21407 { 21408 // const operator[] only works for objects 21409 if (JSON_HEDLEY_LIKELY(is_object())) 21410 { 21411 auto it = m_value.object->find(std::forward<KeyType>(key)); 21412 JSON_ASSERT(it != m_value.object->end()); 21413 return it->second; 21414 } 21415 21416 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21417 } 21418 21419 private: 21420 template<typename KeyType> 21421 using is_comparable_with_object_key = detail::is_comparable < 21422 object_comparator_t, const typename object_t::key_type&, KeyType >; 21423 21424 template<typename ValueType> 21425 using value_return_type = std::conditional < 21426 detail::is_c_string_uncvref<ValueType>::value, 21427 string_t, typename std::decay<ValueType>::type >; 21428 21429 public: 21430 /// @brief access specified object element with default value 21431 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21432 template < class ValueType, detail::enable_if_t < 21433 !detail::is_transparent<object_comparator_t>::value 21434 && detail::is_getable<basic_json_t, ValueType>::value 21435 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21436 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const 21437 { 21438 // value only works for objects 21439 if (JSON_HEDLEY_LIKELY(is_object())) 21440 { 21441 // if key is found, return value and given default value otherwise 21442 const auto it = find(key); 21443 if (it != end()) 21444 { 21445 return it->template get<ValueType>(); 21446 } 21447 21448 return default_value; 21449 } 21450 21451 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21452 } 21453 21454 /// @brief access specified object element with default value 21455 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21456 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 21457 detail::enable_if_t < 21458 !detail::is_transparent<object_comparator_t>::value 21459 && detail::is_getable<basic_json_t, ReturnType>::value 21460 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21461 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const 21462 { 21463 // value only works for objects 21464 if (JSON_HEDLEY_LIKELY(is_object())) 21465 { 21466 // if key is found, return value and given default value otherwise 21467 const auto it = find(key); 21468 if (it != end()) 21469 { 21470 return it->template get<ReturnType>(); 21471 } 21472 21473 return std::forward<ValueType>(default_value); 21474 } 21475 21476 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21477 } 21478 21479 /// @brief access specified object element with default value 21480 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21481 template < class ValueType, class KeyType, detail::enable_if_t < 21482 detail::is_transparent<object_comparator_t>::value 21483 && !detail::is_json_pointer<KeyType>::value 21484 && is_comparable_with_object_key<KeyType>::value 21485 && detail::is_getable<basic_json_t, ValueType>::value 21486 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21487 ValueType value(KeyType && key, const ValueType& default_value) const 21488 { 21489 // value only works for objects 21490 if (JSON_HEDLEY_LIKELY(is_object())) 21491 { 21492 // if key is found, return value and given default value otherwise 21493 const auto it = find(std::forward<KeyType>(key)); 21494 if (it != end()) 21495 { 21496 return it->template get<ValueType>(); 21497 } 21498 21499 return default_value; 21500 } 21501 21502 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21503 } 21504 21505 /// @brief access specified object element via JSON Pointer with default value 21506 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21507 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type, 21508 detail::enable_if_t < 21509 detail::is_transparent<object_comparator_t>::value 21510 && !detail::is_json_pointer<KeyType>::value 21511 && is_comparable_with_object_key<KeyType>::value 21512 && detail::is_getable<basic_json_t, ReturnType>::value 21513 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21514 ReturnType value(KeyType && key, ValueType && default_value) const 21515 { 21516 // value only works for objects 21517 if (JSON_HEDLEY_LIKELY(is_object())) 21518 { 21519 // if key is found, return value and given default value otherwise 21520 const auto it = find(std::forward<KeyType>(key)); 21521 if (it != end()) 21522 { 21523 return it->template get<ReturnType>(); 21524 } 21525 21526 return std::forward<ValueType>(default_value); 21527 } 21528 21529 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21530 } 21531 21532 /// @brief access specified object element via JSON Pointer with default value 21533 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21534 template < class ValueType, detail::enable_if_t < 21535 detail::is_getable<basic_json_t, ValueType>::value 21536 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21537 ValueType value(const json_pointer& ptr, const ValueType& default_value) const 21538 { 21539 // value only works for objects 21540 if (JSON_HEDLEY_LIKELY(is_object())) 21541 { 21542 // if pointer resolves a value, return it or use default value 21543 JSON_TRY 21544 { 21545 return ptr.get_checked(this).template get<ValueType>(); 21546 } 21547 JSON_INTERNAL_CATCH (out_of_range&) 21548 { 21549 return default_value; 21550 } 21551 } 21552 21553 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21554 } 21555 21556 /// @brief access specified object element via JSON Pointer with default value 21557 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21558 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 21559 detail::enable_if_t < 21560 detail::is_getable<basic_json_t, ReturnType>::value 21561 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21562 ReturnType value(const json_pointer& ptr, ValueType && default_value) const 21563 { 21564 // value only works for objects 21565 if (JSON_HEDLEY_LIKELY(is_object())) 21566 { 21567 // if pointer resolves a value, return it or use default value 21568 JSON_TRY 21569 { 21570 return ptr.get_checked(this).template get<ReturnType>(); 21571 } 21572 JSON_INTERNAL_CATCH (out_of_range&) 21573 { 21574 return std::forward<ValueType>(default_value); 21575 } 21576 } 21577 21578 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21579 } 21580 21581 template < class ValueType, class BasicJsonType, detail::enable_if_t < 21582 detail::is_basic_json<BasicJsonType>::value 21583 && detail::is_getable<basic_json_t, ValueType>::value 21584 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21585 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 21586 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const 21587 { 21588 return value(ptr.convert(), default_value); 21589 } 21590 21591 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type, 21592 detail::enable_if_t < 21593 detail::is_basic_json<BasicJsonType>::value 21594 && detail::is_getable<basic_json_t, ReturnType>::value 21595 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21596 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 21597 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const 21598 { 21599 return value(ptr.convert(), std::forward<ValueType>(default_value)); 21600 } 21601 21602 /// @brief access the first element 21603 /// @sa https://json.nlohmann.me/api/basic_json/front/ 21604 reference front() 21605 { 21606 return *begin(); 21607 } 21608 21609 /// @brief access the first element 21610 /// @sa https://json.nlohmann.me/api/basic_json/front/ 21611 const_reference front() const 21612 { 21613 return *cbegin(); 21614 } 21615 21616 /// @brief access the last element 21617 /// @sa https://json.nlohmann.me/api/basic_json/back/ 21618 reference back() 21619 { 21620 auto tmp = end(); 21621 --tmp; 21622 return *tmp; 21623 } 21624 21625 /// @brief access the last element 21626 /// @sa https://json.nlohmann.me/api/basic_json/back/ 21627 const_reference back() const 21628 { 21629 auto tmp = cend(); 21630 --tmp; 21631 return *tmp; 21632 } 21633 21634 /// @brief remove element given an iterator 21635 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21636 template < class IteratorType, detail::enable_if_t < 21637 std::is_same<IteratorType, typename basic_json_t::iterator>::value || 21638 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 21639 IteratorType erase(IteratorType pos) 21640 { 21641 // make sure iterator fits the current value 21642 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) 21643 { 21644 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 21645 } 21646 21647 IteratorType result = end(); 21648 21649 switch (m_type) 21650 { 21651 case value_t::boolean: 21652 case value_t::number_float: 21653 case value_t::number_integer: 21654 case value_t::number_unsigned: 21655 case value_t::string: 21656 case value_t::binary: 21657 { 21658 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) 21659 { 21660 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this)); 21661 } 21662 21663 if (is_string()) 21664 { 21665 AllocatorType<string_t> alloc; 21666 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string); 21667 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1); 21668 m_value.string = nullptr; 21669 } 21670 else if (is_binary()) 21671 { 21672 AllocatorType<binary_t> alloc; 21673 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary); 21674 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1); 21675 m_value.binary = nullptr; 21676 } 21677 21678 m_type = value_t::null; 21679 assert_invariant(); 21680 break; 21681 } 21682 21683 case value_t::object: 21684 { 21685 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); 21686 break; 21687 } 21688 21689 case value_t::array: 21690 { 21691 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); 21692 break; 21693 } 21694 21695 case value_t::null: 21696 case value_t::discarded: 21697 default: 21698 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21699 } 21700 21701 return result; 21702 } 21703 21704 /// @brief remove elements given an iterator range 21705 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21706 template < class IteratorType, detail::enable_if_t < 21707 std::is_same<IteratorType, typename basic_json_t::iterator>::value || 21708 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 21709 IteratorType erase(IteratorType first, IteratorType last) 21710 { 21711 // make sure iterator fits the current value 21712 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) 21713 { 21714 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this)); 21715 } 21716 21717 IteratorType result = end(); 21718 21719 switch (m_type) 21720 { 21721 case value_t::boolean: 21722 case value_t::number_float: 21723 case value_t::number_integer: 21724 case value_t::number_unsigned: 21725 case value_t::string: 21726 case value_t::binary: 21727 { 21728 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() 21729 || !last.m_it.primitive_iterator.is_end())) 21730 { 21731 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this)); 21732 } 21733 21734 if (is_string()) 21735 { 21736 AllocatorType<string_t> alloc; 21737 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string); 21738 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1); 21739 m_value.string = nullptr; 21740 } 21741 else if (is_binary()) 21742 { 21743 AllocatorType<binary_t> alloc; 21744 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary); 21745 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1); 21746 m_value.binary = nullptr; 21747 } 21748 21749 m_type = value_t::null; 21750 assert_invariant(); 21751 break; 21752 } 21753 21754 case value_t::object: 21755 { 21756 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, 21757 last.m_it.object_iterator); 21758 break; 21759 } 21760 21761 case value_t::array: 21762 { 21763 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, 21764 last.m_it.array_iterator); 21765 break; 21766 } 21767 21768 case value_t::null: 21769 case value_t::discarded: 21770 default: 21771 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21772 } 21773 21774 return result; 21775 } 21776 21777 private: 21778 template < typename KeyType, detail::enable_if_t < 21779 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 21780 size_type erase_internal(KeyType && key) 21781 { 21782 // this erase only works for objects 21783 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21784 { 21785 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21786 } 21787 21788 return m_value.object->erase(std::forward<KeyType>(key)); 21789 } 21790 21791 template < typename KeyType, detail::enable_if_t < 21792 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 21793 size_type erase_internal(KeyType && key) 21794 { 21795 // this erase only works for objects 21796 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21797 { 21798 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21799 } 21800 21801 const auto it = m_value.object->find(std::forward<KeyType>(key)); 21802 if (it != m_value.object->end()) 21803 { 21804 m_value.object->erase(it); 21805 return 1; 21806 } 21807 return 0; 21808 } 21809 21810 public: 21811 21812 /// @brief remove element from a JSON object given a key 21813 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21814 size_type erase(const typename object_t::key_type& key) 21815 { 21816 // the indirection via erase_internal() is added to avoid making this 21817 // function a template and thus de-rank it during overload resolution 21818 return erase_internal(key); 21819 } 21820 21821 /// @brief remove element from a JSON object given a key 21822 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21823 template<class KeyType, detail::enable_if_t< 21824 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21825 size_type erase(KeyType && key) 21826 { 21827 return erase_internal(std::forward<KeyType>(key)); 21828 } 21829 21830 /// @brief remove element from a JSON array given an index 21831 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21832 void erase(const size_type idx) 21833 { 21834 // this erase only works for arrays 21835 if (JSON_HEDLEY_LIKELY(is_array())) 21836 { 21837 if (JSON_HEDLEY_UNLIKELY(idx >= size())) 21838 { 21839 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21840 } 21841 21842 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx)); 21843 } 21844 else 21845 { 21846 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21847 } 21848 } 21849 21850 /// @} 21851 21852 21853 //////////// 21854 // lookup // 21855 //////////// 21856 21857 /// @name lookup 21858 /// @{ 21859 21860 /// @brief find an element in a JSON object 21861 /// @sa https://json.nlohmann.me/api/basic_json/find/ 21862 iterator find(const typename object_t::key_type& key) 21863 { 21864 auto result = end(); 21865 21866 if (is_object()) 21867 { 21868 result.m_it.object_iterator = m_value.object->find(key); 21869 } 21870 21871 return result; 21872 } 21873 21874 /// @brief find an element in a JSON object 21875 /// @sa https://json.nlohmann.me/api/basic_json/find/ 21876 const_iterator find(const typename object_t::key_type& key) const 21877 { 21878 auto result = cend(); 21879 21880 if (is_object()) 21881 { 21882 result.m_it.object_iterator = m_value.object->find(key); 21883 } 21884 21885 return result; 21886 } 21887 21888 /// @brief find an element in a JSON object 21889 /// @sa https://json.nlohmann.me/api/basic_json/find/ 21890 template<class KeyType, detail::enable_if_t< 21891 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21892 iterator find(KeyType && key) 21893 { 21894 auto result = end(); 21895 21896 if (is_object()) 21897 { 21898 result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key)); 21899 } 21900 21901 return result; 21902 } 21903 21904 /// @brief find an element in a JSON object 21905 /// @sa https://json.nlohmann.me/api/basic_json/find/ 21906 template<class KeyType, detail::enable_if_t< 21907 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21908 const_iterator find(KeyType && key) const 21909 { 21910 auto result = cend(); 21911 21912 if (is_object()) 21913 { 21914 result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key)); 21915 } 21916 21917 return result; 21918 } 21919 21920 /// @brief returns the number of occurrences of a key in a JSON object 21921 /// @sa https://json.nlohmann.me/api/basic_json/count/ 21922 size_type count(const typename object_t::key_type& key) const 21923 { 21924 // return 0 for all nonobject types 21925 return is_object() ? m_value.object->count(key) : 0; 21926 } 21927 21928 /// @brief returns the number of occurrences of a key in a JSON object 21929 /// @sa https://json.nlohmann.me/api/basic_json/count/ 21930 template<class KeyType, detail::enable_if_t< 21931 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21932 size_type count(KeyType && key) const 21933 { 21934 // return 0 for all nonobject types 21935 return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0; 21936 } 21937 21938 /// @brief check the existence of an element in a JSON object 21939 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 21940 bool contains(const typename object_t::key_type& key) const 21941 { 21942 return is_object() && m_value.object->find(key) != m_value.object->end(); 21943 } 21944 21945 /// @brief check the existence of an element in a JSON object 21946 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 21947 template<class KeyType, detail::enable_if_t< 21948 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21949 bool contains(KeyType && key) const 21950 { 21951 return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end(); 21952 } 21953 21954 /// @brief check the existence of an element in a JSON object given a JSON pointer 21955 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 21956 bool contains(const json_pointer& ptr) const 21957 { 21958 return ptr.contains(this); 21959 } 21960 21961 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 21962 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 21963 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const 21964 { 21965 return ptr.contains(this); 21966 } 21967 21968 /// @} 21969 21970 21971 /////////////// 21972 // iterators // 21973 /////////////// 21974 21975 /// @name iterators 21976 /// @{ 21977 21978 /// @brief returns an iterator to the first element 21979 /// @sa https://json.nlohmann.me/api/basic_json/begin/ 21980 iterator begin() noexcept 21981 { 21982 iterator result(this); 21983 result.set_begin(); 21984 return result; 21985 } 21986 21987 /// @brief returns an iterator to the first element 21988 /// @sa https://json.nlohmann.me/api/basic_json/begin/ 21989 const_iterator begin() const noexcept 21990 { 21991 return cbegin(); 21992 } 21993 21994 /// @brief returns a const iterator to the first element 21995 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/ 21996 const_iterator cbegin() const noexcept 21997 { 21998 const_iterator result(this); 21999 result.set_begin(); 22000 return result; 22001 } 22002 22003 /// @brief returns an iterator to one past the last element 22004 /// @sa https://json.nlohmann.me/api/basic_json/end/ 22005 iterator end() noexcept 22006 { 22007 iterator result(this); 22008 result.set_end(); 22009 return result; 22010 } 22011 22012 /// @brief returns an iterator to one past the last element 22013 /// @sa https://json.nlohmann.me/api/basic_json/end/ 22014 const_iterator end() const noexcept 22015 { 22016 return cend(); 22017 } 22018 22019 /// @brief returns an iterator to one past the last element 22020 /// @sa https://json.nlohmann.me/api/basic_json/cend/ 22021 const_iterator cend() const noexcept 22022 { 22023 const_iterator result(this); 22024 result.set_end(); 22025 return result; 22026 } 22027 22028 /// @brief returns an iterator to the reverse-beginning 22029 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22030 reverse_iterator rbegin() noexcept 22031 { 22032 return reverse_iterator(end()); 22033 } 22034 22035 /// @brief returns an iterator to the reverse-beginning 22036 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22037 const_reverse_iterator rbegin() const noexcept 22038 { 22039 return crbegin(); 22040 } 22041 22042 /// @brief returns an iterator to the reverse-end 22043 /// @sa https://json.nlohmann.me/api/basic_json/rend/ 22044 reverse_iterator rend() noexcept 22045 { 22046 return reverse_iterator(begin()); 22047 } 22048 22049 /// @brief returns an iterator to the reverse-end 22050 /// @sa https://json.nlohmann.me/api/basic_json/rend/ 22051 const_reverse_iterator rend() const noexcept 22052 { 22053 return crend(); 22054 } 22055 22056 /// @brief returns a const reverse iterator to the last element 22057 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/ 22058 const_reverse_iterator crbegin() const noexcept 22059 { 22060 return const_reverse_iterator(cend()); 22061 } 22062 22063 /// @brief returns a const reverse iterator to one before the first 22064 /// @sa https://json.nlohmann.me/api/basic_json/crend/ 22065 const_reverse_iterator crend() const noexcept 22066 { 22067 return const_reverse_iterator(cbegin()); 22068 } 22069 22070 public: 22071 /// @brief wrapper to access iterator member functions in range-based for 22072 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22073 /// @deprecated This function is deprecated since 3.1.0 and will be removed in 22074 /// version 4.0.0 of the library. Please use @ref items() instead; 22075 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22076 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 22077 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept 22078 { 22079 return ref.items(); 22080 } 22081 22082 /// @brief wrapper to access iterator member functions in range-based for 22083 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22084 /// @deprecated This function is deprecated since 3.1.0 and will be removed in 22085 /// version 4.0.0 of the library. Please use @ref items() instead; 22086 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22087 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 22088 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept 22089 { 22090 return ref.items(); 22091 } 22092 22093 /// @brief helper to access iterator member functions in range-based for 22094 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22095 iteration_proxy<iterator> items() noexcept 22096 { 22097 return iteration_proxy<iterator>(*this); 22098 } 22099 22100 /// @brief helper to access iterator member functions in range-based for 22101 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22102 iteration_proxy<const_iterator> items() const noexcept 22103 { 22104 return iteration_proxy<const_iterator>(*this); 22105 } 22106 22107 /// @} 22108 22109 22110 ////////////// 22111 // capacity // 22112 ////////////// 22113 22114 /// @name capacity 22115 /// @{ 22116 22117 /// @brief checks whether the container is empty. 22118 /// @sa https://json.nlohmann.me/api/basic_json/empty/ 22119 bool empty() const noexcept 22120 { 22121 switch (m_type) 22122 { 22123 case value_t::null: 22124 { 22125 // null values are empty 22126 return true; 22127 } 22128 22129 case value_t::array: 22130 { 22131 // delegate call to array_t::empty() 22132 return m_value.array->empty(); 22133 } 22134 22135 case value_t::object: 22136 { 22137 // delegate call to object_t::empty() 22138 return m_value.object->empty(); 22139 } 22140 22141 case value_t::string: 22142 case value_t::boolean: 22143 case value_t::number_integer: 22144 case value_t::number_unsigned: 22145 case value_t::number_float: 22146 case value_t::binary: 22147 case value_t::discarded: 22148 default: 22149 { 22150 // all other types are nonempty 22151 return false; 22152 } 22153 } 22154 } 22155 22156 /// @brief returns the number of elements 22157 /// @sa https://json.nlohmann.me/api/basic_json/size/ 22158 size_type size() const noexcept 22159 { 22160 switch (m_type) 22161 { 22162 case value_t::null: 22163 { 22164 // null values are empty 22165 return 0; 22166 } 22167 22168 case value_t::array: 22169 { 22170 // delegate call to array_t::size() 22171 return m_value.array->size(); 22172 } 22173 22174 case value_t::object: 22175 { 22176 // delegate call to object_t::size() 22177 return m_value.object->size(); 22178 } 22179 22180 case value_t::string: 22181 case value_t::boolean: 22182 case value_t::number_integer: 22183 case value_t::number_unsigned: 22184 case value_t::number_float: 22185 case value_t::binary: 22186 case value_t::discarded: 22187 default: 22188 { 22189 // all other types have size 1 22190 return 1; 22191 } 22192 } 22193 } 22194 22195 /// @brief returns the maximum possible number of elements 22196 /// @sa https://json.nlohmann.me/api/basic_json/max_size/ 22197 size_type max_size() const noexcept 22198 { 22199 switch (m_type) 22200 { 22201 case value_t::array: 22202 { 22203 // delegate call to array_t::max_size() 22204 return m_value.array->max_size(); 22205 } 22206 22207 case value_t::object: 22208 { 22209 // delegate call to object_t::max_size() 22210 return m_value.object->max_size(); 22211 } 22212 22213 case value_t::null: 22214 case value_t::string: 22215 case value_t::boolean: 22216 case value_t::number_integer: 22217 case value_t::number_unsigned: 22218 case value_t::number_float: 22219 case value_t::binary: 22220 case value_t::discarded: 22221 default: 22222 { 22223 // all other types have max_size() == size() 22224 return size(); 22225 } 22226 } 22227 } 22228 22229 /// @} 22230 22231 22232 /////////////// 22233 // modifiers // 22234 /////////////// 22235 22236 /// @name modifiers 22237 /// @{ 22238 22239 /// @brief clears the contents 22240 /// @sa https://json.nlohmann.me/api/basic_json/clear/ 22241 void clear() noexcept 22242 { 22243 switch (m_type) 22244 { 22245 case value_t::number_integer: 22246 { 22247 m_value.number_integer = 0; 22248 break; 22249 } 22250 22251 case value_t::number_unsigned: 22252 { 22253 m_value.number_unsigned = 0; 22254 break; 22255 } 22256 22257 case value_t::number_float: 22258 { 22259 m_value.number_float = 0.0; 22260 break; 22261 } 22262 22263 case value_t::boolean: 22264 { 22265 m_value.boolean = false; 22266 break; 22267 } 22268 22269 case value_t::string: 22270 { 22271 m_value.string->clear(); 22272 break; 22273 } 22274 22275 case value_t::binary: 22276 { 22277 m_value.binary->clear(); 22278 break; 22279 } 22280 22281 case value_t::array: 22282 { 22283 m_value.array->clear(); 22284 break; 22285 } 22286 22287 case value_t::object: 22288 { 22289 m_value.object->clear(); 22290 break; 22291 } 22292 22293 case value_t::null: 22294 case value_t::discarded: 22295 default: 22296 break; 22297 } 22298 } 22299 22300 /// @brief add an object to an array 22301 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22302 void push_back(basic_json&& val) 22303 { 22304 // push_back only works for null objects or arrays 22305 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22306 { 22307 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22308 } 22309 22310 // transform null object into an array 22311 if (is_null()) 22312 { 22313 m_type = value_t::array; 22314 m_value = value_t::array; 22315 assert_invariant(); 22316 } 22317 22318 // add element to array (move semantics) 22319 const auto old_capacity = m_value.array->capacity(); 22320 m_value.array->push_back(std::move(val)); 22321 set_parent(m_value.array->back(), old_capacity); 22322 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor 22323 } 22324 22325 /// @brief add an object to an array 22326 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22327 reference operator+=(basic_json&& val) 22328 { 22329 push_back(std::move(val)); 22330 return *this; 22331 } 22332 22333 /// @brief add an object to an array 22334 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22335 void push_back(const basic_json& val) 22336 { 22337 // push_back only works for null objects or arrays 22338 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22339 { 22340 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22341 } 22342 22343 // transform null object into an array 22344 if (is_null()) 22345 { 22346 m_type = value_t::array; 22347 m_value = value_t::array; 22348 assert_invariant(); 22349 } 22350 22351 // add element to array 22352 const auto old_capacity = m_value.array->capacity(); 22353 m_value.array->push_back(val); 22354 set_parent(m_value.array->back(), old_capacity); 22355 } 22356 22357 /// @brief add an object to an array 22358 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22359 reference operator+=(const basic_json& val) 22360 { 22361 push_back(val); 22362 return *this; 22363 } 22364 22365 /// @brief add an object to an object 22366 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22367 void push_back(const typename object_t::value_type& val) 22368 { 22369 // push_back only works for null objects or objects 22370 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 22371 { 22372 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22373 } 22374 22375 // transform null object into an object 22376 if (is_null()) 22377 { 22378 m_type = value_t::object; 22379 m_value = value_t::object; 22380 assert_invariant(); 22381 } 22382 22383 // add element to object 22384 auto res = m_value.object->insert(val); 22385 set_parent(res.first->second); 22386 } 22387 22388 /// @brief add an object to an object 22389 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22390 reference operator+=(const typename object_t::value_type& val) 22391 { 22392 push_back(val); 22393 return *this; 22394 } 22395 22396 /// @brief add an object to an object 22397 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22398 void push_back(initializer_list_t init) 22399 { 22400 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) 22401 { 22402 basic_json&& key = init.begin()->moved_or_copied(); 22403 push_back(typename object_t::value_type( 22404 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied())); 22405 } 22406 else 22407 { 22408 push_back(basic_json(init)); 22409 } 22410 } 22411 22412 /// @brief add an object to an object 22413 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22414 reference operator+=(initializer_list_t init) 22415 { 22416 push_back(init); 22417 return *this; 22418 } 22419 22420 /// @brief add an object to an array 22421 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ 22422 template<class... Args> 22423 reference emplace_back(Args&& ... args) 22424 { 22425 // emplace_back only works for null objects or arrays 22426 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22427 { 22428 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this)); 22429 } 22430 22431 // transform null object into an array 22432 if (is_null()) 22433 { 22434 m_type = value_t::array; 22435 m_value = value_t::array; 22436 assert_invariant(); 22437 } 22438 22439 // add element to array (perfect forwarding) 22440 const auto old_capacity = m_value.array->capacity(); 22441 m_value.array->emplace_back(std::forward<Args>(args)...); 22442 return set_parent(m_value.array->back(), old_capacity); 22443 } 22444 22445 /// @brief add an object to an object if key does not exist 22446 /// @sa https://json.nlohmann.me/api/basic_json/emplace/ 22447 template<class... Args> 22448 std::pair<iterator, bool> emplace(Args&& ... args) 22449 { 22450 // emplace only works for null objects or arrays 22451 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 22452 { 22453 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this)); 22454 } 22455 22456 // transform null object into an object 22457 if (is_null()) 22458 { 22459 m_type = value_t::object; 22460 m_value = value_t::object; 22461 assert_invariant(); 22462 } 22463 22464 // add element to array (perfect forwarding) 22465 auto res = m_value.object->emplace(std::forward<Args>(args)...); 22466 set_parent(res.first->second); 22467 22468 // create result iterator and set iterator to the result of emplace 22469 auto it = begin(); 22470 it.m_it.object_iterator = res.first; 22471 22472 // return pair of iterator and boolean 22473 return {it, res.second}; 22474 } 22475 22476 /// Helper for insertion of an iterator 22477 /// @note: This uses std::distance to support GCC 4.8, 22478 /// see https://github.com/nlohmann/json/pull/1257 22479 template<typename... Args> 22480 iterator insert_iterator(const_iterator pos, Args&& ... args) 22481 { 22482 iterator result(this); 22483 JSON_ASSERT(m_value.array != nullptr); 22484 22485 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); 22486 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...); 22487 result.m_it.array_iterator = m_value.array->begin() + insert_pos; 22488 22489 // This could have been written as: 22490 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); 22491 // but the return value of insert is missing in GCC 4.8, so it is written this way instead. 22492 22493 set_parents(); 22494 return result; 22495 } 22496 22497 /// @brief inserts element into array 22498 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22499 iterator insert(const_iterator pos, const basic_json& val) 22500 { 22501 // insert only works for arrays 22502 if (JSON_HEDLEY_LIKELY(is_array())) 22503 { 22504 // check if iterator pos fits to this JSON value 22505 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22506 { 22507 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22508 } 22509 22510 // insert to array and return iterator 22511 return insert_iterator(pos, val); 22512 } 22513 22514 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22515 } 22516 22517 /// @brief inserts element into array 22518 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22519 iterator insert(const_iterator pos, basic_json&& val) 22520 { 22521 return insert(pos, val); 22522 } 22523 22524 /// @brief inserts copies of element into array 22525 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22526 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) 22527 { 22528 // insert only works for arrays 22529 if (JSON_HEDLEY_LIKELY(is_array())) 22530 { 22531 // check if iterator pos fits to this JSON value 22532 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22533 { 22534 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22535 } 22536 22537 // insert to array and return iterator 22538 return insert_iterator(pos, cnt, val); 22539 } 22540 22541 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22542 } 22543 22544 /// @brief inserts range of elements into array 22545 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22546 iterator insert(const_iterator pos, const_iterator first, const_iterator last) 22547 { 22548 // insert only works for arrays 22549 if (JSON_HEDLEY_UNLIKELY(!is_array())) 22550 { 22551 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22552 } 22553 22554 // check if iterator pos fits to this JSON value 22555 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22556 { 22557 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22558 } 22559 22560 // check if range iterators belong to the same JSON object 22561 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22562 { 22563 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22564 } 22565 22566 if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) 22567 { 22568 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this)); 22569 } 22570 22571 // insert to array and return iterator 22572 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); 22573 } 22574 22575 /// @brief inserts elements from initializer list into array 22576 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22577 iterator insert(const_iterator pos, initializer_list_t ilist) 22578 { 22579 // insert only works for arrays 22580 if (JSON_HEDLEY_UNLIKELY(!is_array())) 22581 { 22582 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22583 } 22584 22585 // check if iterator pos fits to this JSON value 22586 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22587 { 22588 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22589 } 22590 22591 // insert to array and return iterator 22592 return insert_iterator(pos, ilist.begin(), ilist.end()); 22593 } 22594 22595 /// @brief inserts range of elements into object 22596 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22597 void insert(const_iterator first, const_iterator last) 22598 { 22599 // insert only works for objects 22600 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22601 { 22602 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22603 } 22604 22605 // check if range iterators belong to the same JSON object 22606 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22607 { 22608 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22609 } 22610 22611 // passed iterators must belong to objects 22612 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 22613 { 22614 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); 22615 } 22616 22617 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); 22618 } 22619 22620 /// @brief updates a JSON object from another object, overwriting existing keys 22621 /// @sa https://json.nlohmann.me/api/basic_json/update/ 22622 void update(const_reference j, bool merge_objects = false) 22623 { 22624 update(j.begin(), j.end(), merge_objects); 22625 } 22626 22627 /// @brief updates a JSON object from another object, overwriting existing keys 22628 /// @sa https://json.nlohmann.me/api/basic_json/update/ 22629 void update(const_iterator first, const_iterator last, bool merge_objects = false) 22630 { 22631 // implicitly convert null value to an empty object 22632 if (is_null()) 22633 { 22634 m_type = value_t::object; 22635 m_value.object = create<object_t>(); 22636 assert_invariant(); 22637 } 22638 22639 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22640 { 22641 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this)); 22642 } 22643 22644 // check if range iterators belong to the same JSON object 22645 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22646 { 22647 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22648 } 22649 22650 // passed iterators must belong to objects 22651 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 22652 { 22653 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object)); 22654 } 22655 22656 for (auto it = first; it != last; ++it) 22657 { 22658 if (merge_objects && it.value().is_object()) 22659 { 22660 auto it2 = m_value.object->find(it.key()); 22661 if (it2 != m_value.object->end()) 22662 { 22663 it2->second.update(it.value(), true); 22664 continue; 22665 } 22666 } 22667 m_value.object->operator[](it.key()) = it.value(); 22668 #if JSON_DIAGNOSTICS 22669 m_value.object->operator[](it.key()).m_parent = this; 22670 #endif 22671 } 22672 } 22673 22674 /// @brief exchanges the values 22675 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22676 void swap(reference other) noexcept ( 22677 std::is_nothrow_move_constructible<value_t>::value&& 22678 std::is_nothrow_move_assignable<value_t>::value&& 22679 std::is_nothrow_move_constructible<json_value>::value&& 22680 std::is_nothrow_move_assignable<json_value>::value 22681 ) 22682 { 22683 std::swap(m_type, other.m_type); 22684 std::swap(m_value, other.m_value); 22685 22686 set_parents(); 22687 other.set_parents(); 22688 assert_invariant(); 22689 } 22690 22691 /// @brief exchanges the values 22692 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22693 friend void swap(reference left, reference right) noexcept ( 22694 std::is_nothrow_move_constructible<value_t>::value&& 22695 std::is_nothrow_move_assignable<value_t>::value&& 22696 std::is_nothrow_move_constructible<json_value>::value&& 22697 std::is_nothrow_move_assignable<json_value>::value 22698 ) 22699 { 22700 left.swap(right); 22701 } 22702 22703 /// @brief exchanges the values 22704 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22705 void swap(array_t& other) // NOLINT(bugprone-exception-escape) 22706 { 22707 // swap only works for arrays 22708 if (JSON_HEDLEY_LIKELY(is_array())) 22709 { 22710 using std::swap; 22711 swap(*(m_value.array), other); 22712 } 22713 else 22714 { 22715 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this)); 22716 } 22717 } 22718 22719 /// @brief exchanges the values 22720 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22721 void swap(object_t& other) // NOLINT(bugprone-exception-escape) 22722 { 22723 // swap only works for objects 22724 if (JSON_HEDLEY_LIKELY(is_object())) 22725 { 22726 using std::swap; 22727 swap(*(m_value.object), other); 22728 } 22729 else 22730 { 22731 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this)); 22732 } 22733 } 22734 22735 /// @brief exchanges the values 22736 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22737 void swap(string_t& other) // NOLINT(bugprone-exception-escape) 22738 { 22739 // swap only works for strings 22740 if (JSON_HEDLEY_LIKELY(is_string())) 22741 { 22742 using std::swap; 22743 swap(*(m_value.string), other); 22744 } 22745 else 22746 { 22747 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this)); 22748 } 22749 } 22750 22751 /// @brief exchanges the values 22752 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22753 void swap(binary_t& other) // NOLINT(bugprone-exception-escape) 22754 { 22755 // swap only works for strings 22756 if (JSON_HEDLEY_LIKELY(is_binary())) 22757 { 22758 using std::swap; 22759 swap(*(m_value.binary), other); 22760 } 22761 else 22762 { 22763 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this)); 22764 } 22765 } 22766 22767 /// @brief exchanges the values 22768 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22769 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) 22770 { 22771 // swap only works for strings 22772 if (JSON_HEDLEY_LIKELY(is_binary())) 22773 { 22774 using std::swap; 22775 swap(*(m_value.binary), other); 22776 } 22777 else 22778 { 22779 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this)); 22780 } 22781 } 22782 22783 /// @} 22784 22785 ////////////////////////////////////////// 22786 // lexicographical comparison operators // 22787 ////////////////////////////////////////// 22788 22789 /// @name lexicographical comparison operators 22790 /// @{ 22791 22792 // note parentheses around operands are necessary; see 22793 // https://github.com/nlohmann/json/issues/1530 22794 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \ 22795 const auto lhs_type = lhs.type(); \ 22796 const auto rhs_type = rhs.type(); \ 22797 \ 22798 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \ 22799 { \ 22800 switch (lhs_type) \ 22801 { \ 22802 case value_t::array: \ 22803 return (*lhs.m_value.array) op (*rhs.m_value.array); \ 22804 \ 22805 case value_t::object: \ 22806 return (*lhs.m_value.object) op (*rhs.m_value.object); \ 22807 \ 22808 case value_t::null: \ 22809 return (null_result); \ 22810 \ 22811 case value_t::string: \ 22812 return (*lhs.m_value.string) op (*rhs.m_value.string); \ 22813 \ 22814 case value_t::boolean: \ 22815 return (lhs.m_value.boolean) op (rhs.m_value.boolean); \ 22816 \ 22817 case value_t::number_integer: \ 22818 return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \ 22819 \ 22820 case value_t::number_unsigned: \ 22821 return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \ 22822 \ 22823 case value_t::number_float: \ 22824 return (lhs.m_value.number_float) op (rhs.m_value.number_float); \ 22825 \ 22826 case value_t::binary: \ 22827 return (*lhs.m_value.binary) op (*rhs.m_value.binary); \ 22828 \ 22829 case value_t::discarded: \ 22830 default: \ 22831 return (unordered_result); \ 22832 } \ 22833 } \ 22834 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ 22835 { \ 22836 return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float; \ 22837 } \ 22838 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ 22839 { \ 22840 return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer); \ 22841 } \ 22842 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ 22843 { \ 22844 return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \ 22845 } \ 22846 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ 22847 { \ 22848 return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned); \ 22849 } \ 22850 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ 22851 { \ 22852 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \ 22853 } \ 22854 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ 22855 { \ 22856 return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \ 22857 } \ 22858 else if(compares_unordered(lhs, rhs))\ 22859 {\ 22860 return (unordered_result);\ 22861 }\ 22862 \ 22863 return (default_result); 22864 22865 JSON_PRIVATE_UNLESS_TESTED: 22866 // returns true if: 22867 // - any operand is NaN and the other operand is of number type 22868 // - any operand is discarded 22869 // in legacy mode, discarded values are considered ordered if 22870 // an operation is computed as an odd number of inverses of others 22871 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept 22872 { 22873 if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number()) 22874 || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number())) 22875 { 22876 return true; 22877 } 22878 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 22879 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse; 22880 #else 22881 static_cast<void>(inverse); 22882 return lhs.is_discarded() || rhs.is_discarded(); 22883 #endif 22884 } 22885 22886 private: 22887 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept 22888 { 22889 return compares_unordered(*this, rhs, inverse); 22890 } 22891 22892 public: 22893 #if JSON_HAS_THREE_WAY_COMPARISON 22894 /// @brief comparison: equal 22895 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 22896 bool operator==(const_reference rhs) const noexcept 22897 { 22898 #ifdef __GNUC__ 22899 #pragma GCC diagnostic push 22900 #pragma GCC diagnostic ignored "-Wfloat-equal" 22901 #endif 22902 const_reference lhs = *this; 22903 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 22904 #ifdef __GNUC__ 22905 #pragma GCC diagnostic pop 22906 #endif 22907 } 22908 22909 /// @brief comparison: equal 22910 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 22911 template<typename ScalarType> 22912 requires std::is_scalar_v<ScalarType> 22913 bool operator==(ScalarType rhs) const noexcept 22914 { 22915 return *this == basic_json(rhs); 22916 } 22917 22918 /// @brief comparison: not equal 22919 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 22920 bool operator!=(const_reference rhs) const noexcept 22921 { 22922 if (compares_unordered(rhs, true)) 22923 { 22924 return false; 22925 } 22926 return !operator==(rhs); 22927 } 22928 22929 /// @brief comparison: 3-way 22930 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 22931 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD* 22932 { 22933 const_reference lhs = *this; 22934 // default_result is used if we cannot compare values. In that case, 22935 // we compare types. 22936 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD* 22937 std::partial_ordering::equivalent, 22938 std::partial_ordering::unordered, 22939 lhs_type <=> rhs_type) // *NOPAD* 22940 } 22941 22942 /// @brief comparison: 3-way 22943 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 22944 template<typename ScalarType> 22945 requires std::is_scalar_v<ScalarType> 22946 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD* 22947 { 22948 return *this <=> basic_json(rhs); // *NOPAD* 22949 } 22950 22951 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 22952 // all operators that are computed as an odd number of inverses of others 22953 // need to be overloaded to emulate the legacy comparison behavior 22954 22955 /// @brief comparison: less than or equal 22956 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 22957 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 22958 bool operator<=(const_reference rhs) const noexcept 22959 { 22960 if (compares_unordered(rhs, true)) 22961 { 22962 return false; 22963 } 22964 return !(rhs < *this); 22965 } 22966 22967 /// @brief comparison: less than or equal 22968 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 22969 template<typename ScalarType> 22970 requires std::is_scalar_v<ScalarType> 22971 bool operator<=(ScalarType rhs) const noexcept 22972 { 22973 return *this <= basic_json(rhs); 22974 } 22975 22976 /// @brief comparison: greater than or equal 22977 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 22978 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 22979 bool operator>=(const_reference rhs) const noexcept 22980 { 22981 if (compares_unordered(rhs, true)) 22982 { 22983 return false; 22984 } 22985 return !(*this < rhs); 22986 } 22987 22988 /// @brief comparison: greater than or equal 22989 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 22990 template<typename ScalarType> 22991 requires std::is_scalar_v<ScalarType> 22992 bool operator>=(ScalarType rhs) const noexcept 22993 { 22994 return *this >= basic_json(rhs); 22995 } 22996 #endif 22997 #else 22998 /// @brief comparison: equal 22999 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23000 friend bool operator==(const_reference lhs, const_reference rhs) noexcept 23001 { 23002 #ifdef __GNUC__ 23003 #pragma GCC diagnostic push 23004 #pragma GCC diagnostic ignored "-Wfloat-equal" 23005 #endif 23006 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 23007 #ifdef __GNUC__ 23008 #pragma GCC diagnostic pop 23009 #endif 23010 } 23011 23012 /// @brief comparison: equal 23013 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23014 template<typename ScalarType, typename std::enable_if< 23015 std::is_scalar<ScalarType>::value, int>::type = 0> 23016 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept 23017 { 23018 return lhs == basic_json(rhs); 23019 } 23020 23021 /// @brief comparison: equal 23022 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23023 template<typename ScalarType, typename std::enable_if< 23024 std::is_scalar<ScalarType>::value, int>::type = 0> 23025 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept 23026 { 23027 return basic_json(lhs) == rhs; 23028 } 23029 23030 /// @brief comparison: not equal 23031 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23032 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept 23033 { 23034 if (compares_unordered(lhs, rhs, true)) 23035 { 23036 return false; 23037 } 23038 return !(lhs == rhs); 23039 } 23040 23041 /// @brief comparison: not equal 23042 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23043 template<typename ScalarType, typename std::enable_if< 23044 std::is_scalar<ScalarType>::value, int>::type = 0> 23045 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept 23046 { 23047 return lhs != basic_json(rhs); 23048 } 23049 23050 /// @brief comparison: not equal 23051 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23052 template<typename ScalarType, typename std::enable_if< 23053 std::is_scalar<ScalarType>::value, int>::type = 0> 23054 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept 23055 { 23056 return basic_json(lhs) != rhs; 23057 } 23058 23059 /// @brief comparison: less than 23060 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23061 friend bool operator<(const_reference lhs, const_reference rhs) noexcept 23062 { 23063 // default_result is used if we cannot compare values. In that case, 23064 // we compare types. Note we have to call the operator explicitly, 23065 // because MSVC has problems otherwise. 23066 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type)) 23067 } 23068 23069 /// @brief comparison: less than 23070 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23071 template<typename ScalarType, typename std::enable_if< 23072 std::is_scalar<ScalarType>::value, int>::type = 0> 23073 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept 23074 { 23075 return lhs < basic_json(rhs); 23076 } 23077 23078 /// @brief comparison: less than 23079 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23080 template<typename ScalarType, typename std::enable_if< 23081 std::is_scalar<ScalarType>::value, int>::type = 0> 23082 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept 23083 { 23084 return basic_json(lhs) < rhs; 23085 } 23086 23087 /// @brief comparison: less than or equal 23088 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23089 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept 23090 { 23091 if (compares_unordered(lhs, rhs, true)) 23092 { 23093 return false; 23094 } 23095 return !(rhs < lhs); 23096 } 23097 23098 /// @brief comparison: less than or equal 23099 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23100 template<typename ScalarType, typename std::enable_if< 23101 std::is_scalar<ScalarType>::value, int>::type = 0> 23102 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept 23103 { 23104 return lhs <= basic_json(rhs); 23105 } 23106 23107 /// @brief comparison: less than or equal 23108 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23109 template<typename ScalarType, typename std::enable_if< 23110 std::is_scalar<ScalarType>::value, int>::type = 0> 23111 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept 23112 { 23113 return basic_json(lhs) <= rhs; 23114 } 23115 23116 /// @brief comparison: greater than 23117 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23118 friend bool operator>(const_reference lhs, const_reference rhs) noexcept 23119 { 23120 // double inverse 23121 if (compares_unordered(lhs, rhs)) 23122 { 23123 return false; 23124 } 23125 return !(lhs <= rhs); 23126 } 23127 23128 /// @brief comparison: greater than 23129 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23130 template<typename ScalarType, typename std::enable_if< 23131 std::is_scalar<ScalarType>::value, int>::type = 0> 23132 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept 23133 { 23134 return lhs > basic_json(rhs); 23135 } 23136 23137 /// @brief comparison: greater than 23138 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23139 template<typename ScalarType, typename std::enable_if< 23140 std::is_scalar<ScalarType>::value, int>::type = 0> 23141 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept 23142 { 23143 return basic_json(lhs) > rhs; 23144 } 23145 23146 /// @brief comparison: greater than or equal 23147 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23148 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept 23149 { 23150 if (compares_unordered(lhs, rhs, true)) 23151 { 23152 return false; 23153 } 23154 return !(lhs < rhs); 23155 } 23156 23157 /// @brief comparison: greater than or equal 23158 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23159 template<typename ScalarType, typename std::enable_if< 23160 std::is_scalar<ScalarType>::value, int>::type = 0> 23161 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept 23162 { 23163 return lhs >= basic_json(rhs); 23164 } 23165 23166 /// @brief comparison: greater than or equal 23167 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23168 template<typename ScalarType, typename std::enable_if< 23169 std::is_scalar<ScalarType>::value, int>::type = 0> 23170 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept 23171 { 23172 return basic_json(lhs) >= rhs; 23173 } 23174 #endif 23175 23176 #undef JSON_IMPLEMENT_OPERATOR 23177 23178 /// @} 23179 23180 /////////////////// 23181 // serialization // 23182 /////////////////// 23183 23184 /// @name serialization 23185 /// @{ 23186 #ifndef JSON_NO_IO 23187 /// @brief serialize to stream 23188 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 23189 friend std::ostream& operator<<(std::ostream& o, const basic_json& j) 23190 { 23191 // read width member and use it as indentation parameter if nonzero 23192 const bool pretty_print = o.width() > 0; 23193 const auto indentation = pretty_print ? o.width() : 0; 23194 23195 // reset width to 0 for subsequent calls to this stream 23196 o.width(0); 23197 23198 // do the actual serialization 23199 serializer s(detail::output_adapter<char>(o), o.fill()); 23200 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation)); 23201 return o; 23202 } 23203 23204 /// @brief serialize to stream 23205 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 23206 /// @deprecated This function is deprecated since 3.0.0 and will be removed in 23207 /// version 4.0.0 of the library. Please use 23208 /// operator<<(std::ostream&, const basic_json&) instead; that is, 23209 /// replace calls like `j >> o;` with `o << j;`. 23210 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) 23211 friend std::ostream& operator>>(const basic_json& j, std::ostream& o) 23212 { 23213 return o << j; 23214 } 23215 #endif // JSON_NO_IO 23216 /// @} 23217 23218 23219 ///////////////////// 23220 // deserialization // 23221 ///////////////////// 23222 23223 /// @name deserialization 23224 /// @{ 23225 23226 /// @brief deserialize from a compatible input 23227 /// @sa https://json.nlohmann.me/api/basic_json/parse/ 23228 template<typename InputType> 23229 JSON_HEDLEY_WARN_UNUSED_RESULT 23230 static basic_json parse(InputType&& i, 23231 const parser_callback_t cb = nullptr, 23232 const bool allow_exceptions = true, 23233 const bool ignore_comments = false) 23234 { 23235 basic_json result; 23236 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result); 23237 return result; 23238 } 23239 23240 /// @brief deserialize from a pair of character iterators 23241 /// @sa https://json.nlohmann.me/api/basic_json/parse/ 23242 template<typename IteratorType> 23243 JSON_HEDLEY_WARN_UNUSED_RESULT 23244 static basic_json parse(IteratorType first, 23245 IteratorType last, 23246 const parser_callback_t cb = nullptr, 23247 const bool allow_exceptions = true, 23248 const bool ignore_comments = false) 23249 { 23250 basic_json result; 23251 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); 23252 return result; 23253 } 23254 23255 JSON_HEDLEY_WARN_UNUSED_RESULT 23256 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) 23257 static basic_json parse(detail::span_input_adapter&& i, 23258 const parser_callback_t cb = nullptr, 23259 const bool allow_exceptions = true, 23260 const bool ignore_comments = false) 23261 { 23262 basic_json result; 23263 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); 23264 return result; 23265 } 23266 23267 /// @brief check if the input is valid JSON 23268 /// @sa https://json.nlohmann.me/api/basic_json/accept/ 23269 template<typename InputType> 23270 static bool accept(InputType&& i, 23271 const bool ignore_comments = false) 23272 { 23273 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true); 23274 } 23275 23276 /// @brief check if the input is valid JSON 23277 /// @sa https://json.nlohmann.me/api/basic_json/accept/ 23278 template<typename IteratorType> 23279 static bool accept(IteratorType first, IteratorType last, 23280 const bool ignore_comments = false) 23281 { 23282 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); 23283 } 23284 23285 JSON_HEDLEY_WARN_UNUSED_RESULT 23286 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) 23287 static bool accept(detail::span_input_adapter&& i, 23288 const bool ignore_comments = false) 23289 { 23290 return parser(i.get(), nullptr, false, ignore_comments).accept(true); 23291 } 23292 23293 /// @brief generate SAX events 23294 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23295 template <typename InputType, typename SAX> 23296 JSON_HEDLEY_NON_NULL(2) 23297 static bool sax_parse(InputType&& i, SAX* sax, 23298 input_format_t format = input_format_t::json, 23299 const bool strict = true, 23300 const bool ignore_comments = false) 23301 { 23302 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23303 return format == input_format_t::json 23304 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23305 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23306 } 23307 23308 /// @brief generate SAX events 23309 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23310 template<class IteratorType, class SAX> 23311 JSON_HEDLEY_NON_NULL(3) 23312 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, 23313 input_format_t format = input_format_t::json, 23314 const bool strict = true, 23315 const bool ignore_comments = false) 23316 { 23317 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23318 return format == input_format_t::json 23319 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23320 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23321 } 23322 23323 /// @brief generate SAX events 23324 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23325 /// @deprecated This function is deprecated since 3.8.0 and will be removed in 23326 /// version 4.0.0 of the library. Please use 23327 /// sax_parse(ptr, ptr + len) instead. 23328 template <typename SAX> 23329 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) 23330 JSON_HEDLEY_NON_NULL(2) 23331 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, 23332 input_format_t format = input_format_t::json, 23333 const bool strict = true, 23334 const bool ignore_comments = false) 23335 { 23336 auto ia = i.get(); 23337 return format == input_format_t::json 23338 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23339 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23340 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23341 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23342 } 23343 #ifndef JSON_NO_IO 23344 /// @brief deserialize from stream 23345 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 23346 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in 23347 /// version 4.0.0 of the library. Please use 23348 /// operator>>(std::istream&, basic_json&) instead; that is, 23349 /// replace calls like `j << i;` with `i >> j;`. 23350 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) 23351 friend std::istream& operator<<(basic_json& j, std::istream& i) 23352 { 23353 return operator>>(i, j); 23354 } 23355 23356 /// @brief deserialize from stream 23357 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 23358 friend std::istream& operator>>(std::istream& i, basic_json& j) 23359 { 23360 parser(detail::input_adapter(i)).parse(false, j); 23361 return i; 23362 } 23363 #endif // JSON_NO_IO 23364 /// @} 23365 23366 /////////////////////////// 23367 // convenience functions // 23368 /////////////////////////// 23369 23370 /// @brief return the type as string 23371 /// @sa https://json.nlohmann.me/api/basic_json/type_name/ 23372 JSON_HEDLEY_RETURNS_NON_NULL 23373 const char* type_name() const noexcept 23374 { 23375 switch (m_type) 23376 { 23377 case value_t::null: 23378 return "null"; 23379 case value_t::object: 23380 return "object"; 23381 case value_t::array: 23382 return "array"; 23383 case value_t::string: 23384 return "string"; 23385 case value_t::boolean: 23386 return "boolean"; 23387 case value_t::binary: 23388 return "binary"; 23389 case value_t::discarded: 23390 return "discarded"; 23391 case value_t::number_integer: 23392 case value_t::number_unsigned: 23393 case value_t::number_float: 23394 default: 23395 return "number"; 23396 } 23397 } 23398 23399 23400 JSON_PRIVATE_UNLESS_TESTED: 23401 ////////////////////// 23402 // member variables // 23403 ////////////////////// 23404 23405 /// the type of the current element 23406 value_t m_type = value_t::null; 23407 23408 /// the value of the current element 23409 json_value m_value = {}; 23410 23411 #if JSON_DIAGNOSTICS 23412 /// a pointer to a parent value (for debugging purposes) 23413 basic_json* m_parent = nullptr; 23414 #endif 23415 23416 ////////////////////////////////////////// 23417 // binary serialization/deserialization // 23418 ////////////////////////////////////////// 23419 23420 /// @name binary serialization/deserialization support 23421 /// @{ 23422 23423 public: 23424 /// @brief create a CBOR serialization of a given JSON value 23425 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23426 static std::vector<std::uint8_t> to_cbor(const basic_json& j) 23427 { 23428 std::vector<std::uint8_t> result; 23429 to_cbor(j, result); 23430 return result; 23431 } 23432 23433 /// @brief create a CBOR serialization of a given JSON value 23434 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23435 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23436 { 23437 binary_writer<std::uint8_t>(o).write_cbor(j); 23438 } 23439 23440 /// @brief create a CBOR serialization of a given JSON value 23441 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23442 static void to_cbor(const basic_json& j, detail::output_adapter<char> o) 23443 { 23444 binary_writer<char>(o).write_cbor(j); 23445 } 23446 23447 /// @brief create a MessagePack serialization of a given JSON value 23448 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23449 static std::vector<std::uint8_t> to_msgpack(const basic_json& j) 23450 { 23451 std::vector<std::uint8_t> result; 23452 to_msgpack(j, result); 23453 return result; 23454 } 23455 23456 /// @brief create a MessagePack serialization of a given JSON value 23457 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23458 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23459 { 23460 binary_writer<std::uint8_t>(o).write_msgpack(j); 23461 } 23462 23463 /// @brief create a MessagePack serialization of a given JSON value 23464 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23465 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) 23466 { 23467 binary_writer<char>(o).write_msgpack(j); 23468 } 23469 23470 /// @brief create a UBJSON serialization of a given JSON value 23471 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23472 static std::vector<std::uint8_t> to_ubjson(const basic_json& j, 23473 const bool use_size = false, 23474 const bool use_type = false) 23475 { 23476 std::vector<std::uint8_t> result; 23477 to_ubjson(j, result, use_size, use_type); 23478 return result; 23479 } 23480 23481 /// @brief create a UBJSON serialization of a given JSON value 23482 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23483 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o, 23484 const bool use_size = false, const bool use_type = false) 23485 { 23486 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type); 23487 } 23488 23489 /// @brief create a UBJSON serialization of a given JSON value 23490 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23491 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, 23492 const bool use_size = false, const bool use_type = false) 23493 { 23494 binary_writer<char>(o).write_ubjson(j, use_size, use_type); 23495 } 23496 23497 /// @brief create a BJData serialization of a given JSON value 23498 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23499 static std::vector<std::uint8_t> to_bjdata(const basic_json& j, 23500 const bool use_size = false, 23501 const bool use_type = false) 23502 { 23503 std::vector<std::uint8_t> result; 23504 to_bjdata(j, result, use_size, use_type); 23505 return result; 23506 } 23507 23508 /// @brief create a BJData serialization of a given JSON value 23509 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23510 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, 23511 const bool use_size = false, const bool use_type = false) 23512 { 23513 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true); 23514 } 23515 23516 /// @brief create a BJData serialization of a given JSON value 23517 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23518 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, 23519 const bool use_size = false, const bool use_type = false) 23520 { 23521 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true); 23522 } 23523 23524 /// @brief create a BSON serialization of a given JSON value 23525 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23526 static std::vector<std::uint8_t> to_bson(const basic_json& j) 23527 { 23528 std::vector<std::uint8_t> result; 23529 to_bson(j, result); 23530 return result; 23531 } 23532 23533 /// @brief create a BSON serialization of a given JSON value 23534 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23535 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23536 { 23537 binary_writer<std::uint8_t>(o).write_bson(j); 23538 } 23539 23540 /// @brief create a BSON serialization of a given JSON value 23541 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23542 static void to_bson(const basic_json& j, detail::output_adapter<char> o) 23543 { 23544 binary_writer<char>(o).write_bson(j); 23545 } 23546 23547 /// @brief create a JSON value from an input in CBOR format 23548 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 23549 template<typename InputType> 23550 JSON_HEDLEY_WARN_UNUSED_RESULT 23551 static basic_json from_cbor(InputType&& i, 23552 const bool strict = true, 23553 const bool allow_exceptions = true, 23554 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23555 { 23556 basic_json result; 23557 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23558 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23559 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23560 return res ? result : basic_json(value_t::discarded); 23561 } 23562 23563 /// @brief create a JSON value from an input in CBOR format 23564 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 23565 template<typename IteratorType> 23566 JSON_HEDLEY_WARN_UNUSED_RESULT 23567 static basic_json from_cbor(IteratorType first, IteratorType last, 23568 const bool strict = true, 23569 const bool allow_exceptions = true, 23570 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23571 { 23572 basic_json result; 23573 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23574 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23575 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23576 return res ? result : basic_json(value_t::discarded); 23577 } 23578 23579 template<typename T> 23580 JSON_HEDLEY_WARN_UNUSED_RESULT 23581 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 23582 static basic_json from_cbor(const T* ptr, std::size_t len, 23583 const bool strict = true, 23584 const bool allow_exceptions = true, 23585 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23586 { 23587 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); 23588 } 23589 23590 23591 JSON_HEDLEY_WARN_UNUSED_RESULT 23592 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 23593 static basic_json from_cbor(detail::span_input_adapter&& i, 23594 const bool strict = true, 23595 const bool allow_exceptions = true, 23596 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23597 { 23598 basic_json result; 23599 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23600 auto ia = i.get(); 23601 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23602 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23603 return res ? result : basic_json(value_t::discarded); 23604 } 23605 23606 /// @brief create a JSON value from an input in MessagePack format 23607 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 23608 template<typename InputType> 23609 JSON_HEDLEY_WARN_UNUSED_RESULT 23610 static basic_json from_msgpack(InputType&& i, 23611 const bool strict = true, 23612 const bool allow_exceptions = true) 23613 { 23614 basic_json result; 23615 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23616 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23617 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23618 return res ? result : basic_json(value_t::discarded); 23619 } 23620 23621 /// @brief create a JSON value from an input in MessagePack format 23622 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 23623 template<typename IteratorType> 23624 JSON_HEDLEY_WARN_UNUSED_RESULT 23625 static basic_json from_msgpack(IteratorType first, IteratorType last, 23626 const bool strict = true, 23627 const bool allow_exceptions = true) 23628 { 23629 basic_json result; 23630 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23631 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23632 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23633 return res ? result : basic_json(value_t::discarded); 23634 } 23635 23636 template<typename T> 23637 JSON_HEDLEY_WARN_UNUSED_RESULT 23638 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 23639 static basic_json from_msgpack(const T* ptr, std::size_t len, 23640 const bool strict = true, 23641 const bool allow_exceptions = true) 23642 { 23643 return from_msgpack(ptr, ptr + len, strict, allow_exceptions); 23644 } 23645 23646 JSON_HEDLEY_WARN_UNUSED_RESULT 23647 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 23648 static basic_json from_msgpack(detail::span_input_adapter&& i, 23649 const bool strict = true, 23650 const bool allow_exceptions = true) 23651 { 23652 basic_json result; 23653 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23654 auto ia = i.get(); 23655 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23656 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23657 return res ? result : basic_json(value_t::discarded); 23658 } 23659 23660 /// @brief create a JSON value from an input in UBJSON format 23661 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 23662 template<typename InputType> 23663 JSON_HEDLEY_WARN_UNUSED_RESULT 23664 static basic_json from_ubjson(InputType&& i, 23665 const bool strict = true, 23666 const bool allow_exceptions = true) 23667 { 23668 basic_json result; 23669 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23670 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23671 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23672 return res ? result : basic_json(value_t::discarded); 23673 } 23674 23675 /// @brief create a JSON value from an input in UBJSON format 23676 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 23677 template<typename IteratorType> 23678 JSON_HEDLEY_WARN_UNUSED_RESULT 23679 static basic_json from_ubjson(IteratorType first, IteratorType last, 23680 const bool strict = true, 23681 const bool allow_exceptions = true) 23682 { 23683 basic_json result; 23684 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23685 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23686 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23687 return res ? result : basic_json(value_t::discarded); 23688 } 23689 23690 template<typename T> 23691 JSON_HEDLEY_WARN_UNUSED_RESULT 23692 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 23693 static basic_json from_ubjson(const T* ptr, std::size_t len, 23694 const bool strict = true, 23695 const bool allow_exceptions = true) 23696 { 23697 return from_ubjson(ptr, ptr + len, strict, allow_exceptions); 23698 } 23699 23700 JSON_HEDLEY_WARN_UNUSED_RESULT 23701 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 23702 static basic_json from_ubjson(detail::span_input_adapter&& i, 23703 const bool strict = true, 23704 const bool allow_exceptions = true) 23705 { 23706 basic_json result; 23707 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23708 auto ia = i.get(); 23709 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23710 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23711 return res ? result : basic_json(value_t::discarded); 23712 } 23713 23714 23715 /// @brief create a JSON value from an input in BJData format 23716 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 23717 template<typename InputType> 23718 JSON_HEDLEY_WARN_UNUSED_RESULT 23719 static basic_json from_bjdata(InputType&& i, 23720 const bool strict = true, 23721 const bool allow_exceptions = true) 23722 { 23723 basic_json result; 23724 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23725 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23726 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 23727 return res ? result : basic_json(value_t::discarded); 23728 } 23729 23730 /// @brief create a JSON value from an input in BJData format 23731 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 23732 template<typename IteratorType> 23733 JSON_HEDLEY_WARN_UNUSED_RESULT 23734 static basic_json from_bjdata(IteratorType first, IteratorType last, 23735 const bool strict = true, 23736 const bool allow_exceptions = true) 23737 { 23738 basic_json result; 23739 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23740 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23741 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 23742 return res ? result : basic_json(value_t::discarded); 23743 } 23744 23745 /// @brief create a JSON value from an input in BSON format 23746 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 23747 template<typename InputType> 23748 JSON_HEDLEY_WARN_UNUSED_RESULT 23749 static basic_json from_bson(InputType&& i, 23750 const bool strict = true, 23751 const bool allow_exceptions = true) 23752 { 23753 basic_json result; 23754 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23755 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23756 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 23757 return res ? result : basic_json(value_t::discarded); 23758 } 23759 23760 /// @brief create a JSON value from an input in BSON format 23761 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 23762 template<typename IteratorType> 23763 JSON_HEDLEY_WARN_UNUSED_RESULT 23764 static basic_json from_bson(IteratorType first, IteratorType last, 23765 const bool strict = true, 23766 const bool allow_exceptions = true) 23767 { 23768 basic_json result; 23769 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23770 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23771 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 23772 return res ? result : basic_json(value_t::discarded); 23773 } 23774 23775 template<typename T> 23776 JSON_HEDLEY_WARN_UNUSED_RESULT 23777 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 23778 static basic_json from_bson(const T* ptr, std::size_t len, 23779 const bool strict = true, 23780 const bool allow_exceptions = true) 23781 { 23782 return from_bson(ptr, ptr + len, strict, allow_exceptions); 23783 } 23784 23785 JSON_HEDLEY_WARN_UNUSED_RESULT 23786 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 23787 static basic_json from_bson(detail::span_input_adapter&& i, 23788 const bool strict = true, 23789 const bool allow_exceptions = true) 23790 { 23791 basic_json result; 23792 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23793 auto ia = i.get(); 23794 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23795 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 23796 return res ? result : basic_json(value_t::discarded); 23797 } 23798 /// @} 23799 23800 ////////////////////////// 23801 // JSON Pointer support // 23802 ////////////////////////// 23803 23804 /// @name JSON Pointer functions 23805 /// @{ 23806 23807 /// @brief access specified element via JSON Pointer 23808 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 23809 reference operator[](const json_pointer& ptr) 23810 { 23811 return ptr.get_unchecked(this); 23812 } 23813 23814 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23815 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23816 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) 23817 { 23818 return ptr.get_unchecked(this); 23819 } 23820 23821 /// @brief access specified element via JSON Pointer 23822 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 23823 const_reference operator[](const json_pointer& ptr) const 23824 { 23825 return ptr.get_unchecked(this); 23826 } 23827 23828 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23829 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23830 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 23831 { 23832 return ptr.get_unchecked(this); 23833 } 23834 23835 /// @brief access specified element via JSON Pointer 23836 /// @sa https://json.nlohmann.me/api/basic_json/at/ 23837 reference at(const json_pointer& ptr) 23838 { 23839 return ptr.get_checked(this); 23840 } 23841 23842 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23843 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23844 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) 23845 { 23846 return ptr.get_checked(this); 23847 } 23848 23849 /// @brief access specified element via JSON Pointer 23850 /// @sa https://json.nlohmann.me/api/basic_json/at/ 23851 const_reference at(const json_pointer& ptr) const 23852 { 23853 return ptr.get_checked(this); 23854 } 23855 23856 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23857 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23858 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 23859 { 23860 return ptr.get_checked(this); 23861 } 23862 23863 /// @brief return flattened JSON value 23864 /// @sa https://json.nlohmann.me/api/basic_json/flatten/ 23865 basic_json flatten() const 23866 { 23867 basic_json result(value_t::object); 23868 json_pointer::flatten("", *this, result); 23869 return result; 23870 } 23871 23872 /// @brief unflatten a previously flattened JSON value 23873 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/ 23874 basic_json unflatten() const 23875 { 23876 return json_pointer::unflatten(*this); 23877 } 23878 23879 /// @} 23880 23881 ////////////////////////// 23882 // JSON Patch functions // 23883 ////////////////////////// 23884 23885 /// @name JSON Patch functions 23886 /// @{ 23887 23888 /// @brief applies a JSON patch in-place without copying the object 23889 /// @sa https://json.nlohmann.me/api/basic_json/patch/ 23890 void patch_inplace(const basic_json& json_patch) 23891 { 23892 basic_json& result = *this; 23893 // the valid JSON Patch operations 23894 enum class patch_operations {add, remove, replace, move, copy, test, invalid}; 23895 23896 const auto get_op = [](const std::string & op) 23897 { 23898 if (op == "add") 23899 { 23900 return patch_operations::add; 23901 } 23902 if (op == "remove") 23903 { 23904 return patch_operations::remove; 23905 } 23906 if (op == "replace") 23907 { 23908 return patch_operations::replace; 23909 } 23910 if (op == "move") 23911 { 23912 return patch_operations::move; 23913 } 23914 if (op == "copy") 23915 { 23916 return patch_operations::copy; 23917 } 23918 if (op == "test") 23919 { 23920 return patch_operations::test; 23921 } 23922 23923 return patch_operations::invalid; 23924 }; 23925 23926 // wrapper for "add" operation; add value at ptr 23927 const auto operation_add = [&result](json_pointer & ptr, basic_json val) 23928 { 23929 // adding to the root of the target document means replacing it 23930 if (ptr.empty()) 23931 { 23932 result = val; 23933 return; 23934 } 23935 23936 // make sure the top element of the pointer exists 23937 json_pointer const top_pointer = ptr.top(); 23938 if (top_pointer != ptr) 23939 { 23940 result.at(top_pointer); 23941 } 23942 23943 // get reference to parent of JSON pointer ptr 23944 const auto last_path = ptr.back(); 23945 ptr.pop_back(); 23946 // parent must exist when performing patch add per RFC6902 specs 23947 basic_json& parent = result.at(ptr); 23948 23949 switch (parent.m_type) 23950 { 23951 case value_t::null: 23952 case value_t::object: 23953 { 23954 // use operator[] to add value 23955 parent[last_path] = val; 23956 break; 23957 } 23958 23959 case value_t::array: 23960 { 23961 if (last_path == "-") 23962 { 23963 // special case: append to back 23964 parent.push_back(val); 23965 } 23966 else 23967 { 23968 const auto idx = json_pointer::template array_index<basic_json_t>(last_path); 23969 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) 23970 { 23971 // avoid undefined behavior 23972 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent)); 23973 } 23974 23975 // default case: insert add offset 23976 parent.insert(parent.begin() + static_cast<difference_type>(idx), val); 23977 } 23978 break; 23979 } 23980 23981 // if there exists a parent it cannot be primitive 23982 case value_t::string: // LCOV_EXCL_LINE 23983 case value_t::boolean: // LCOV_EXCL_LINE 23984 case value_t::number_integer: // LCOV_EXCL_LINE 23985 case value_t::number_unsigned: // LCOV_EXCL_LINE 23986 case value_t::number_float: // LCOV_EXCL_LINE 23987 case value_t::binary: // LCOV_EXCL_LINE 23988 case value_t::discarded: // LCOV_EXCL_LINE 23989 default: // LCOV_EXCL_LINE 23990 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 23991 } 23992 }; 23993 23994 // wrapper for "remove" operation; remove value at ptr 23995 const auto operation_remove = [this, &result](json_pointer & ptr) 23996 { 23997 // get reference to parent of JSON pointer ptr 23998 const auto last_path = ptr.back(); 23999 ptr.pop_back(); 24000 basic_json& parent = result.at(ptr); 24001 24002 // remove child 24003 if (parent.is_object()) 24004 { 24005 // perform range check 24006 auto it = parent.find(last_path); 24007 if (JSON_HEDLEY_LIKELY(it != parent.end())) 24008 { 24009 parent.erase(it); 24010 } 24011 else 24012 { 24013 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this)); 24014 } 24015 } 24016 else if (parent.is_array()) 24017 { 24018 // note erase performs range check 24019 parent.erase(json_pointer::template array_index<basic_json_t>(last_path)); 24020 } 24021 }; 24022 24023 // type check: top level value must be an array 24024 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) 24025 { 24026 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch)); 24027 } 24028 24029 // iterate and apply the operations 24030 for (const auto& val : json_patch) 24031 { 24032 // wrapper to get a value for an operation 24033 const auto get_value = [&val](const std::string & op, 24034 const std::string & member, 24035 bool string_type) -> basic_json & 24036 { 24037 // find value 24038 auto it = val.m_value.object->find(member); 24039 24040 // context-sensitive error message 24041 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); 24042 24043 // check if desired value is present 24044 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) 24045 { 24046 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24047 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); 24048 } 24049 24050 // check if result is of type string 24051 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) 24052 { 24053 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24054 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val)); 24055 } 24056 24057 // no error: return value 24058 return it->second; 24059 }; 24060 24061 // type check: every element of the array must be an object 24062 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) 24063 { 24064 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val)); 24065 } 24066 24067 // collect mandatory members 24068 const auto op = get_value("op", "op", true).template get<std::string>(); 24069 const auto path = get_value(op, "path", true).template get<std::string>(); 24070 json_pointer ptr(path); 24071 24072 switch (get_op(op)) 24073 { 24074 case patch_operations::add: 24075 { 24076 operation_add(ptr, get_value("add", "value", false)); 24077 break; 24078 } 24079 24080 case patch_operations::remove: 24081 { 24082 operation_remove(ptr); 24083 break; 24084 } 24085 24086 case patch_operations::replace: 24087 { 24088 // the "path" location must exist - use at() 24089 result.at(ptr) = get_value("replace", "value", false); 24090 break; 24091 } 24092 24093 case patch_operations::move: 24094 { 24095 const auto from_path = get_value("move", "from", true).template get<std::string>(); 24096 json_pointer from_ptr(from_path); 24097 24098 // the "from" location must exist - use at() 24099 basic_json const v = result.at(from_ptr); 24100 24101 // The move operation is functionally identical to a 24102 // "remove" operation on the "from" location, followed 24103 // immediately by an "add" operation at the target 24104 // location with the value that was just removed. 24105 operation_remove(from_ptr); 24106 operation_add(ptr, v); 24107 break; 24108 } 24109 24110 case patch_operations::copy: 24111 { 24112 const auto from_path = get_value("copy", "from", true).template get<std::string>(); 24113 const json_pointer from_ptr(from_path); 24114 24115 // the "from" location must exist - use at() 24116 basic_json const v = result.at(from_ptr); 24117 24118 // The copy is functionally identical to an "add" 24119 // operation at the target location using the value 24120 // specified in the "from" member. 24121 operation_add(ptr, v); 24122 break; 24123 } 24124 24125 case patch_operations::test: 24126 { 24127 bool success = false; 24128 JSON_TRY 24129 { 24130 // check if "value" matches the one at "path" 24131 // the "path" location must exist - use at() 24132 success = (result.at(ptr) == get_value("test", "value", false)); 24133 } 24134 JSON_INTERNAL_CATCH (out_of_range&) 24135 { 24136 // ignore out of range errors: success remains false 24137 } 24138 24139 // throw an exception if test fails 24140 if (JSON_HEDLEY_UNLIKELY(!success)) 24141 { 24142 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val)); 24143 } 24144 24145 break; 24146 } 24147 24148 case patch_operations::invalid: 24149 default: 24150 { 24151 // op must be "add", "remove", "replace", "move", "copy", or 24152 // "test" 24153 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val)); 24154 } 24155 } 24156 } 24157 } 24158 24159 /// @brief applies a JSON patch to a copy of the current object 24160 /// @sa https://json.nlohmann.me/api/basic_json/patch/ 24161 basic_json patch(const basic_json& json_patch) const 24162 { 24163 basic_json result = *this; 24164 result.patch_inplace(json_patch); 24165 return result; 24166 } 24167 24168 /// @brief creates a diff as a JSON patch 24169 /// @sa https://json.nlohmann.me/api/basic_json/diff/ 24170 JSON_HEDLEY_WARN_UNUSED_RESULT 24171 static basic_json diff(const basic_json& source, const basic_json& target, 24172 const std::string& path = "") 24173 { 24174 // the patch 24175 basic_json result(value_t::array); 24176 24177 // if the values are the same, return empty patch 24178 if (source == target) 24179 { 24180 return result; 24181 } 24182 24183 if (source.type() != target.type()) 24184 { 24185 // different types: replace value 24186 result.push_back( 24187 { 24188 {"op", "replace"}, {"path", path}, {"value", target} 24189 }); 24190 return result; 24191 } 24192 24193 switch (source.type()) 24194 { 24195 case value_t::array: 24196 { 24197 // first pass: traverse common elements 24198 std::size_t i = 0; 24199 while (i < source.size() && i < target.size()) 24200 { 24201 // recursive call to compare array values at index i 24202 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); 24203 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 24204 ++i; 24205 } 24206 24207 // We now reached the end of at least one array 24208 // in a second pass, traverse the remaining elements 24209 24210 // remove my remaining elements 24211 const auto end_index = static_cast<difference_type>(result.size()); 24212 while (i < source.size()) 24213 { 24214 // add operations in reverse order to avoid invalid 24215 // indices 24216 result.insert(result.begin() + end_index, object( 24217 { 24218 {"op", "remove"}, 24219 {"path", detail::concat(path, '/', std::to_string(i))} 24220 })); 24221 ++i; 24222 } 24223 24224 // add other remaining elements 24225 while (i < target.size()) 24226 { 24227 result.push_back( 24228 { 24229 {"op", "add"}, 24230 {"path", detail::concat(path, "/-")}, 24231 {"value", target[i]} 24232 }); 24233 ++i; 24234 } 24235 24236 break; 24237 } 24238 24239 case value_t::object: 24240 { 24241 // first pass: traverse this object's elements 24242 for (auto it = source.cbegin(); it != source.cend(); ++it) 24243 { 24244 // escape the key name to be used in a JSON patch 24245 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 24246 24247 if (target.find(it.key()) != target.end()) 24248 { 24249 // recursive call to compare object values at key it 24250 auto temp_diff = diff(it.value(), target[it.key()], path_key); 24251 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 24252 } 24253 else 24254 { 24255 // found a key that is not in o -> remove it 24256 result.push_back(object( 24257 { 24258 {"op", "remove"}, {"path", path_key} 24259 })); 24260 } 24261 } 24262 24263 // second pass: traverse other object's elements 24264 for (auto it = target.cbegin(); it != target.cend(); ++it) 24265 { 24266 if (source.find(it.key()) == source.end()) 24267 { 24268 // found a key that is not in this -> add it 24269 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 24270 result.push_back( 24271 { 24272 {"op", "add"}, {"path", path_key}, 24273 {"value", it.value()} 24274 }); 24275 } 24276 } 24277 24278 break; 24279 } 24280 24281 case value_t::null: 24282 case value_t::string: 24283 case value_t::boolean: 24284 case value_t::number_integer: 24285 case value_t::number_unsigned: 24286 case value_t::number_float: 24287 case value_t::binary: 24288 case value_t::discarded: 24289 default: 24290 { 24291 // both primitive type: replace value 24292 result.push_back( 24293 { 24294 {"op", "replace"}, {"path", path}, {"value", target} 24295 }); 24296 break; 24297 } 24298 } 24299 24300 return result; 24301 } 24302 /// @} 24303 24304 //////////////////////////////// 24305 // JSON Merge Patch functions // 24306 //////////////////////////////// 24307 24308 /// @name JSON Merge Patch functions 24309 /// @{ 24310 24311 /// @brief applies a JSON Merge Patch 24312 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ 24313 void merge_patch(const basic_json& apply_patch) 24314 { 24315 if (apply_patch.is_object()) 24316 { 24317 if (!is_object()) 24318 { 24319 *this = object(); 24320 } 24321 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) 24322 { 24323 if (it.value().is_null()) 24324 { 24325 erase(it.key()); 24326 } 24327 else 24328 { 24329 operator[](it.key()).merge_patch(it.value()); 24330 } 24331 } 24332 } 24333 else 24334 { 24335 *this = apply_patch; 24336 } 24337 } 24338 24339 /// @} 24340 }; 24341 24342 /// @brief user-defined to_string function for JSON values 24343 /// @sa https://json.nlohmann.me/api/basic_json/to_string/ 24344 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24345 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) 24346 { 24347 return j.dump(); 24348 } 24349 24350 inline namespace literals 24351 { 24352 inline namespace json_literals 24353 { 24354 24355 /// @brief user-defined string literal for JSON values 24356 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ 24357 JSON_HEDLEY_NON_NULL(1) 24358 inline nlohmann::json operator "" _json(const char* s, std::size_t n) 24359 { 24360 return nlohmann::json::parse(s, s + n); 24361 } 24362 24363 /// @brief user-defined string literal for JSON pointer 24364 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ 24365 JSON_HEDLEY_NON_NULL(1) 24366 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) 24367 { 24368 return nlohmann::json::json_pointer(std::string(s, n)); 24369 } 24370 24371 } // namespace json_literals 24372 } // namespace literals 24373 NLOHMANN_JSON_NAMESPACE_END 24374 24375 /////////////////////// 24376 // nonmember support // 24377 /////////////////////// 24378 24379 namespace std // NOLINT(cert-dcl58-cpp) 24380 { 24381 24382 /// @brief hash value for JSON objects 24383 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ 24384 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24385 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp) 24386 { 24387 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const 24388 { 24389 return nlohmann::detail::hash(j); 24390 } 24391 }; 24392 24393 // specialization for std::less<value_t> 24394 template<> 24395 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 24396 { 24397 /*! 24398 @brief compare two value_t enum values 24399 @since version 3.0.0 24400 */ 24401 bool operator()(::nlohmann::detail::value_t lhs, 24402 ::nlohmann::detail::value_t rhs) const noexcept 24403 { 24404 #if JSON_HAS_THREE_WAY_COMPARISON 24405 return std::is_lt(lhs <=> rhs); // *NOPAD* 24406 #else 24407 return ::nlohmann::detail::operator<(lhs, rhs); 24408 #endif 24409 } 24410 }; 24411 24412 // C++20 prohibit function specialization in the std namespace. 24413 #ifndef JSON_HAS_CPP_20 24414 24415 /// @brief exchanges the values of two JSON objects 24416 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ 24417 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24418 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) 24419 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression) 24420 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value) 24421 { 24422 j1.swap(j2); 24423 } 24424 24425 #endif 24426 24427 } // namespace std 24428 24429 #if JSON_USE_GLOBAL_UDLS 24430 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24431 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24432 #endif 24433 24434 // #include <nlohmann/detail/macro_unscope.hpp> 24435 // __ _____ _____ _____ 24436 // __| | __| | | | JSON for Modern C++ 24437 // | | |__ | | | | | | version 3.11.2 24438 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 24439 // 24440 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 24441 // SPDX-License-Identifier: MIT 24442 24443 24444 24445 // restore clang diagnostic settings 24446 #if defined(__clang__) 24447 #pragma clang diagnostic pop 24448 #endif 24449 24450 // clean up 24451 #undef JSON_ASSERT 24452 #undef JSON_INTERNAL_CATCH 24453 #undef JSON_THROW 24454 #undef JSON_PRIVATE_UNLESS_TESTED 24455 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION 24456 #undef NLOHMANN_BASIC_JSON_TPL 24457 #undef JSON_EXPLICIT 24458 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL 24459 #undef JSON_INLINE_VARIABLE 24460 #undef JSON_NO_UNIQUE_ADDRESS 24461 #undef JSON_DISABLE_ENUM_SERIALIZATION 24462 #undef JSON_USE_GLOBAL_UDLS 24463 24464 #ifndef JSON_TEST_KEEP_MACROS 24465 #undef JSON_CATCH 24466 #undef JSON_TRY 24467 #undef JSON_HAS_CPP_11 24468 #undef JSON_HAS_CPP_14 24469 #undef JSON_HAS_CPP_17 24470 #undef JSON_HAS_CPP_20 24471 #undef JSON_HAS_FILESYSTEM 24472 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 24473 #undef JSON_HAS_THREE_WAY_COMPARISON 24474 #undef JSON_HAS_RANGES 24475 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 24476 #endif 24477 24478 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> 24479 // __ _____ _____ _____ 24480 // __| | __| | | | JSON for Modern C++ 24481 // | | |__ | | | | | | version 3.11.2 24482 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 24483 // 24484 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 24485 // SPDX-License-Identifier: MIT 24486 24487 24488 24489 #undef JSON_HEDLEY_ALWAYS_INLINE 24490 #undef JSON_HEDLEY_ARM_VERSION 24491 #undef JSON_HEDLEY_ARM_VERSION_CHECK 24492 #undef JSON_HEDLEY_ARRAY_PARAM 24493 #undef JSON_HEDLEY_ASSUME 24494 #undef JSON_HEDLEY_BEGIN_C_DECLS 24495 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 24496 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN 24497 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 24498 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 24499 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION 24500 #undef JSON_HEDLEY_CLANG_HAS_FEATURE 24501 #undef JSON_HEDLEY_CLANG_HAS_WARNING 24502 #undef JSON_HEDLEY_COMPCERT_VERSION 24503 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 24504 #undef JSON_HEDLEY_CONCAT 24505 #undef JSON_HEDLEY_CONCAT3 24506 #undef JSON_HEDLEY_CONCAT3_EX 24507 #undef JSON_HEDLEY_CONCAT_EX 24508 #undef JSON_HEDLEY_CONST 24509 #undef JSON_HEDLEY_CONSTEXPR 24510 #undef JSON_HEDLEY_CONST_CAST 24511 #undef JSON_HEDLEY_CPP_CAST 24512 #undef JSON_HEDLEY_CRAY_VERSION 24513 #undef JSON_HEDLEY_CRAY_VERSION_CHECK 24514 #undef JSON_HEDLEY_C_DECL 24515 #undef JSON_HEDLEY_DEPRECATED 24516 #undef JSON_HEDLEY_DEPRECATED_FOR 24517 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 24518 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 24519 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 24520 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 24521 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 24522 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 24523 #undef JSON_HEDLEY_DIAGNOSTIC_POP 24524 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH 24525 #undef JSON_HEDLEY_DMC_VERSION 24526 #undef JSON_HEDLEY_DMC_VERSION_CHECK 24527 #undef JSON_HEDLEY_EMPTY_BASES 24528 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION 24529 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 24530 #undef JSON_HEDLEY_END_C_DECLS 24531 #undef JSON_HEDLEY_FLAGS 24532 #undef JSON_HEDLEY_FLAGS_CAST 24533 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 24534 #undef JSON_HEDLEY_GCC_HAS_BUILTIN 24535 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 24536 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 24537 #undef JSON_HEDLEY_GCC_HAS_EXTENSION 24538 #undef JSON_HEDLEY_GCC_HAS_FEATURE 24539 #undef JSON_HEDLEY_GCC_HAS_WARNING 24540 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 24541 #undef JSON_HEDLEY_GCC_VERSION 24542 #undef JSON_HEDLEY_GCC_VERSION_CHECK 24543 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 24544 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN 24545 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 24546 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 24547 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION 24548 #undef JSON_HEDLEY_GNUC_HAS_FEATURE 24549 #undef JSON_HEDLEY_GNUC_HAS_WARNING 24550 #undef JSON_HEDLEY_GNUC_VERSION 24551 #undef JSON_HEDLEY_GNUC_VERSION_CHECK 24552 #undef JSON_HEDLEY_HAS_ATTRIBUTE 24553 #undef JSON_HEDLEY_HAS_BUILTIN 24554 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 24555 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 24556 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 24557 #undef JSON_HEDLEY_HAS_EXTENSION 24558 #undef JSON_HEDLEY_HAS_FEATURE 24559 #undef JSON_HEDLEY_HAS_WARNING 24560 #undef JSON_HEDLEY_IAR_VERSION 24561 #undef JSON_HEDLEY_IAR_VERSION_CHECK 24562 #undef JSON_HEDLEY_IBM_VERSION 24563 #undef JSON_HEDLEY_IBM_VERSION_CHECK 24564 #undef JSON_HEDLEY_IMPORT 24565 #undef JSON_HEDLEY_INLINE 24566 #undef JSON_HEDLEY_INTEL_CL_VERSION 24567 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 24568 #undef JSON_HEDLEY_INTEL_VERSION 24569 #undef JSON_HEDLEY_INTEL_VERSION_CHECK 24570 #undef JSON_HEDLEY_IS_CONSTANT 24571 #undef JSON_HEDLEY_IS_CONSTEXPR_ 24572 #undef JSON_HEDLEY_LIKELY 24573 #undef JSON_HEDLEY_MALLOC 24574 #undef JSON_HEDLEY_MCST_LCC_VERSION 24575 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 24576 #undef JSON_HEDLEY_MESSAGE 24577 #undef JSON_HEDLEY_MSVC_VERSION 24578 #undef JSON_HEDLEY_MSVC_VERSION_CHECK 24579 #undef JSON_HEDLEY_NEVER_INLINE 24580 #undef JSON_HEDLEY_NON_NULL 24581 #undef JSON_HEDLEY_NO_ESCAPE 24582 #undef JSON_HEDLEY_NO_RETURN 24583 #undef JSON_HEDLEY_NO_THROW 24584 #undef JSON_HEDLEY_NULL 24585 #undef JSON_HEDLEY_PELLES_VERSION 24586 #undef JSON_HEDLEY_PELLES_VERSION_CHECK 24587 #undef JSON_HEDLEY_PGI_VERSION 24588 #undef JSON_HEDLEY_PGI_VERSION_CHECK 24589 #undef JSON_HEDLEY_PREDICT 24590 #undef JSON_HEDLEY_PRINTF_FORMAT 24591 #undef JSON_HEDLEY_PRIVATE 24592 #undef JSON_HEDLEY_PUBLIC 24593 #undef JSON_HEDLEY_PURE 24594 #undef JSON_HEDLEY_REINTERPRET_CAST 24595 #undef JSON_HEDLEY_REQUIRE 24596 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR 24597 #undef JSON_HEDLEY_REQUIRE_MSG 24598 #undef JSON_HEDLEY_RESTRICT 24599 #undef JSON_HEDLEY_RETURNS_NON_NULL 24600 #undef JSON_HEDLEY_SENTINEL 24601 #undef JSON_HEDLEY_STATIC_ASSERT 24602 #undef JSON_HEDLEY_STATIC_CAST 24603 #undef JSON_HEDLEY_STRINGIFY 24604 #undef JSON_HEDLEY_STRINGIFY_EX 24605 #undef JSON_HEDLEY_SUNPRO_VERSION 24606 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 24607 #undef JSON_HEDLEY_TINYC_VERSION 24608 #undef JSON_HEDLEY_TINYC_VERSION_CHECK 24609 #undef JSON_HEDLEY_TI_ARMCL_VERSION 24610 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 24611 #undef JSON_HEDLEY_TI_CL2000_VERSION 24612 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 24613 #undef JSON_HEDLEY_TI_CL430_VERSION 24614 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 24615 #undef JSON_HEDLEY_TI_CL6X_VERSION 24616 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 24617 #undef JSON_HEDLEY_TI_CL7X_VERSION 24618 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 24619 #undef JSON_HEDLEY_TI_CLPRU_VERSION 24620 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 24621 #undef JSON_HEDLEY_TI_VERSION 24622 #undef JSON_HEDLEY_TI_VERSION_CHECK 24623 #undef JSON_HEDLEY_UNAVAILABLE 24624 #undef JSON_HEDLEY_UNLIKELY 24625 #undef JSON_HEDLEY_UNPREDICTABLE 24626 #undef JSON_HEDLEY_UNREACHABLE 24627 #undef JSON_HEDLEY_UNREACHABLE_RETURN 24628 #undef JSON_HEDLEY_VERSION 24629 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR 24630 #undef JSON_HEDLEY_VERSION_DECODE_MINOR 24631 #undef JSON_HEDLEY_VERSION_DECODE_REVISION 24632 #undef JSON_HEDLEY_VERSION_ENCODE 24633 #undef JSON_HEDLEY_WARNING 24634 #undef JSON_HEDLEY_WARN_UNUSED_RESULT 24635 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 24636 #undef JSON_HEDLEY_FALL_THROUGH 24637 24638 24639 24640 #endif // INCLUDE_NLOHMANN_JSON_HPP_